diff --git a/README.rst b/README.rst index 4db2806..baf2652 100644 --- a/README.rst +++ b/README.rst @@ -28,8 +28,9 @@ More details about Py-BOBYQA and its enhancements over BOBYQA can be found in ou 1. Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, `Improving the Flexibility and Robustness of Model-Based Derivative-Free Optimization Solvers `_, *ACM Transactions on Mathematical Software*, 45:3 (2019), pp. 32:1-32:41 [`arXiv preprint: 1804.00154 `_] 2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +3. Lindon Roberts, `Model Construction for Convex-Constrained Derivative-Free Optimization `_, *arXiv preprint arXiv:2403.14960* (2024). -Please cite [1] when using Py-BOBYQA for local optimization, and [1,2] when using Py-BOBYQA's global optimization heuristic functionality. For reproducibility of all figures, please feel free to contact the authors. +Please cite [1] when using Py-BOBYQA for local optimization, [1,2] when using Py-BOBYQA's global optimization heuristic functionality, and [1,3] if using the general convex constraints functionality. The original paper by Powell is: M. J. D. Powell, The BOBYQA algorithm for bound constrained optimization without derivatives, technical report DAMTP 2009/NA06, University of Cambridge (2009), and the original Fortran implementation is available `here `_. @@ -41,13 +42,13 @@ See manual.pdf or the `online manual `_, *ACM Transactions on Mathematical Software*, 45:3 (2019), pp. 32:1-32:41 [`preprint `_] +2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +3. Lindon Roberts, `Model Construction for Convex-Constrained Derivative-Free Optimization `_, *arXiv preprint arXiv:2403.14960* (2024). -If you use Py-BOBYQA's global optimization heuristic, please cite the above and also - -Cartis, C., Roberts, L. and Sheridan-Methven, O., Escaping local minima with derivative-free methods: a numerical investigation, Optimization, 71:8 (2022), pp. 2343-2373. +Please cite [1] when using Py-BOBYQA for local optimization, [1,2] when using Py-BOBYQA's global optimization heuristic functionality, and [1,3] if using the general convex constraints functionality. Requirements ------------ @@ -65,31 +66,17 @@ Additionally, the following python packages should be installed (these will be i Installation using pip ---------------------- -For easy installation, use `pip `_ as root: - - .. code-block:: bash - - $ [sudo] pip install Py-BOBYQA - -or alternatively *easy_install*: - - .. code-block:: bash - - $ [sudo] easy_install Py-BOBYQA - -If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use: +For easy installation, use `pip `_: .. code-block:: bash - $ pip install --user Py-BOBYQA - -which will install Py-BOBYQA in your home directory. + $ pip install Py-BOBYQA Note that if an older install of Py-BOBYQA is present on your system you can use: .. code-block:: bash - $ [sudo] pip install --upgrade Py-BOBYQA + $ pip install --upgrade Py-BOBYQA to upgrade Py-BOBYQA to the latest version. @@ -106,13 +93,7 @@ Py-BOBYQA is written in pure Python and requires no compilation. It can be insta .. code-block:: bash - $ [sudo] pip install . - -If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use: - - .. code-block:: bash - - $ pip install --user . + $ pip install . instead. @@ -121,7 +102,7 @@ To upgrade Py-BOBYQA to the latest version, navigate to the top-level directory .. code-block:: bash $ git pull - $ [sudo] pip install . # with admin privileges + $ pip install . Testing ------- @@ -144,7 +125,7 @@ If Py-BOBYQA was installed using *pip* you can uninstall as follows: .. code-block:: bash - $ [sudo] pip uninstall Py-BOBYQA + $ pip uninstall Py-BOBYQA If Py-BOBYQA was installed manually you have to remove the installed files by hand (located in your python site-packages directory). diff --git a/docs/advanced.rst b/docs/advanced.rst index 7ba922b..04dfd07 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -21,9 +21,9 @@ Logging and Output Initialization of Points ------------------------ -* :code:`init.random_initial_directions` - Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is :code:`True`. -* :code:`init.random_directions_make_orthogonal` - If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is :code:`True`. -* :code:`init.run_in_parallel` - If using random directions, whether or not to ask for all :code:`objfun` to be evaluated at all points without any intermediate processing. Default is :code:`False`. +* :code:`init.random_initial_directions` - Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is :code:`True`. Not used if general convex constraints provided. +* :code:`init.random_directions_make_orthogonal` - If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is :code:`True`. Not used if general convex constraints provided. +* :code:`init.run_in_parallel` - If using random directions, whether or not to ask for all :code:`objfun` to be evaluated at all points without any intermediate processing. Default is :code:`False`. Not used if general convex constraints provided. Trust Region Management ----------------------- @@ -74,6 +74,12 @@ Multiple Restarts * :code:`restarts.auto_detect.min_chg_model_slope` - Minimum rate of increase of :math:`\log(\|g_k-g_{k-1}\|)` and :math:`\log(\|H_k-H_{k-1}\|_F)` over the past iterations to cause a restart. Default is 0.015. * :code:`restarts.auto_detect.min_correl` - Minimum correlation of the data sets :math:`(k, \log(\|g_k-g_{k-1}\|))` and :math:`(k, \log(\|H_k-H_{k-1}\|_F))` required to cause a restart. Default is 0.1. +General Convex Constraints +-------------------------- +* :code:`projections.dykstra.d_tol` - termination tolerance for Dykstra's algorithm for computing the projection onto the intersection of all convex constraints. Default is :math:`10^{-10}`. +* :code:`projections.dykstra.max_iters` - maximum iterations of Dykstra's algorithm for computing the projection onto the intersection of all convex constraints. Default is 100. +* :code:`projections.feasible_tol` - tolerance for checking feasibility of initial points with respect to general convex constraints. Default is :math:`10^{-10}`. +* :code:`projections.pgd_tol` - termination tolerance for trust-region and geometry-improving subproblems. Default is :math:`10^{-8}`. References ---------- diff --git a/docs/build/doctrees/advanced.doctree b/docs/build/doctrees/advanced.doctree index 52d8896..82c78fe 100644 Binary files a/docs/build/doctrees/advanced.doctree and b/docs/build/doctrees/advanced.doctree differ diff --git a/docs/build/doctrees/diagnostic.doctree b/docs/build/doctrees/diagnostic.doctree index dfa010a..e6c8f32 100644 Binary files a/docs/build/doctrees/diagnostic.doctree and b/docs/build/doctrees/diagnostic.doctree differ diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index 5be51ff..6273742 100644 Binary files a/docs/build/doctrees/environment.pickle and b/docs/build/doctrees/environment.pickle differ diff --git a/docs/build/doctrees/history.doctree b/docs/build/doctrees/history.doctree index 5e14dcc..c709bfc 100644 Binary files a/docs/build/doctrees/history.doctree and b/docs/build/doctrees/history.doctree differ diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree index 03fb5c6..f3d00df 100644 Binary files a/docs/build/doctrees/index.doctree and b/docs/build/doctrees/index.doctree differ diff --git a/docs/build/doctrees/info.doctree b/docs/build/doctrees/info.doctree index 3b754ac..f7676c4 100644 Binary files a/docs/build/doctrees/info.doctree and b/docs/build/doctrees/info.doctree differ diff --git a/docs/build/doctrees/install.doctree b/docs/build/doctrees/install.doctree index e6a7825..d2be799 100644 Binary files a/docs/build/doctrees/install.doctree and b/docs/build/doctrees/install.doctree differ diff --git a/docs/build/doctrees/userguide.doctree b/docs/build/doctrees/userguide.doctree index 4e2653b..75e8734 100644 Binary files a/docs/build/doctrees/userguide.doctree and b/docs/build/doctrees/userguide.doctree differ diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo index 6ddba6b..736dff4 100644 --- a/docs/build/html/.buildinfo +++ b/docs/build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 71b7b5e9dd47a27f370b73edfaf0d9fa +config: 23c30e3852e30f05e3745555cbeb2562 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_sources/advanced.rst.txt b/docs/build/html/_sources/advanced.rst.txt index 7ba922b..04dfd07 100644 --- a/docs/build/html/_sources/advanced.rst.txt +++ b/docs/build/html/_sources/advanced.rst.txt @@ -21,9 +21,9 @@ Logging and Output Initialization of Points ------------------------ -* :code:`init.random_initial_directions` - Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is :code:`True`. -* :code:`init.random_directions_make_orthogonal` - If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is :code:`True`. -* :code:`init.run_in_parallel` - If using random directions, whether or not to ask for all :code:`objfun` to be evaluated at all points without any intermediate processing. Default is :code:`False`. +* :code:`init.random_initial_directions` - Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is :code:`True`. Not used if general convex constraints provided. +* :code:`init.random_directions_make_orthogonal` - If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is :code:`True`. Not used if general convex constraints provided. +* :code:`init.run_in_parallel` - If using random directions, whether or not to ask for all :code:`objfun` to be evaluated at all points without any intermediate processing. Default is :code:`False`. Not used if general convex constraints provided. Trust Region Management ----------------------- @@ -74,6 +74,12 @@ Multiple Restarts * :code:`restarts.auto_detect.min_chg_model_slope` - Minimum rate of increase of :math:`\log(\|g_k-g_{k-1}\|)` and :math:`\log(\|H_k-H_{k-1}\|_F)` over the past iterations to cause a restart. Default is 0.015. * :code:`restarts.auto_detect.min_correl` - Minimum correlation of the data sets :math:`(k, \log(\|g_k-g_{k-1}\|))` and :math:`(k, \log(\|H_k-H_{k-1}\|_F))` required to cause a restart. Default is 0.1. +General Convex Constraints +-------------------------- +* :code:`projections.dykstra.d_tol` - termination tolerance for Dykstra's algorithm for computing the projection onto the intersection of all convex constraints. Default is :math:`10^{-10}`. +* :code:`projections.dykstra.max_iters` - maximum iterations of Dykstra's algorithm for computing the projection onto the intersection of all convex constraints. Default is 100. +* :code:`projections.feasible_tol` - tolerance for checking feasibility of initial points with respect to general convex constraints. Default is :math:`10^{-10}`. +* :code:`projections.pgd_tol` - termination tolerance for trust-region and geometry-improving subproblems. Default is :math:`10^{-8}`. References ---------- diff --git a/docs/build/html/_sources/history.rst.txt b/docs/build/html/_sources/history.rst.txt index 803d6f9..eee4b55 100644 --- a/docs/build/html/_sources/history.rst.txt +++ b/docs/build/html/_sources/history.rst.txt @@ -48,6 +48,10 @@ Version 1.4 (16 May 2023) * Bugfix: reset slow iteration counter when doing soft restarts Version 1.4.1 (11 Apr 2024) -------------------------- +--------------------------- * Migrate package setup to pyproject.toml (required for Python version 3.12) * Drop support for Python 2.7 and <=3.7 due to new setup process + +Version 1.5.0 (16 Sep 2024) +--------------------------- +* Added support for general convex constraints diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt index f0ec695..4b54d60 100644 --- a/docs/build/html/_sources/index.rst.txt +++ b/docs/build/html/_sources/index.rst.txt @@ -12,23 +12,26 @@ Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization **Author:** `Lindon Roberts `_ -Py-BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound constraints), without requiring any derivatives of the objective. Py-BOBYQA is a Python implementation of the `BOBYQA `_ solver by Powell (documentation `here `_). It is particularly useful when evaluations of the objective function are expensive and/or noisy. +Py-BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound and other convex constraints), without requiring any derivatives of the objective. Py-BOBYQA is a Python implementation of the `BOBYQA `_ solver by Powell (documentation `here `_). It is particularly useful when evaluations of the objective function are expensive and/or noisy. That is, Py-BOBYQA solves .. math:: \min_{x\in\mathbb{R}^n} &\quad f(x)\\ - \text{s.t.} &\quad a \leq x \leq b + \text{s.t.} &\quad a \leq x \leq b \\ + &\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex} -The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). +If provided, the constraints the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds), +although the general :math:`x \in C` constraint may be slightly violated from rounding errors. Full details of the Py-BOBYQA algorithm are given in our papers: 1. Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, `Improving the Flexibility and Robustness of Model-Based Derivative-Free Optimization Solvers `_, *ACM Transactions on Mathematical Software*, 45:3 (2019), pp. 32:1-32:41 [`preprint `_] -2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +3. Lindon Roberts, `Model Construction for Convex-Constrained Derivative-Free Optimization `_, *arXiv preprint arXiv:2403.14960* (2024). -Please cite [1] when using Py-BOBYQA for local optimization, and [1,2] when using Py-BOBYQA's global optimization heuristic functionality. +Please cite [1] when using Py-BOBYQA for local optimization, [1,2] when using Py-BOBYQA's global optimization heuristic functionality, and [1,3] if using the general convex constraints :math:`x \in C` functionality. If you are interested in solving least-squares minimization problems, you may wish to try `DFO-LS `_, which has the same features as Py-BOBYQA (plus some more), and exploits the least-squares problem structure, so performs better on such problems. @@ -49,5 +52,6 @@ Py-BOBYQA is released under the GNU General Public License. Please `contact NAG Acknowledgements ---------------- -This software was developed under the supervision of `Coralia Cartis `_, and was supported by the EPSRC Centre For Doctoral Training in `Industrially Focused Mathematical Modelling `_ (EP/L015803/1) in collaboration with the `Numerical Algorithms Group `_. +This software was initially developed under the supervision of `Coralia Cartis `_, and was supported by the EPSRC Centre For Doctoral Training in `Industrially Focused Mathematical Modelling `_ (EP/L015803/1) in collaboration with the `Numerical Algorithms Group `_. +Development of Py-BOBYQA has also been supported by the Australian Research Council (DE240100006). diff --git a/docs/build/html/_sources/info.rst.txt b/docs/build/html/_sources/info.rst.txt index 4b60412..c289ad9 100644 --- a/docs/build/html/_sources/info.rst.txt +++ b/docs/build/html/_sources/info.rst.txt @@ -3,12 +3,13 @@ Overview When to use Py-BOBYQA --------------------- -Py-BOBYQA is designed to solve the nonlinear least-squares minimization problem (with optional bound constraints) +Py-BOBYQA is designed to solve the nonlinear least-squares minimization problem (with optional bound and general convex constraints) .. math:: \min_{x\in\mathbb{R}^n} &\quad f(x)\\ - \text{s.t.} &\quad a \leq x \leq b + \text{s.t.} &\quad a \leq x \leq b\\ + &\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex} We call :math:`f(x)` the objective function. diff --git a/docs/build/html/_sources/install.rst.txt b/docs/build/html/_sources/install.rst.txt index 94454c0..08a638c 100644 --- a/docs/build/html/_sources/install.rst.txt +++ b/docs/build/html/_sources/install.rst.txt @@ -17,25 +17,17 @@ Additionally, the following python packages should be installed (these will be i Installation using pip ---------------------- -For easy installation, use `pip `_ as root: +For easy installation, use `pip `_: .. code-block:: bash - $ [sudo] pip install Py-BOBYQA - -If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use: - - .. code-block:: bash - - $ pip install --user Py-BOBYQA - -which will install Py-BOBYQA in your home directory. + $ pip install Py-BOBYQA Note that if an older install of Py-BOBYQA is present on your system you can use: .. code-block:: bash - $ [sudo] pip install --upgrade Py-BOBYQA + $ pip install --upgrade Py-BOBYQA to upgrade Py-BOBYQA to the latest version. @@ -52,22 +44,14 @@ Py-BOBYQA is written in pure Python and requires no compilation. It can be insta .. code-block:: bash - $ [sudo] pip install . - -If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use: - - .. code-block:: bash - - $ pip install --user . - -instead. + $ pip install . To upgrade Py-BOBYQA to the latest version, navigate to the top-level directory (i.e. the one containing :code:`setup.py`) and rerun the installation using :code:`pip`, as above: .. code-block:: bash $ git pull - $ [sudo] pip install . # with admin privileges + $ pip install . Testing ------- @@ -84,7 +68,7 @@ If Py-BOBYQA was installed using `pip `_ you can .. code-block:: bash - $ [sudo] pip uninstall Py-BOBYQA + $ pip uninstall Py-BOBYQA If Py-BOBYQA was installed manually you have to remove the installed files by hand (located in your python site-packages directory). diff --git a/docs/build/html/_sources/userguide.rst.txt b/docs/build/html/_sources/userguide.rst.txt index b88d30e..5513874 100644 --- a/docs/build/html/_sources/userguide.rst.txt +++ b/docs/build/html/_sources/userguide.rst.txt @@ -9,12 +9,18 @@ Py-BOBYQA is designed to solve the local optimization problem .. math:: \min_{x\in\mathbb{R}^n} &\quad f(x) \\ - \text{s.t.} &\quad a \leq x \leq b + \text{s.t.} &\quad a \leq x \leq b\\ + &\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex} -where the bound constraints :math:`a \leq x \leq b` are optional. The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). The objective function :math:`f(x)` is usually nonlinear and nonquadratic. If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see `here `_ for details). +where the bound constraints :math:`a \leq x \leq b` and general convex constraints :math:`x \in C` are optional. +The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). +The general convex constraints are also non-relaxable, but they may be slightly violated at some points from rounding errors. +The objective function :math:`f(x)` is usually nonlinear and nonquadratic. +If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see `here `_ for details). Py-BOBYQA iteratively constructs an interpolation-based model for the objective, and determines a step using a trust-region framework. For an in-depth technical description of the algorithm see the paper [CFMR2018]_, and for the global optimization heuristic, see [CRO2022]_. +For details about how Py-BOBYQA handles general convex constraints, see [R2024]_. How to use Py-BOBYQA -------------------- @@ -65,17 +71,18 @@ The :code:`solve` function has several optional arguments which the user may pro .. code-block:: python - pybobyqa.solve(objfun, x0, args=(), bounds=None, npt=None, - rhobeg=None, rhoend=1e-8, maxfun=None, nsamples=None, - user_params=None, objfun_has_noise=False, - seek_global_minimum=False, - scaling_within_bounds=False, - do_logging=True, print_progress=False) + pybobyqa.solve(objfun, x0, args=(), bounds=None, projections=None, + npt=None, rhobeg=None, rhoend=1e-8, maxfun=None, + nsamples=None, user_params=None, objfun_has_noise=False, + seek_global_minimum=False, + scaling_within_bounds=False, + do_logging=True, print_progress=False) These arguments are: * :code:`args` - a tuple of extra arguments passed to the objective function. * :code:`bounds` - a tuple :code:`(lower, upper)` with the vectors :math:`a` and :math:`b` of lower and upper bounds on :math:`x` (default is :math:`a_i=-10^{20}` and :math:`b_i=10^{20}`). To set bounds for either :code:`lower` or :code:`upper`, but not both, pass a tuple :code:`(lower, None)` or :code:`(None, upper)`. +* :code:`projections` - a list of functions defining the Euclidean projections for each general convex constraint :math:`C_i`. Each element of the list :code:`projections` is a function that takes an input vector :math:`x` and returns the closest point to :math:`x` that is in :math:`C_i`. An example of using this is given below. * :code:`npt` - the number of interpolation points to use (default is :math:`2n+1` for a problem with :code:`len(x0)=n` if :code:`objfun_has_noise=False`, otherwise it is set to :math:`(n+1)(n+2)/2`). Py-BOBYQA requires :math:`n+1 \leq npt \leq (n+1)(n+2)/2`. Larger values are particularly useful for noisy problems. * :code:`rhobeg` - the initial value of the trust region radius (default is 0.1 if :code:`scaling_within_bounds=True`, otherwise :math:`0.1\max(\|x_0\|_{\infty}, 1)`). * :code:`rhoend` - minimum allowed value of trust region radius, which determines when a successful termination occurs (default is :math:`10^{-8}`). @@ -217,6 +224,81 @@ An alternative option available is to get Py-BOBYQA to print to terminal progres 1 132 1.00e-02 2.00e-01 1.50e-08 1.00e-08 144 1 133 1.00e-02 2.00e-01 1.50e-08 1.00e-08 145 +Adding General Convex Constraints +--------------------------------- +We can also add more general convex constraints :math:`x \in C := C_1 \cap \cdots \cap C_n` to our problem, where +each :math:`C_i` is a convex set. To do this, we need to know the Euclidean projection operator for each :math:`C_i`: + +.. math:: + + \operatorname{proj}_{C_i}(x) := \operatorname{argmin}_{y\in C_i} \|y-x\|_2^2. + +i.e. given a point :math:`x`, return the closest point to :math:`x` in the set :math:`C_i`. +There are many examples of simple convex sets :math:`C_i` for which this function has a known, simple form, such as: + +* Bound constraints (but since Py-BOBYQA supports this directly, it is better to give these explicitly via the :code:`bounds` input, as above) +* Euclidean ball constraints: :math:`\|x-c\|_2 \leq r` +* Unit simplex: :math:`x_i \geq 0` and :math:`\sum_{i=1}^{n} x_i \leq 1` +* Linear inequalities: :math:`a^T x \geq b` + +In Py-BOBYQA, set the input :code:`projections` to be a list of projection functions, one per :math:`C_i`. +Internally, Py-BOBYQA computes the projection onto the intersection of these sets and the bound constraints +using `Dykstra's projection algorithm `_. + +For the explicit expressions for the above projections, and more examples, see for example `this online database `_ +or Section 6.4.6 of the textbook [B2017]_. + +As an example, let's minimize the above Rosenbrock function with different bounds, and with a Euclidean +ball constraint, namely :math:`(x_1-0.5)^2 + (x_2-1)^2 \leq 0.25^2`. + +To do this, we can run + + .. code-block:: python + + import numpy as np + import pybobyqa + + # Define the objective function + def rosenbrock(x): + return 100.0 * (x[1] - x[0] ** 2) ** 2 + (1.0 - x[0]) ** 2 + + # Define the starting point + x0 = np.array([-1.2, 1.0]) + + # Define bound constraints (lower <= x <= upper) + lower = np.array([0.7, -2.0]) + upper = np.array([1.0, 2.0]) + + # Define the ball constraint ||x-center|| <= radius, and its projection operator + center = np.array([0.5, 1.0]) + radius = 0.25 + ball_proj = lambda x: center + (radius/max(np.linalg.norm(x-center), radius)) * (x-center) + + # Call Py-BOBYQA (with bounds and projection operator) + # Note: it is better to provide bounds explicitly, instead of using the corresponding + # projection function + # Note: input 'projections' must be a list of projection functions + soln = pybobyqa.solve(rosenbrock, x0, bounds=(lower,upper), projections=[ball_proj]) + + print(soln) + +Py-BOBYQA correctly finds the solution to the constrained problem: + + .. code-block:: none + + ****** Py-BOBYQA Results ****** + Solution xmin = [0.70424386 0.85583188] + Objective value f(xmin) = 13.03829114 + Needed 25 objective evaluations (at 25 points) + Approximate gradient = [-101.9667031 71.97449424] + Approximate Hessian = [[ 253.11858775 -279.39193327] + [-279.39193327 201.49725358]] + Exit flag = 0 + Success: rho has reached rhoend + ****************************** + +Just like for bound constraints, Py-BOBYQA will automatically ensure the starting point is feasible with respect to all constraints (bounds and general convex constraints). + Example: Noisy Objective Evaluation ----------------------------------- As described in :doc:`info`, derivative-free algorithms such as Py-BOBYQA are particularly useful when :code:`objfun` has noise. Let's modify the previous example to include random noise in our objective evaluation, and compare it to a derivative-based solver: @@ -411,3 +493,7 @@ References Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, `Improving the Flexibility and Robustness of Model-Based Derivative-Free Optimization Solvers `_, *ACM Transactions on Mathematical Software*, 45:3 (2019), pp. 32:1-32:41 [`preprint `_] .. [CRO2022] Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +.. [R2024] + Lindon Roberts, `Model Construction for Convex-Constrained Derivative-Free Optimization `_, *arXiv preprint arXiv:2403.14960* (2024). +.. [B2017] + Amir Beck, `First-Order Methods in Optimization `_, SIAM (2017). \ No newline at end of file diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css index 30fee9d..f316efc 100644 --- a/docs/build/html/_static/basic.css +++ b/docs/build/html/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js index d06a71d..4d67807 100644 --- a/docs/build/html/_static/doctools.js +++ b/docs/build/html/_static/doctools.js @@ -4,7 +4,7 @@ * * Base JavaScript utilities for all Sphinx HTML documentation. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js index dfba10e..f476d73 100644 --- a/docs/build/html/_static/documentation_options.js +++ b/docs/build/html/_static/documentation_options.js @@ -1,5 +1,5 @@ const DOCUMENTATION_OPTIONS = { - VERSION: '1.4.1', + VERSION: '1.5.0', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/docs/build/html/_static/language_data.js b/docs/build/html/_static/language_data.js index 250f566..367b8ed 100644 --- a/docs/build/html/_static/language_data.js +++ b/docs/build/html/_static/language_data.js @@ -5,7 +5,7 @@ * This script contains the language-specific data used by searchtools.js, * namely the list of stopwords, stemmer, scorer and splitter. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -13,7 +13,7 @@ var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; -/* Non-minified version is copied as a separate JS file, is available */ +/* Non-minified version is copied as a separate JS file, if available */ /** * Porter Stemmer diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js index 7918c3f..b08d58c 100644 --- a/docs/build/html/_static/searchtools.js +++ b/docs/build/html/_static/searchtools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -99,7 +99,7 @@ const _displayItem = (item, searchTerms, highlightTerms) => { .then((data) => { if (data) listItem.appendChild( - Search.makeSearchSummary(data, searchTerms) + Search.makeSearchSummary(data, searchTerms, anchor) ); // highlight search terms in the summary if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js @@ -116,8 +116,8 @@ const _finishSearch = (resultCount) => { ); else Search.status.innerText = _( - `Search finished, found ${resultCount} page(s) matching the search query.` - ); + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); }; const _displayNextItem = ( results, @@ -137,6 +137,22 @@ const _displayNextItem = ( // search finished, update title and status message else _finishSearch(resultCount); }; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; /** * Default splitQuery function. Can be overridden in ``sphinx.search`` with a @@ -160,13 +176,26 @@ const Search = { _queued_query: null, _pulse_status: -1, - htmlToText: (htmlString) => { + htmlToText: (htmlString, anchor) => { const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent !== undefined) return docContent.textContent; + if (docContent) return docContent.textContent; + console.warn( - "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." ); return ""; }, @@ -239,16 +268,7 @@ const Search = { else Search.deferQuery(query); }, - /** - * execute search (requires search index to be loaded) - */ - query: (query) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - + _parseQuery: (query) => { // stem the search terms and add them to the correct list const stemmer = new Stemmer(); const searchTerms = new Set(); @@ -284,21 +304,38 @@ const Search = { // console.info("required: ", [...searchTerms]); // console.info("excluded: ", [...excludedTerms]); - // array of [docname, title, anchor, descr, score, filename] - let results = []; + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + _removeChildren(document.getElementById("search-progress")); - const queryLower = query.toLowerCase(); + const queryLower = query.toLowerCase().trim(); for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { for (const [file, id] of foundTitles) { - let score = Math.round(100 * queryLower.length / title.length) - results.push([ + const score = Math.round(Scorer.title * queryLower.length / title.length); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ docNames[file], titles[file] !== title ? `${titles[file]} > ${title}` : title, id !== null ? "#" + id : "", null, - score, + score + boost, filenames[file], ]); } @@ -308,46 +345,47 @@ const Search = { // search for explicit entries in index directives for (const [entry, foundEntries] of Object.entries(indexEntries)) { if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id] of foundEntries) { - let score = Math.round(100 * queryLower.length / entry.length) - results.push([ + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ docNames[file], titles[file], id ? "#" + id : "", null, score, filenames[file], - ]); + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } } } } // lookup as object objectTerms.forEach((term) => - results.push(...Search.performObjectSearch(term, objectTerms)) + normalResults.push(...Search.performObjectSearch(term, objectTerms)) ); // lookup as search terms in fulltext - results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); // let the scorer override scores with a custom scoring function - if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); - - // now sort the results by score (in opposite order of appearance, since the - // display function below uses pop() to retrieve items) and then - // alphabetically - results.sort((a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; - }); + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; // remove duplicate search results // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept @@ -361,7 +399,12 @@ const Search = { return acc; }, []); - results = results.reverse(); + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); // for debugging //Search.lastresults = results.slice(); // a copy @@ -466,14 +509,18 @@ const Search = { // add support for partial matches if (word.length > 2) { const escapedWord = _escapeRegExp(word); - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord) && !terms[word]) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord) && !titleTerms[word]) - arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); - }); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } } // no match but word was a required one @@ -496,9 +543,8 @@ const Search = { // create the mapping files.forEach((file) => { - if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) - fileMap.get(file).push(word); - else fileMap.set(file, [word]); + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); }); }); @@ -549,8 +595,8 @@ const Search = { * search summary for a given text. keywords is a list * of stemmed words. */ - makeSearchSummary: (htmlText, keywords) => { - const text = Search.htmlToText(htmlText); + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); if (text === "") return null; const textLower = text.toLowerCase(); diff --git a/docs/build/html/advanced.html b/docs/build/html/advanced.html index 3857668..8332754 100644 --- a/docs/build/html/advanced.html +++ b/docs/build/html/advanced.html @@ -4,7 +4,7 @@ - Advanced Usage — Py-BOBYQA v1.4.1 documentation + Advanced Usage — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -38,7 +38,7 @@ Py-BOBYQA
- 1.4.1 + 1.5.0
@@ -63,6 +63,7 @@
  • Stochastic Noise Information
  • Interpolation Management
  • Multiple Restarts
  • +
  • General Convex Constraints
  • References
  • @@ -119,9 +120,9 @@

    Logging and Output

    Initialization of Points

      -
    • init.random_initial_directions - Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is True.

    • -
    • init.random_directions_make_orthogonal - If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is True.

    • -
    • init.run_in_parallel - If using random directions, whether or not to ask for all objfun to be evaluated at all points without any intermediate processing. Default is False.

    • +
    • init.random_initial_directions - Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is True. Not used if general convex constraints provided.

    • +
    • init.random_directions_make_orthogonal - If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is True. Not used if general convex constraints provided.

    • +
    • init.run_in_parallel - If using random directions, whether or not to ask for all objfun to be evaluated at all points without any intermediate processing. Default is False. Not used if general convex constraints provided.

    @@ -185,6 +186,15 @@

    Multiple Restartsrestarts.auto_detect.min_correl - Minimum correlation of the data sets \((k, \log(\|g_k-g_{k-1}\|))\) and \((k, \log(\|H_k-H_{k-1}\|_F))\) required to cause a restart. Default is 0.1.

    +
    +

    General Convex Constraints

    +
      +
    • projections.dykstra.d_tol - termination tolerance for Dykstra’s algorithm for computing the projection onto the intersection of all convex constraints. Default is \(10^{-10}\).

    • +
    • projections.dykstra.max_iters - maximum iterations of Dykstra’s algorithm for computing the projection onto the intersection of all convex constraints. Default is 100.

    • +
    • projections.feasible_tol - tolerance for checking feasibility of initial points with respect to general convex constraints. Default is \(10^{-10}\).

    • +
    • projections.pgd_tol - termination tolerance for trust-region and geometry-improving subproblems. Default is \(10^{-8}\).

    • +
    +

    References

    diff --git a/docs/build/html/diagnostic.html b/docs/build/html/diagnostic.html index 8e2595f..57a9aeb 100644 --- a/docs/build/html/diagnostic.html +++ b/docs/build/html/diagnostic.html @@ -4,7 +4,7 @@ - Diagnostic Information — Py-BOBYQA v1.4.1 documentation + Diagnostic Information — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -38,7 +38,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html index 67e9328..b0478a7 100644 --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -3,7 +3,7 @@ - Index — Py-BOBYQA v1.4.1 documentation + Index — Py-BOBYQA v1.5.0 documentation @@ -14,8 +14,8 @@ - - + + @@ -34,7 +34,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    diff --git a/docs/build/html/history.html b/docs/build/html/history.html index e53256b..532e937 100644 --- a/docs/build/html/history.html +++ b/docs/build/html/history.html @@ -4,7 +4,7 @@ - Version History — Py-BOBYQA v1.4.1 documentation + Version History — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -36,7 +36,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    @@ -63,6 +63,7 @@
  • Version 1.3 (14 Apr 2021)
  • Version 1.4 (16 May 2023)
  • Version 1.4.1 (11 Apr 2024)
  • +
  • Version 1.5.0 (16 Sep 2024)
  • @@ -161,6 +162,12 @@

    Version 1.4.1 (11 Apr 2024) +

    Version 1.5.0 (16 Sep 2024)

    +
      +
    • Added support for general convex constraints

    • +
    +

    diff --git a/docs/build/html/index.html b/docs/build/html/index.html index ff07314..3e8e897 100644 --- a/docs/build/html/index.html +++ b/docs/build/html/index.html @@ -4,7 +4,7 @@ - Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization — Py-BOBYQA v1.4.1 documentation + Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -37,7 +37,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    @@ -83,21 +83,24 @@

    Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization

    -

    Release: 1.4.1

    -

    Date: 11 April 2024

    +

    Release: 1.5.0

    +

    Date: 16 September 2024

    Author: Lindon Roberts

    -

    Py-BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound constraints), without requiring any derivatives of the objective. Py-BOBYQA is a Python implementation of the BOBYQA solver by Powell (documentation here). It is particularly useful when evaluations of the objective function are expensive and/or noisy.

    +

    Py-BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound and other convex constraints), without requiring any derivatives of the objective. Py-BOBYQA is a Python implementation of the BOBYQA solver by Powell (documentation here). It is particularly useful when evaluations of the objective function are expensive and/or noisy.

    That is, Py-BOBYQA solves

    \[\begin{split}\min_{x\in\mathbb{R}^n} &\quad f(x)\\ -\text{s.t.} &\quad a \leq x \leq b\end{split}\]
    -

    The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds).

    +\text{s.t.} &\quad a \leq x \leq b \\ +&\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex}\end{split}\]
    +

    If provided, the constraints the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds), +although the general \(x \in C\) constraint may be slightly violated from rounding errors.

    Full details of the Py-BOBYQA algorithm are given in our papers:

    1. Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, Improving the Flexibility and Robustness of Model-Based Derivative-Free Optimization Solvers, ACM Transactions on Mathematical Software, 45:3 (2019), pp. 32:1-32:41 [preprint]

    2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, Escaping local minima with derivative-free methods: a numerical investigation, Optimization, 71:8 (2022), pp. 2343-2373. [arXiv preprint: 1812.11343]

    3. +
    4. Lindon Roberts, Model Construction for Convex-Constrained Derivative-Free Optimization, arXiv preprint arXiv:2403.14960 (2024).

    -

    Please cite [1] when using Py-BOBYQA for local optimization, and [1,2] when using Py-BOBYQA’s global optimization heuristic functionality.

    +

    Please cite [1] when using Py-BOBYQA for local optimization, [1,2] when using Py-BOBYQA’s global optimization heuristic functionality, and [1,3] if using the general convex constraints \(x \in C\) functionality.

    If you are interested in solving least-squares minimization problems, you may wish to try DFO-LS, which has the same features as Py-BOBYQA (plus some more), and exploits the least-squares problem structure, so performs better on such problems.

    Since v1.1, Py-BOBYQA has a heuristic for global optimization (see Using Py-BOBYQA for details). As this is a heuristic, there are no guarantees it will find a global minimum, but it is more likely to escape local minima if there are better values nearby.

    Py-BOBYQA is released under the GNU General Public License. Please contact NAG for alternative licensing.

    @@ -124,6 +127,7 @@

    Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained MinimizationOptional Arguments
  • A Simple Example
  • Adding Bounds and More Output
  • +
  • Adding General Convex Constraints
  • Example: Noisy Objective Evaluation
  • Example: Global Optimization
  • References
  • @@ -139,6 +143,7 @@

    Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained MinimizationStochastic Noise Information
  • Interpolation Management
  • Multiple Restarts
  • +
  • General Convex Constraints
  • References
  • @@ -160,13 +165,15 @@

    Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained MinimizationVersion 1.3 (14 Apr 2021)
  • Version 1.4 (16 May 2023)
  • Version 1.4.1 (11 Apr 2024)
  • +
  • Version 1.5.0 (16 Sep 2024)
  • Acknowledgements

    -

    This software was developed under the supervision of Coralia Cartis, and was supported by the EPSRC Centre For Doctoral Training in Industrially Focused Mathematical Modelling (EP/L015803/1) in collaboration with the Numerical Algorithms Group.

    +

    This software was initially developed under the supervision of Coralia Cartis, and was supported by the EPSRC Centre For Doctoral Training in Industrially Focused Mathematical Modelling (EP/L015803/1) in collaboration with the Numerical Algorithms Group. +Development of Py-BOBYQA has also been supported by the Australian Research Council (DE240100006).

    diff --git a/docs/build/html/info.html b/docs/build/html/info.html index 650fa5d..b637822 100644 --- a/docs/build/html/info.html +++ b/docs/build/html/info.html @@ -4,7 +4,7 @@ - Overview — Py-BOBYQA v1.4.1 documentation + Overview — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -38,7 +38,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    @@ -91,10 +91,11 @@

    Overview

    When to use Py-BOBYQA

    -

    Py-BOBYQA is designed to solve the nonlinear least-squares minimization problem (with optional bound constraints)

    +

    Py-BOBYQA is designed to solve the nonlinear least-squares minimization problem (with optional bound and general convex constraints)

    \[\begin{split}\min_{x\in\mathbb{R}^n} &\quad f(x)\\ -\text{s.t.} &\quad a \leq x \leq b\end{split}\]
    +\text{s.t.} &\quad a \leq x \leq b\\ +&\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex}\end{split}\]

    We call \(f(x)\) the objective function.

    Py-BOBYQA is a derivative-free optimization algorithm, which means it does not require the user to provide the derivatives of \(f(x)\), nor does it attempt to estimate them internally (by using finite differencing, for instance).

    There are two main situations when using a derivative-free algorithm (such as Py-BOBYQA) is preferable to a derivative-based algorithm (which is the vast majority of least-squares solvers).

    diff --git a/docs/build/html/install.html b/docs/build/html/install.html index 50d9841..e8f0a31 100644 --- a/docs/build/html/install.html +++ b/docs/build/html/install.html @@ -4,7 +4,7 @@ - Installing Py-BOBYQA — Py-BOBYQA v1.4.1 documentation + Installing Py-BOBYQA — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -37,7 +37,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    @@ -106,22 +106,15 @@

    Requirements

    Installation using pip

    -

    For easy installation, use pip as root:

    +

    For easy installation, use pip:

    -
    $ [sudo] pip install Py-BOBYQA
    +
    $ pip install Py-BOBYQA
     
    -

    If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use:

    -
    -
    $ pip install --user Py-BOBYQA
    -
    -
    -
    -

    which will install Py-BOBYQA in your home directory.

    Note that if an older install of Py-BOBYQA is present on your system you can use:

    -
    $ [sudo] pip install --upgrade Py-BOBYQA
    +
    $ pip install --upgrade Py-BOBYQA
     
    @@ -138,21 +131,14 @@

    Manual installation
    $ [sudo] pip install .
    -
    -

    - -

    If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use:

    -
    -
    $ pip install --user .
    +
    $ pip install .
     
    -

    instead.

    To upgrade Py-BOBYQA to the latest version, navigate to the top-level directory (i.e. the one containing setup.py) and rerun the installation using pip, as above:

    $ git pull
    -$ [sudo] pip install .  # with admin privileges
    +$ pip install .
     
    @@ -171,7 +157,7 @@

    Testing

    Uninstallation

    If Py-BOBYQA was installed using pip you can uninstall as follows:

    -
    $ [sudo] pip uninstall Py-BOBYQA
    +
    $ pip uninstall Py-BOBYQA
     
    diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv index 2fd018d..11829d9 100644 Binary files a/docs/build/html/objects.inv and b/docs/build/html/objects.inv differ diff --git a/docs/build/html/search.html b/docs/build/html/search.html index cc919bb..411b192 100644 --- a/docs/build/html/search.html +++ b/docs/build/html/search.html @@ -3,7 +3,7 @@ - Search — Py-BOBYQA v1.4.1 documentation + Search — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -37,7 +37,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index afef6c8..fa5f8d0 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["advanced", "diagnostic", "history", "index", "info", "install", "userguide"], "filenames": ["advanced.rst", "diagnostic.rst", "history.rst", "index.rst", "info.rst", "install.rst", "userguide.rst"], "titles": ["Advanced Usage", "Diagnostic Information", "Version History", "Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization", "Overview", "Installing Py-BOBYQA", "Using Py-BOBYQA"], "terms": {"thi": [0, 1, 2, 3, 4, 5, 6], "section": [0, 1, 2, 6], "describ": [0, 6], "differ": [0, 2, 4, 6], "option": [0, 2, 3, 4, 5], "user": [0, 4, 5, 6], "avail": [0, 1, 2, 5, 6], "py": [0, 1, 2], "bobyqa": [0, 1, 2], "In": [0, 1, 4, 6], "last": [0, 1], "us": [0, 1, 2, 3], "we": [0, 1, 4, 6], "introduc": 0, "pybobyqa": [0, 1, 5, 6], "solv": [0, 1, 3, 4, 6], "which": [0, 1, 2, 3, 4, 5, 6], "ha": [0, 1, 2, 3, 6], "input": [0, 2, 6], "user_param": [0, 1, 6], "i": [0, 1, 2, 3, 4, 5, 6], "python": [0, 2, 3, 4, 5, 6], "dictionari": [0, 1, 2, 6], "now": [0, 6], "go": 0, "through": [0, 2], "set": [0, 1, 2, 6], "can": [0, 4, 5, 6], "chang": [0, 1, 2], "wai": [0, 6], "more": [0, 3, 4], "detail": [0, 3, 6], "ar": [0, 3, 4, 6], "paper": [0, 3, 4, 6], "cfmr2018": [0, 4, 6], "The": [0, 1, 3, 4, 5, 6], "default": [0, 2, 5, 6], "overrid": 0, "given": [0, 3, 4, 6], "some": [0, 3, 6], "case": [0, 6], "vari": 0, "depend": [0, 1, 2], "whether": [0, 6], "objfun": [0, 1, 2, 6], "evalu": [0, 1, 3, 4], "x": [0, 3, 4, 6], "sever": [0, 4, 6], "time": [0, 1, 4, 6], "same": [0, 3, 4, 6], "give": [0, 6], "result": [0, 1, 2, 4, 6], "determin": [0, 6], "objfun_has_nois": [0, 6], "inspect": 0, "instanc": [0, 4], "similarli": 0, "flag": [0, 2, 6], "seek_global_minimum": [0, 2, 6], "e": [0, 1, 3, 4, 5, 6], "global": [0, 2, 3], "minimum": [0, 3, 6], "desir": [0, 6], "rounding_error_const": 0, "intern": [0, 4, 6], "all": [0, 1, 6], "store": [0, 2], "respect": 0, "base": [0, 2, 3, 4, 6], "x_b": 0, "y_t": 0, "reduc": [0, 2], "risk": 0, "roundoff": 0, "error": [0, 1, 2, 6], "shift": [0, 6], "x_k": [0, 4], "when": [0, 2, 3, 6], "s_k": [0, 1, 4], "leq": [0, 3, 4, 6], "text": [0, 1, 3, 4, 6], "const": 0, "where": [0, 1, 6], "0": [0, 1, 3, 4, 6], "1": [0, 1, 3, 4, 5, 6], "safety_step_thresh": 0, "threshold": 0, "call": [0, 1, 4, 6], "safeti": [0, 1, 2], "step": [0, 1, 2, 4, 6], "gamma_": 0, "rho_k": [0, 1], "5": [0, 3, 6], "check_objfun_for_overflow": 0, "cap": 0, "r_i": 0, "thei": [0, 4], "larg": 0, "enough": 0, "an": [0, 2, 5, 6], "overflowerror": 0, "encount": 0, "try": [0, 3, 6], "f": [0, 1, 3, 4, 6], "true": [0, 1, 6], "n_to_print_whole_x_vector": 0, "If": [0, 1, 3, 4, 5, 6], "print": [0, 2, 6], "function": [0, 2, 3, 4, 6], "screen": 0, "file": [0, 1, 5, 6], "maximum": [0, 1, 6], "len": [0, 6], "full": [0, 2, 3, 6], "vector": [0, 6], "should": [0, 5, 6], "also": [0, 5, 6], "6": [0, 3, 6], "save_diagnostic_info": [0, 1], "so": [0, 1, 2, 3, 6], "save": [0, 1, 6], "diagnost": [0, 2, 3, 6], "each": [0, 1, 4, 6], "iter": [0, 2, 3, 6], "fals": [0, 6], "save_poised": [0, 1], "includ": [0, 1, 6], "lambda": [0, 1], "poised": [0, 1], "y_k": [0, 1], "most": [0, 1, 6], "computation": 0, "expens": [0, 1, 3, 4], "piec": [0, 1], "save_xk": [0, 1], "init": 0, "random_initial_direct": 0, "build": [0, 6], "random": [0, 2, 6], "direct": [0, 6], "oppos": 0, "coordin": [0, 6], "random_directions_make_orthogon": 0, "orthogon": 0, "run_in_parallel": 0, "ask": [0, 3, 6], "without": [0, 3, 4], "ani": [0, 1, 3, 6], "intermedi": 0, "process": [0, 2, 4], "tr_radiu": 0, "eta1": 0, "unsuccess": 0, "eta_1": 0, "eta2": 0, "veri": [0, 4], "success": [0, 1, 6], "eta_2": 0, "7": [0, 2, 6], "gamma_dec": 0, "ratio": [0, 1], "decreas": [0, 4, 6], "delta_k": [0, 1, 4], "dec": [0, 3], "smooth": 0, "problem": [0, 3, 4, 6], "98": [0, 6], "noisi": [0, 3, 4], "gamma_inc": 0, "increas": 0, "inc": 0, "2": [0, 3, 5, 6], "gamma_inc_overlin": 0, "overlin": 0, "gamma": 0, "_": [0, 6], "4": [0, 3, 6], "alpha1": 0, "alpha_1": 0, "9": [0, 6], "alpha2": 0, "alpha_2": 0, "95": 0, "model": [0, 2, 3, 4, 6], "abs_tol": 0, "toler": 0, "quit": 0, "below": [0, 1, 6], "10": [0, 6], "20": [0, 3, 6], "history_for_slow": 0, "histori": [0, 3], "current": [0, 3, 4], "thresh_for_slow": 0, "8": [0, 3, 5, 6], "max_slow_it": 0, "number": [0, 1, 4, 6], "consecut": 0, "befor": [0, 2], "x0": [0, 1, 6], "quit_on_noise_level": 0, "within": [0, 2, 6], "level": [0, 5, 6], "scale_factor_for_quit": 0, "factor": 0, "criterion": 0, "multiplicative_noise_level": 0, "onli": [0, 1, 6], "specifi": [0, 6], "one": [0, 1, 4, 5, 6], "addit": 0, "none": [0, 6], "additive_noise_level": 0, "precondit": 0, "scale": [0, 2, 6], "linear": [0, 1, 4, 6], "system": [0, 1, 5, 6], "improv": [0, 2, 3, 4, 6], "condit": [0, 1], "minimum_change_hessian": 0, "underdetermin": 0, "quadrat": [0, 4, 6], "minim": [0, 2, 4], "frobeniu": [0, 1], "norm": [0, 1], "hessian": [0, 1, 2, 6], "use_restart": 0, "do": [0, 2, 5, 6], "reach": [0, 6], "rho_": 0, "end": 0, "seek": 0, "max_unsuccessful_restart": 0, "allow": [0, 6], "did": [0, 6], "further": 0, "max_unsuccessful_restarts_tot": 0, "total": [0, 1, 6], "otherwis": [0, 4, 6], "maxfun": [0, 6], "restrict": 0, "rhobeg_scale_after_unsuccessful_restart": 0, "beg": 0, "after": 0, "rhoend_scal": 0, "use_soft_restart": 0, "soft": [0, 2], "hard": 0, "num_geom_step": 0, "For": [0, 3, 5, 6], "move": [0, 4, 6], "3": [0, 3, 4, 5, 6], "move_xk": 0, "preserv": 0, "best": [0, 1, 6], "new": [0, 2, 4], "use_old_fk": 0, "recycl": 0, "found": [0, 1, 6], "perform": [0, 2, 3, 4, 6], "max_fake_successful_step": 0, "run": [0, 5, 6], "smaller": 0, "larger": [0, 6], "than": [0, 2, 6], "previou": [0, 6], "auto_detect": 0, "automat": [0, 2, 5, 6], "extra": [0, 2, 6], "still": [0, 6], "trigger": 0, "radiu": [0, 1, 2, 4, 6], "etc": [0, 1], "how": [0, 1, 3], "mani": [0, 4, 6], "data": 0, "radii": 0, "There": [0, 4], "two": [0, 4, 6], "criteria": 0, "over": [0, 2, 6], "jacobian": 0, "consist": 0, "trend": 0, "measur": [0, 4], "slope": 0, "correl": 0, "coeffici": 0, "line": [0, 6], "fit": 0, "30": [0, 6], "min_chg_model_slop": 0, "rate": 0, "g_k": [0, 1], "g_": [0, 1], "k": [0, 1, 4, 6], "h_k": [0, 1], "h_": [0, 1, 6], "_f": [0, 1], "past": 0, "caus": [0, 6], "015": 0, "min_correl": 0, "requir": [0, 2, 3, 4, 6], "coralia": [0, 3, 4, 6], "carti": [0, 3, 4, 6], "jan": [0, 3, 4, 6], "fiala": [0, 3, 4, 6], "benjamin": [0, 3, 4, 6], "marteau": [0, 3, 4, 6], "lindon": [0, 3, 4, 6], "robert": [0, 3, 4, 6], "flexibl": [0, 3, 4, 6], "robust": [0, 3, 4, 6], "deriv": [0, 4, 6], "free": [0, 4, 6], "optim": [0, 2, 4], "solver": [0, 2, 3, 4, 6], "acm": [0, 3, 4, 6], "transact": [0, 3, 4, 6], "mathemat": [0, 3, 4, 6], "softwar": [0, 3, 4, 5, 6], "45": [0, 3, 4, 6], "2019": [0, 3, 4, 6], "pp": [0, 3, 4, 6], "32": [0, 3, 4, 6], "41": [0, 3, 4, 6], "preprint": [0, 3, 4, 6], "saw": 1, "output": [1, 2, 3], "return": [1, 2, 6], "contain": [1, 5, 6], "about": [1, 4, 6], "soln": [1, 6], "diagnostic_info": [1, 6], "object": [1, 3, 4], "panda": [1, 2, 5, 6], "datafram": [1, 6], "row": 1, "per": [1, 2, 6], "kei": 1, "list": [1, 2, 6], "valu": [1, 2, 3, 4, 6], "explain": 1, "mean": [1, 4], "type": [1, 4], "column": 1, "To": [1, 4, 5, 6], "csv": 1, "previous": 1, "defin": [1, 6], "turn": 1, "log": [1, 2, 3, 6], "info": [1, 6], "to_csv": 1, "myfil": [1, 6], "exactli": [1, 6], "termin": [1, 3, 6], "mai": [1, 3, 4, 6], "fulli": 1, "popul": 1, "xk": 1, "point": [1, 2, 3, 4, 6], "far": [1, 6], "fk": 1, "rho": [1, 6], "lower": [1, 3, 6], "bound": [1, 2, 4], "delta": [1, 6], "norm_sk": 1, "npt": [1, 6], "interpolation_error": 1, "sum": 1, "squar": [1, 3, 4], "from": [1, 2, 4, 6], "interpolation_condition_numb": 1, "matrix": [1, 6], "interpolation_change_g_norm": 1, "gradient": [1, 2, 6], "interpolation_change_h_norm": 1, "smallest": 1, "pois": 1, "comput": [1, 4], "max_distance_xk": 1, "distanc": 1, "norm_gk": 1, "nrun": [1, 6], "been": [1, 6], "restart": [1, 2, 3, 6], "nf": [1, 6], "see": [1, 3, 5, 6], "nx": [1, 6], "nsampl": [1, 6], "iter_this_run": 1, "sinc": [1, 3], "iters_tot": 1, "iter_typ": 1, "A": [1, 3], "descript": [1, 6], "what": 1, "had": 1, "g": [1, 5, 6], "actual": 1, "predict": 1, "reduct": 1, "slow_it": 1, "equal": 1, "slow": [1, 2, 3, 6], "wa": [1, 3, 5, 6], "updat": 2, "between": 2, "them": [2, 4], "initi": [2, 3, 6], "releas": [2, 3], "minor": 2, "bug": 2, "fix": [2, 6], "trust": [2, 3, 4, 5, 6], "region": [2, 3, 4, 5, 6], "subproblem": [2, 4, 5, 6], "crvmin": 2, "calcul": [2, 4, 6], "correctli": [2, 6], "impact": [2, 6], "arg": [2, 6], "pass": [2, 6], "argument": [2, 3], "pull": [2, 5], "request": [2, 6], "logangrado": 2, "paramet": [2, 3, 6], "cost": 2, "regim": 2, "correct": [2, 6], "retriev": 2, "dure": 2, "instal": [2, 3], "control": 2, "multipl": [2, 3, 4, 6], "design": [2, 4, 6], "sensibl": [2, 6], "exampl": [2, 3], "script": [2, 6], "demonstr": [2, 6], "variabl": [2, 3, 6], "1a0": 2, "17": [2, 6], "jul": 2, "link": 2, "code": [2, 5, 6], "zenodo": 2, "creat": 2, "doi": 2, "algorithm": [2, 3, 6], "determinist": 2, "initialis": [2, 6], "longer": 2, "necessari": 2, "seed": [2, 6], "reproduc": [2, 6], "rather": [2, 6], "just": 2, "upper": [2, 3, 6], "triangular": 2, "part": [2, 6], "runtim": 2, "oper": 2, "faster": 2, "geometri": [2, 4], "solut": [2, 3, 4, 5, 6], "fortran": [2, 5], "trustregion": [2, 5], "packag": [2, 3, 5], "don": 2, "t": [2, 3, 4, 6], "adjust": [2, 6], "start": [2, 6], "close": [2, 4], "long": 2, "feasibl": 2, "stop": 2, "behavior": 2, "enabl": 2, "bugfix": 2, "handl": 2, "side": 2, "avoid": 2, "divid": 2, "zero": 2, "warn": [2, 6], "auto": 2, "detect": 2, "remov": [2, 5], "numpi": [2, 5, 6], "deprec": 2, "np": [2, 6], "int": 2, "float": [2, 6], "inform": [2, 3, 4, 6], "nan": 2, "inf": 2, "gracefulli": 2, "exit": [2, 6], "make": [2, 4, 5, 6], "symmetr": 2, "instead": [2, 5], "reset": 2, "counter": 2, "date": 3, "11": [3, 6], "april": 3, "2024": 3, "author": 3, "find": [3, 6], "local": [3, 6], "nonlinear": [3, 4], "nonconvex": [3, 4], "constraint": [3, 4, 6], "implement": [3, 4, 6], "powel": [3, 4], "document": 3, "here": [3, 6], "It": [3, 5, 6], "particularli": [3, 6], "That": 3, "min_": [3, 4, 6], "mathbb": [3, 4, 6], "r": [3, 4, 6], "n": [3, 4, 6], "quad": [3, 4, 6], "": [3, 4, 6], "b": [3, 4, 6], "non": [3, 6], "relax": [3, 6], "never": [3, 6], "outsid": [3, 6], "our": [3, 4, 6], "oliv": [3, 6], "sheridan": [3, 6], "methven": [3, 6], "escap": [3, 6], "minima": [3, 6], "method": [3, 4, 6], "numer": [3, 6], "investig": [3, 6], "2021": 3, "pleas": 3, "cite": 3, "heurist": [3, 6], "v1": 3, "you": [3, 4, 5, 6], "interest": [3, 4], "least": [3, 4], "wish": [3, 6], "dfo": 3, "l": 3, "featur": [3, 6], "plu": 3, "exploit": 3, "structur": 3, "better": [3, 6], "As": [3, 6], "guarante": [3, 6], "like": [3, 6], "nearbi": [3, 6], "under": 3, "gnu": 3, "gener": [3, 6], "public": 3, "licens": 3, "contact": 3, "nag": 3, "altern": [3, 6], "pip": 3, "manual": 3, "test": [3, 6], "uninstal": 3, "overview": [3, 6], "refer": 3, "simpl": 3, "ad": 3, "advanc": [3, 6], "usag": [3, 6], "manag": 3, "small": [3, 4, 6], "progress": [3, 6], "stochast": [3, 6], "nois": [3, 6], "interpol": [3, 4, 6], "count": 3, "version": [3, 5], "feb": 3, "2018": 3, "jun": 3, "24": [3, 6], "apr": 3, "25": [3, 6], "2020": 3, "14": [3, 6], "16": 3, "2023": 3, "develop": 3, "supervis": 3, "support": [2, 3, 5], "epsrc": 3, "centr": 3, "doctor": 3, "train": 3, "industri": 3, "focus": 3, "ep": 3, "l015803": 3, "collabor": 3, "group": 3, "doe": [4, 6], "provid": [4, 6], "nor": 4, "attempt": 4, "estim": [4, 6], "finit": 4, "differenc": 4, "main": [4, 6], "situat": 4, "prefer": 4, "vast": 4, "major": 4, "residu": 4, "even": 4, "imposs": 4, "inaccur": 4, "By": 4, "get": [4, 6], "happen": 4, "mont": 4, "carlo": 4, "simul": 4, "involv": 4, "physic": 4, "experi": 4, "everi": [4, 6], "prohibit": 4, "fewest": 4, "possibl": [4, 6], "howev": [4, 6], "have": [4, 5, 6], "probabl": 4, "good": [4, 6], "idea": 4, "scipi": [4, 5, 6], "librari": 4, "common": [4, 6], "categori": 4, "approxim": [4, 6], "m_k": 4, "approx": [4, 6], "maintain": 4, "size": [4, 6], "At": 4, "trial": 4, "task": 4, "take": [4, 6], "x_": [4, 6], "stai": 4, "put": 4, "choos": 4, "delta_": 4, "repeat": 4, "construct": [4, 6], "sure": [4, 5], "accur": [4, 6], "need": [4, 6], "regularli": 4, "check": 4, "well": 4, "space": 4, "aren": 4, "powell2009": 4, "michael": 4, "j": [4, 6], "d": 4, "constrain": [4, 6], "technic": [4, 6], "report": 4, "damtp": 4, "2009": 4, "na06": 4, "univers": 4, "cambridg": 4, "follow": [5, 6], "addition": 5, "higher": 5, "18": [], "fast": 5, "compil": 5, "gfortran": 5, "work": 5, "easi": [5, 6], "root": 5, "sudo": 5, "privileg": 5, "want": [5, 6], "your": [5, 6], "privat": 5, "home": 5, "directori": [5, 6], "note": [5, 6], "older": 5, "present": 5, "upgrad": 5, "latest": 5, "sourc": 5, "github": [5, 6], "git": 5, "clone": 5, "http": 5, "com": 5, "numericalalgorithmsgroup": 5, "cd": 5, "written": 5, "pure": 5, "navig": 5, "top": 5, "setup": [2, 5], "rerun": 5, "abov": [5, 6], "admin": 5, "hand": 5, "locat": 5, "site": 5, "interfac": 6, "usual": 6, "nonquadrat": 6, "know": 6, "consid": 6, "framework": 6, "depth": 6, "cro2018": [], "via": 6, "must": 6, "dimension": 6, "arrai": 6, "shape": 6, "singl": 6, "min": 6, "possibli": 6, "first": 6, "g_i": 6, "partial": 6, "x_i": 6, "length": 6, "second": 6, "x_j": 6, "integ": 6, "sampl": 6, "averag": 6, "msg": 6, "why": 6, "finish": 6, "string": 6, "tabl": 6, "show": 6, "exit_success": 6, "successfulli": 6, "suffici": 6, "exit_maxfun_warn": 6, "exit_slow_warn": 6, "exit_false_success_warn": 6, "wors": 6, "exit_input_error": 6, "exit_tr_increase_error": 6, "occur": 6, "exit_linalg_error": 6, "algebra": 6, "produc": 6, "singular": 6, "These": 6, "access": 6, "rhobeg": 6, "rhoend": 6, "1e": 6, "scaling_within_bound": 6, "do_log": 6, "print_progress": 6, "tupl": 6, "a_i": 6, "b_i": 6, "either": 6, "both": 6, "2n": 6, "max": 6, "x_0": 6, "infti": 6, "100": 6, "1000": 6, "nrestart": 6, "applic": 6, "param1": 6, "val1": 6, "param2": 6, "val2": 6, "next": 6, "indic": 6, "overridden": 6, "search": 6, "mechan": 6, "repeatedli": 6, "re": 6, "reigon": 6, "multi": 6, "approach": 6, "entri": 6, "becom": 6, "order": 6, "magnitud": 6, "appli": 6, "visibl": 6, "unless": 6, "modul": 6, "practic": 6, "amount": 6, "achiev": 6, "suppos": 6, "rosenbrock": 6, "x_1": 6, "x_2": 6, "commonli": 6, "purpos": 6, "__future__": 6, "import": 6, "print_funct": 6, "def": 6, "displai": 6, "its": 6, "phase": 6, "along": 6, "xmin": 6, "013856052e": 6, "151": 6, "35772499e": 6, "08": 6, "07598803e": 6, "802": 6, "00799968": 6, "400": 6, "04089119": 6, "199": 6, "99228723": 6, "page": 6, "extend": 6, "add": 6, "85": 6, "81": 6, "01": 6, "146": 6, "00000006e": 6, "74578563e": 6, "09": 6, "649": 6, "66398033": 6, "361": 6, "03094781": 6, "94223213": 6, "runtimewarn": 6, "out": 6, "basicconfig": 6, "format": 6, "messag": 6, "And": 6, "eval": 6, "39": 6, "65": 6, "337296": 6, "55": 6, "73": 6, "145": 6, "0100000013172792": 6, "89999999": 6, "80999999": 6, "00999999999999993": 6, "could": 6, "replac": 6, "filenam": 6, "filemod": 6, "w": 6, "deactiv": 6, "obj": 6, "grad": 6, "43e": 6, "74e": 6, "02": 6, "20e": 6, "57e": 6, "00": 6, "66e": 6, "00e": 6, "132": 6, "50e": 6, "144": 6, "133": 6, "let": 6, "modifi": 6, "compar": 6, "gaussian": 6, "rosenbrock_noisi": 6, "normal": 6, "rang": 6, "opt": 6, "str": 6, "10g": 6, "fun": 6, "nfev": 6, "statu": 6, "6269": 6, "2968": 6, "4369": 6, "7423": 6, "6519": 6, "04327395": 6, "09935385": 6, "080030471": 6, "42": 6, "3786376": 6, "5065785": 6, "5876675": 6, "51763198": 6, "32881117e": 6, "68241358e": 6, "09785319e": 6, "20013817": 6, "99992915": 6, "23": 6, "86371763": 6, "80": 6, "necessarili": 6, "due": [2, 6], "precis": 6, "loss": 6, "although": 6, "cannot": 6, "reason": 6, "troubl": 6, "unabl": 6, "therefor": 6, "237351799e": 6, "19": 6, "300": 6, "17072738e": 6, "07": 6, "62304351e": 6, "809": 6, "56521044": 6, "33737779": 6, "198": 6, "36487985": 6, "freudenstein": 6, "roth": 6, "mor\u00e9": 6, "garbow": 6, "hillstrom": 6, "unconstrain": 6, "tran": 6, "math": 6, "1981": 6, "48": 6, "8968": 6, "freudenstein_roth": 6, "r1": 6, "13": 6, "r2": 6, "29": 6, "500": 6, "41277902": 6, "89680525": 6, "98425368": 6, "143": 6, "64941396e": 6, "69795781e": 6, "74717421": 6, "104": 6, "51102613": 6, "1135": 6, "76500421": 6, "659891409e": 6, "70038835e": 6, "64918043e": 6, "28883646": 6, "64": 6, "16836253": 6, "3722": 6, "93109385": 6, "help": 6, "71": [3, 6], "2022": [3, 6], "2343": [3, 6], "2373": [3, 6], "arxiv": [3, 6], "1812": [3, 6], "11343": [3, 6], "www": 5, "org": 5, "pydata": 5, "pytest": 5, "m": 5, "pyarg": 5, "cro2022": 6, "migrat": 2, "pyproject": 2, "toml": 2, "12": 2, "drop": 2}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"advanc": 0, "usag": 0, "gener": 0, "algorithm": [0, 1, 4], "paramet": 0, "log": 0, "output": [0, 6], "initi": 0, "point": 0, "trust": [0, 1], "region": [0, 1], "manag": 0, "termin": 0, "small": 0, "object": [0, 6], "valu": 0, "slow": 0, "progress": [0, 1], "stochast": 0, "nois": 0, "inform": [0, 1], "interpol": [0, 1], "multipl": 0, "restart": 0, "refer": [0, 4, 6], "diagnost": 1, "current": 1, "iter": 1, "model": 1, "count": 1, "version": 2, "histori": 2, "1": 2, "0": 2, "6": 2, "feb": 2, "2018": 2, "20": 2, "2": 2, "jun": 2, "24": 2, "dec": 2, "5": 2, "apr": 2, "2019": 2, "25": 2, "2020": 2, "3": 2, "14": 2, "2021": 2, "4": 2, "16": 2, "mai": 2, "2023": 2, "py": [3, 4, 5, 6], "bobyqa": [3, 4, 5, 6], "deriv": 3, "free": 3, "optim": [3, 6], "bound": [3, 6], "constrain": 3, "minim": [3, 6], "content": 3, "acknowledg": 3, "overview": 4, "when": 4, "us": [4, 5, 6], "detail": 4, "instal": 5, "requir": 5, "pip": 5, "manual": 5, "test": 5, "uninstal": 5, "nonlinear": 6, "how": 6, "option": 6, "argument": 6, "A": 6, "simpl": 6, "exampl": 6, "ad": 6, "more": 6, "noisi": 6, "evalu": 6, "global": 6, "11": 2, "2024": 2}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Advanced Usage": [[0, "advanced-usage"]], "General Algorithm Parameters": [[0, "general-algorithm-parameters"]], "Logging and Output": [[0, "logging-and-output"]], "Initialization of Points": [[0, "initialization-of-points"]], "Trust Region Management": [[0, "trust-region-management"]], "Termination on Small Objective Value": [[0, "termination-on-small-objective-value"]], "Termination on Slow Progress": [[0, "termination-on-slow-progress"]], "Stochastic Noise Information": [[0, "stochastic-noise-information"]], "Interpolation Management": [[0, "interpolation-management"]], "Multiple Restarts": [[0, "multiple-restarts"]], "References": [[0, "references"], [4, "references"], [6, "references"]], "Diagnostic Information": [[1, "diagnostic-information"]], "Current Iterate": [[1, "current-iterate"]], "Trust Region": [[1, "trust-region"]], "Model Interpolation": [[1, "model-interpolation"]], "Iteration Count": [[1, "iteration-count"]], "Algorithm Progress": [[1, "algorithm-progress"]], "Version History": [[2, "version-history"]], "Version 1.0 (6 Feb 2018)": [[2, "version-1-0-6-feb-2018"]], "Version 1.0.1 (20 Feb 2018)": [[2, "version-1-0-1-20-feb-2018"]], "Version 1.0.2 (20 Jun 2018)": [[2, "version-1-0-2-20-jun-2018"]], "Version 1.1 (24 Dec 2018)": [[2, "version-1-1-24-dec-2018"]], "Version 1.1.1 (5 Apr 2019)": [[2, "version-1-1-1-5-apr-2019"]], "Version 1.2 (25 Feb 2020)": [[2, "version-1-2-25-feb-2020"]], "Version 1.3 (14 Apr 2021)": [[2, "version-1-3-14-apr-2021"]], "Version 1.4 (16 May 2023)": [[2, "version-1-4-16-may-2023"]], "Version 1.4.1 (11 Apr 2024)": [[2, "version-1-4-1-11-apr-2024"]], "Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization": [[3, "py-bobyqa-derivative-free-optimizer-for-bound-constrained-minimization"]], "Contents:": [[3, null]], "Acknowledgements": [[3, "acknowledgements"]], "Overview": [[4, "overview"]], "When to use Py-BOBYQA": [[4, "when-to-use-py-bobyqa"]], "Details of the Py-BOBYQA Algorithm": [[4, "details-of-the-py-bobyqa-algorithm"]], "Installing Py-BOBYQA": [[5, "installing-py-bobyqa"]], "Requirements": [[5, "requirements"]], "Installation using pip": [[5, "installation-using-pip"]], "Manual installation": [[5, "manual-installation"]], "Testing": [[5, "testing"]], "Uninstallation": [[5, "uninstallation"]], "Using Py-BOBYQA": [[6, "using-py-bobyqa"]], "Nonlinear Minimization": [[6, "nonlinear-minimization"]], "How to use Py-BOBYQA": [[6, "how-to-use-py-bobyqa"]], "Optional Arguments": [[6, "optional-arguments"]], "A Simple Example": [[6, "a-simple-example"]], "Adding Bounds and More Output": [[6, "adding-bounds-and-more-output"]], "Example: Noisy Objective Evaluation": [[6, "example-noisy-objective-evaluation"]], "Example: Global Optimization": [[6, "example-global-optimization"]]}, "indexentries": {}}) \ No newline at end of file +Search.setIndex({"alltitles": {"A Simple Example": [[6, "a-simple-example"]], "Acknowledgements": [[3, "acknowledgements"]], "Adding Bounds and More Output": [[6, "adding-bounds-and-more-output"]], "Adding General Convex Constraints": [[6, "adding-general-convex-constraints"]], "Advanced Usage": [[0, null]], "Algorithm Progress": [[1, "algorithm-progress"]], "Contents:": [[3, null]], "Current Iterate": [[1, "current-iterate"]], "Details of the Py-BOBYQA Algorithm": [[4, "details-of-the-py-bobyqa-algorithm"]], "Diagnostic Information": [[1, null]], "Example: Global Optimization": [[6, "example-global-optimization"]], "Example: Noisy Objective Evaluation": [[6, "example-noisy-objective-evaluation"]], "General Algorithm Parameters": [[0, "general-algorithm-parameters"]], "General Convex Constraints": [[0, "general-convex-constraints"]], "How to use Py-BOBYQA": [[6, "how-to-use-py-bobyqa"]], "Initialization of Points": [[0, "initialization-of-points"]], "Installation using pip": [[5, "installation-using-pip"]], "Installing Py-BOBYQA": [[5, null]], "Interpolation Management": [[0, "interpolation-management"]], "Iteration Count": [[1, "iteration-count"]], "Logging and Output": [[0, "logging-and-output"]], "Manual installation": [[5, "manual-installation"]], "Model Interpolation": [[1, "model-interpolation"]], "Multiple Restarts": [[0, "multiple-restarts"]], "Nonlinear Minimization": [[6, "nonlinear-minimization"]], "Optional Arguments": [[6, "optional-arguments"]], "Overview": [[4, null]], "Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization": [[3, null]], "References": [[0, "references"], [4, "references"], [6, "references"]], "Requirements": [[5, "requirements"]], "Stochastic Noise Information": [[0, "stochastic-noise-information"]], "Termination on Slow Progress": [[0, "termination-on-slow-progress"]], "Termination on Small Objective Value": [[0, "termination-on-small-objective-value"]], "Testing": [[5, "testing"]], "Trust Region": [[1, "trust-region"]], "Trust Region Management": [[0, "trust-region-management"]], "Uninstallation": [[5, "uninstallation"]], "Using Py-BOBYQA": [[6, null]], "Version 1.0 (6 Feb 2018)": [[2, "version-1-0-6-feb-2018"]], "Version 1.0.1 (20 Feb 2018)": [[2, "version-1-0-1-20-feb-2018"]], "Version 1.0.2 (20 Jun 2018)": [[2, "version-1-0-2-20-jun-2018"]], "Version 1.1 (24 Dec 2018)": [[2, "version-1-1-24-dec-2018"]], "Version 1.1.1 (5 Apr 2019)": [[2, "version-1-1-1-5-apr-2019"]], "Version 1.2 (25 Feb 2020)": [[2, "version-1-2-25-feb-2020"]], "Version 1.3 (14 Apr 2021)": [[2, "version-1-3-14-apr-2021"]], "Version 1.4 (16 May 2023)": [[2, "version-1-4-16-may-2023"]], "Version 1.4.1 (11 Apr 2024)": [[2, "version-1-4-1-11-apr-2024"]], "Version 1.5.0 (16 Sep 2024)": [[2, "version-1-5-0-16-sep-2024"]], "Version History": [[2, null]], "When to use Py-BOBYQA": [[4, "when-to-use-py-bobyqa"]]}, "docnames": ["advanced", "diagnostic", "history", "index", "info", "install", "userguide"], "envversion": {"sphinx": 62, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["advanced.rst", "diagnostic.rst", "history.rst", "index.rst", "info.rst", "install.rst", "userguide.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"": [0, 3, 4, 6], "0": [0, 1, 3, 4, 6], "00": 6, "00000006e": 6, "00799968": 6, "00999999999999993": 6, "00e": 6, "01": 6, "0100000013172792": 6, "013856052e": 6, "015": 0, "02": 6, "03094781": 6, "03829114": 6, "04089119": 6, "04327395": 6, "07": 6, "07598803e": 6, "08": 6, "080030471": 6, "09": 6, "09785319e": 6, "09935385": 6, "1": [0, 1, 3, 4, 5, 6], "10": [0, 6], "100": [0, 6], "1000": 6, "101": 6, "104": 6, "10g": 6, "11": [3, 6], "11343": [3, 6], "1135": 6, "11858775": 6, "12": 2, "13": 6, "132": 6, "133": 6, "14": [3, 6], "143": 6, "144": 6, "145": 6, "146": 6, "14960": [3, 6], "151": 6, "16": 3, "16836253": 6, "17": [2, 6], "17072738e": 6, "1812": [3, 6], "19": 6, "198": 6, "1981": 6, "199": 6, "1a0": 2, "1e": 6, "2": [0, 3, 5, 6], "20": [0, 3, 6], "20013817": 6, "2009": 4, "201": 6, "2017": 6, "2018": 3, "2019": [0, 3, 4, 6], "2020": 3, "2021": 3, "2022": [3, 6], "2023": 3, "2024": [3, 6], "20e": 6, "23": 6, "2343": [3, 6], "2373": [3, 6], "237351799e": 6, "24": [3, 6], "2403": [3, 6], "25": [3, 6], "253": 6, "279": 6, "28883646": 6, "29": 6, "2968": 6, "2n": 6, "3": [0, 3, 4, 5, 6], "30": [0, 6], "300": 6, "32": [0, 3, 4, 6], "32881117e": 6, "337296": 6, "33737779": 6, "35772499e": 6, "361": 6, "36487985": 6, "3722": 6, "3786376": 6, "39": 6, "39193327": 6, "4": [0, 3, 6], "400": 6, "41": [0, 3, 4, 6], "41277902": 6, "42": 6, "4369": 6, "43e": 6, "45": [0, 3, 4, 6], "48": 6, "49725358": 6, "5": [0, 3, 6], "500": 6, "5065785": 6, "50e": 6, "51102613": 6, "51763198": 6, "55": 6, "56521044": 6, "57e": 6, "5876675": 6, "6": [0, 3, 6], "62304351e": 6, "6269": 6, "64": 6, "649": 6, "64918043e": 6, "64941396e": 6, "65": 6, "6519": 6, "659891409e": 6, "66398033": 6, "66e": 6, "68241358e": 6, "69795781e": 6, "7": [0, 2, 6], "70038835e": 6, "70424386": 6, "71": [3, 6], "73": 6, "7423": 6, "74578563e": 6, "74717421": 6, "74e": 6, "76500421": 6, "8": [0, 3, 5, 6], "80": 6, "802": 6, "809": 6, "80999999": 6, "81": 6, "85": 6, "85583188": 6, "86371763": 6, "8968": 6, "89680525": 6, "89999999": 6, "9": [0, 6], "93109385": 6, "94223213": 6, "95": 0, "9667031": 6, "97449424": 6, "98": [0, 6], "98425368": 6, "99228723": 6, "99992915": 6, "A": [1, 3], "And": 6, "As": [3, 6], "At": 4, "By": 4, "For": [0, 3, 5, 6], "If": [0, 1, 3, 4, 5, 6], "In": [0, 1, 4, 6], "It": [3, 5, 6], "Not": 0, "That": 3, "The": [0, 1, 4, 5, 6], "There": [0, 4, 6], "These": 6, "To": [1, 4, 5, 6], "_": [0, 6], "_2": 6, "__future__": 6, "_f": [0, 1], "a_i": 6, "about": [1, 4, 6], "abov": [5, 6], "abs_tol": 0, "access": 6, "accur": [4, 6], "achiev": 6, "acm": [0, 3, 4, 6], "actual": 1, "ad": [2, 3], "add": 6, "addit": 0, "addition": 5, "additive_noise_level": 0, "adjust": [2, 6], "admin": [], "advanc": [3, 6], "after": 0, "algebra": 6, "algorithm": [2, 3, 6], "all": [0, 1, 3, 4, 6], "allow": [0, 6], "along": 6, "alpha1": 0, "alpha2": 0, "alpha_1": 0, "alpha_2": 0, "also": [0, 3, 5, 6], "altern": [3, 6], "although": [3, 6], "amir": 6, "amount": 6, "an": [0, 2, 5, 6], "ani": [0, 1, 3, 6], "appli": 6, "applic": 6, "approach": 6, "approx": [4, 6], "approxim": [4, 6], "apr": 3, "ar": [0, 3, 4, 6], "aren": 4, "arg": [2, 6], "argmin": 6, "argument": [2, 3], "arrai": 6, "arxiv": [3, 6], "ask": [0, 3, 6], "attempt": 4, "australian": 3, "author": 3, "auto": 2, "auto_detect": 0, "automat": [0, 2, 5, 6], "avail": [0, 1, 2, 5, 6], "averag": 6, "avoid": 2, "b": [3, 4, 6], "b2017": 6, "b_i": 6, "ball": 6, "ball_proj": 6, "base": [0, 2, 3, 4, 6], "basicconfig": 6, "beck": 6, "becom": 6, "been": [1, 3, 6], "befor": [0, 2], "beg": 0, "behavior": 2, "below": [0, 1, 6], "benjamin": [0, 3, 4, 6], "best": [0, 1, 6], "better": [3, 6], "between": 2, "bobyqa": [0, 1, 2], "both": 6, "bound": [1, 2, 4], "bug": 2, "bugfix": 2, "build": [0, 6], "c": [3, 4, 6], "c_1": [3, 4, 6], "c_i": [3, 4, 6], "c_n": [3, 4, 6], "calcul": [2, 4, 6], "call": [0, 1, 4, 6], "cambridg": 4, "can": [0, 4, 5, 6], "cannot": 6, "cap": [0, 3, 4, 6], "carlo": 4, "carti": [0, 3, 4, 6], "case": [0, 6], "categori": 4, "caus": [0, 6], "cd": 5, "cdot": [3, 4, 6], "center": 6, "centr": 3, "cfmr2018": [0, 4, 6], "chang": [0, 1, 2], "check": [0, 4], "check_objfun_for_overflow": 0, "choos": 4, "cite": 3, "clone": 5, "close": [2, 4], "closest": 6, "code": [2, 5, 6], "coeffici": 0, "collabor": 3, "column": 1, "com": 5, "common": [4, 6], "commonli": 6, "compar": 6, "compil": 5, "comput": [0, 1, 4, 6], "computation": 0, "condit": [0, 1], "consecut": 0, "consid": 6, "consist": 0, "const": 0, "constrain": [4, 6], "constraint": [2, 3, 4], "construct": [3, 4, 6], "contact": 3, "contain": [1, 5, 6], "control": 2, "convex": [2, 3, 4], "coordin": [0, 6], "coralia": [0, 3, 4, 6], "correct": [2, 6], "correctli": [2, 6], "correl": 0, "correspond": 6, "cost": 2, "could": 6, "council": 3, "count": 3, "counter": 2, "creat": 2, "criteria": 0, "criterion": 0, "cro2022": 6, "crvmin": 2, "csv": 1, "current": [0, 3, 4], "d": 4, "d_tol": 0, "damtp": 4, "data": 0, "databas": 6, "datafram": [1, 6], "date": 3, "de240100006": 3, "deactiv": 6, "dec": [0, 3], "decreas": [0, 4, 6], "def": 6, "default": [0, 2, 5, 6], "defin": [1, 6], "delta": [1, 6], "delta_": 4, "delta_k": [0, 1, 4], "demonstr": [2, 6], "depend": [0, 1, 2], "deprec": 2, "depth": 6, "deriv": [0, 4, 6], "describ": [0, 6], "descript": [1, 6], "design": [2, 4, 6], "desir": [0, 6], "detail": [0, 3, 6], "detect": 2, "determin": [0, 6], "determinist": 2, "develop": 3, "dfo": 3, "diagnost": [0, 2, 3, 6], "diagnostic_info": [1, 6], "dictionari": [0, 1, 2, 6], "did": [0, 6], "differ": [0, 2, 4, 6], "differenc": 4, "dimension": 6, "direct": [0, 6], "directli": 6, "directori": [5, 6], "displai": 6, "distanc": 1, "divid": 2, "do": [0, 2, 5, 6], "do_log": 6, "doctor": 3, "document": 3, "doe": [4, 6], "doi": 2, "don": 2, "drop": 2, "due": [2, 6], "dure": 2, "dykstra": [0, 6], "e": [0, 1, 3, 4, 5, 6], "each": [0, 1, 4, 6], "easi": [5, 6], "either": 6, "element": 6, "enabl": 2, "encount": 0, "end": 0, "enough": 0, "ensur": 6, "entri": 6, "ep": 3, "epsrc": 3, "equal": 1, "error": [0, 1, 2, 3, 6], "escap": [3, 6], "estim": [4, 6], "eta1": 0, "eta2": 0, "eta_1": 0, "eta_2": 0, "etc": [0, 1], "euclidean": 6, "eval": 6, "evalu": [0, 1, 3, 4], "even": 4, "everi": [4, 6], "exactli": [1, 6], "exampl": [2, 3], "exit": [2, 6], "exit_false_success_warn": 6, "exit_input_error": 6, "exit_linalg_error": 6, "exit_maxfun_warn": 6, "exit_slow_warn": 6, "exit_success": 6, "exit_tr_increase_error": 6, "expens": [0, 1, 3, 4], "experi": 4, "explain": 1, "explicit": 6, "explicitli": 6, "exploit": 3, "express": 6, "extend": 6, "extra": [0, 2, 6], "f": [0, 1, 3, 4, 6], "factor": 0, "fals": [0, 6], "far": [1, 6], "fast": 5, "faster": 2, "feasibl": [0, 2, 6], "feasible_tol": 0, "featur": [3, 6], "feb": 3, "fewest": 4, "fiala": [0, 3, 4, 6], "file": [0, 1, 5, 6], "filemod": 6, "filenam": 6, "find": [3, 6], "finish": 6, "finit": 4, "first": 6, "fit": 0, "fix": [2, 6], "fk": 1, "flag": [0, 2, 6], "flexibl": [0, 3, 4, 6], "float": [2, 6], "focus": 3, "follow": [5, 6], "form": 6, "format": 6, "fortran": [2, 5], "found": [0, 1, 6], "framework": 6, "free": [0, 4, 6], "freudenstein": 6, "freudenstein_roth": 6, "frobeniu": [0, 1], "from": [1, 2, 3, 4, 6], "full": [0, 2, 3, 6], "fulli": 1, "fun": 6, "function": [0, 2, 3, 4, 6], "further": 0, "g": [1, 5, 6], "g_": [0, 1], "g_i": 6, "g_k": [0, 1], "gamma": 0, "gamma_": 0, "gamma_dec": 0, "gamma_inc": 0, "gamma_inc_overlin": 0, "garbow": 6, "gaussian": 6, "gener": [2, 3, 4], "geometri": [0, 2, 4], "geq": 6, "get": [4, 6], "gfortran": 5, "git": 5, "github": [5, 6], "give": [0, 6], "given": [0, 3, 4, 6], "global": [0, 2, 3], "gnu": 3, "go": 0, "good": [4, 6], "gracefulli": 2, "grad": 6, "gradient": [1, 2, 6], "group": 3, "guarante": [3, 6], "h_": [0, 1, 6], "h_k": [0, 1], "ha": [0, 1, 2, 3, 6], "had": 1, "hand": 5, "handl": [2, 6], "happen": 4, "hard": 0, "have": [4, 5, 6], "help": 6, "here": [3, 6], "hessian": [0, 1, 2, 6], "heurist": [3, 6], "higher": 5, "hillstrom": 6, "histori": [0, 3], "history_for_slow": 0, "home": [], "how": [0, 1, 3], "howev": [4, 6], "http": 5, "i": [0, 1, 2, 3, 4, 5, 6], "idea": 4, "impact": [2, 6], "implement": [3, 4, 6], "import": 6, "imposs": 4, "improv": [0, 2, 3, 4, 6], "inaccur": 4, "inc": 0, "includ": [0, 1, 6], "increas": 0, "indic": 6, "industri": 3, "inequ": 6, "inf": 2, "info": [1, 6], "inform": [2, 3, 4, 6], "infti": 6, "init": 0, "initi": [2, 3, 6], "initialis": [2, 6], "input": [0, 2, 6], "inspect": 0, "instal": [2, 3], "instanc": [0, 4], "instead": [2, 6], "int": 2, "integ": 6, "interest": [3, 4], "interfac": 6, "intermedi": 0, "intern": [0, 4, 6], "interpol": [3, 4, 6], "interpolation_change_g_norm": 1, "interpolation_change_h_norm": 1, "interpolation_condition_numb": 1, "interpolation_error": 1, "intersect": [0, 6], "introduc": 0, "investig": [3, 6], "involv": 4, "iter": [0, 2, 3, 6], "iter_this_run": 1, "iter_typ": 1, "iters_tot": 1, "its": 6, "j": [4, 6], "jacobian": 0, "jan": [0, 3, 4, 6], "jul": 2, "jun": 3, "just": [2, 6], "k": [0, 1, 4, 6], "kei": 1, "know": 6, "known": 6, "l": 3, "l015803": 3, "lambda": [0, 1, 6], "larg": 0, "larger": [0, 6], "last": [0, 1], "latest": 5, "least": [3, 4], "len": [0, 6], "length": 6, "leq": [0, 3, 4, 6], "let": 6, "level": [0, 5, 6], "librari": 4, "licens": 3, "like": [3, 6], "linalg": 6, "lindon": [0, 3, 4, 6], "line": [0, 6], "linear": [0, 1, 4, 6], "link": 2, "list": [1, 2, 6], "local": [3, 6], "locat": 5, "log": [1, 2, 3, 6], "logangrado": 2, "long": 2, "longer": 2, "loss": 6, "lower": [1, 6], "m": 5, "m_k": 4, "magnitud": 6, "mai": [1, 3, 4, 6], "main": [4, 6], "maintain": 4, "major": 4, "make": [2, 4, 5, 6], "manag": 3, "mani": [0, 4, 6], "manual": 3, "marteau": [0, 3, 4, 6], "math": 6, "mathbb": [3, 4, 6], "mathemat": [0, 3, 4, 6], "matrix": [1, 6], "max": 6, "max_distance_xk": 1, "max_fake_successful_step": 0, "max_it": 0, "max_slow_it": 0, "max_unsuccessful_restart": 0, "max_unsuccessful_restarts_tot": 0, "maxfun": [0, 6], "maximum": [0, 1, 6], "mean": [1, 4], "measur": [0, 4], "mechan": 6, "messag": 6, "method": [3, 4, 6], "methven": [3, 6], "michael": 4, "migrat": 2, "min": 6, "min_": [3, 4, 6], "min_chg_model_slop": 0, "min_correl": 0, "minim": [0, 2, 4], "minima": [3, 6], "minimum": [0, 3, 6], "minimum_change_hessian": 0, "minor": 2, "model": [0, 2, 3, 4, 6], "modifi": 6, "modul": 6, "mont": 4, "more": [0, 3, 4], "mor\u00e9": 6, "most": [0, 1, 6], "move": [0, 4, 6], "move_xk": 0, "msg": 6, "multi": 6, "multipl": [2, 3, 4, 6], "multiplicative_noise_level": 0, "must": 6, "myfil": [1, 6], "n": [3, 4, 6], "n_to_print_whole_x_vector": 0, "na06": 4, "nag": 3, "name": 6, "nan": 2, "navig": 5, "nearbi": [3, 6], "necessari": 2, "necessarili": 6, "need": [4, 6], "never": [3, 6], "new": [0, 2, 4], "next": 6, "nf": [1, 6], "nfev": 6, "nois": [3, 6], "noisi": [0, 3, 4], "non": [3, 6], "nonconvex": [3, 4], "none": [0, 6], "nonlinear": [3, 4], "nonquadrat": 6, "nor": 4, "norm": [0, 1, 6], "norm_gk": 1, "norm_sk": 1, "normal": 6, "note": [5, 6], "now": [0, 6], "np": [2, 6], "npt": [1, 6], "nrestart": 6, "nrun": [1, 6], "nsampl": [1, 6], "num_geom_step": 0, "number": [0, 1, 4, 6], "numer": [3, 6], "numericalalgorithmsgroup": 5, "numpi": [2, 5, 6], "nx": [1, 6], "obj": 6, "object": [1, 3, 4], "objfun": [0, 1, 2, 6], "objfun_has_nois": [0, 6], "occur": 6, "older": 5, "oliv": [3, 6], "one": [0, 1, 4, 5, 6], "onli": [0, 1, 6], "onlin": 6, "onto": [0, 6], "oper": [2, 6], "operatornam": 6, "oppos": 0, "opt": 6, "optim": [0, 2, 4], "option": [0, 2, 3, 4, 5], "order": 6, "org": 5, "orthogon": 0, "other": 3, "otherwis": [0, 4, 6], "our": [3, 4, 6], "out": 6, "output": [1, 2, 3], "outsid": [3, 6], "over": [0, 2, 6], "overflowerror": 0, "overlin": 0, "overrid": 0, "overridden": 6, "overview": [3, 6], "p_": [], "packag": [2, 3, 5], "page": 6, "panda": [1, 2, 5, 6], "paper": [0, 3, 4, 6], "param1": 6, "param2": 6, "paramet": [2, 3, 6], "part": [2, 6], "partial": 6, "particularli": [3, 6], "pass": [2, 6], "past": 0, "per": [1, 2, 6], "perform": [0, 2, 3, 4, 6], "pgd_tol": 0, "phase": 6, "physic": 4, "piec": [0, 1], "pip": 3, "pleas": 3, "plu": 3, "point": [1, 2, 3, 4, 6], "pois": 1, "poised": [0, 1], "popul": 1, "possibl": [4, 6], "possibli": 6, "powel": [3, 4], "powell2009": 4, "pp": [0, 3, 4, 6], "practic": 6, "precis": 6, "precondit": 0, "predict": 1, "prefer": 4, "preprint": [0, 3, 4, 6], "present": 5, "preserv": 0, "previou": [0, 6], "previous": 1, "print": [0, 2, 6], "print_funct": 6, "print_progress": 6, "privat": [], "privileg": [], "probabl": 4, "problem": [0, 3, 4, 6], "process": [0, 2, 4], "produc": 6, "progress": [3, 6], "prohibit": 4, "proj": 6, "project": [0, 6], "provid": [0, 3, 4, 6], "public": 3, "pull": [2, 5], "pure": 5, "purpos": 6, "put": 4, "py": [0, 1, 2], "pyarg": 5, "pybobyqa": [0, 1, 5, 6], "pydata": 5, "pyproject": 2, "pytest": 5, "python": [0, 2, 3, 4, 5, 6], "quad": [3, 4, 6], "quadrat": [0, 4, 6], "quit": 0, "quit_on_noise_level": 0, "r": [3, 4, 6], "r1": 6, "r2": 6, "r2024": 6, "r_i": 0, "radii": 0, "radiu": [0, 1, 2, 4, 6], "random": [0, 2, 6], "random_directions_make_orthogon": 0, "random_initial_direct": 0, "rang": 6, "rate": 0, "rather": [2, 6], "ratio": [0, 1], "re": 6, "reach": [0, 6], "reason": 6, "recycl": 0, "reduc": [0, 2], "reduct": 1, "refer": 3, "regim": 2, "region": [2, 3, 4, 5, 6], "regularli": 4, "reigon": 6, "relax": [3, 6], "releas": [2, 3], "remov": [2, 5], "repeat": 4, "repeatedli": 6, "replac": 6, "report": 4, "reproduc": [2, 6], "request": [2, 6], "requir": [0, 2, 3, 4, 6], "rerun": 5, "research": 3, "reset": 2, "residu": 4, "respect": [0, 6], "restart": [1, 2, 3, 6], "restrict": 0, "result": [0, 1, 2, 4, 6], "retriev": 2, "return": [1, 2, 6], "rho": [1, 6], "rho_": 0, "rho_k": [0, 1], "rhobeg": 6, "rhobeg_scale_after_unsuccessful_restart": 0, "rhoend": 6, "rhoend_scal": 0, "risk": 0, "robert": [0, 3, 4, 6], "robust": [0, 3, 4, 6], "root": [], "rosenbrock": 6, "rosenbrock_noisi": 6, "roth": 6, "round": [3, 6], "rounding_error_const": 0, "roundoff": 0, "row": 1, "run": [0, 5, 6], "run_in_parallel": 0, "runtim": 2, "runtimewarn": 6, "s_k": [0, 1, 4], "safeti": [0, 1, 2], "safety_step_thresh": 0, "same": [0, 3, 4, 6], "sampl": 6, "save": [0, 1, 6], "save_diagnostic_info": [0, 1], "save_poised": [0, 1], "save_xk": [0, 1], "saw": 1, "scale": [0, 2, 6], "scale_factor_for_quit": 0, "scaling_within_bound": 6, "scipi": [4, 5, 6], "screen": 0, "script": [2, 6], "search": 6, "second": 6, "section": [0, 1, 2, 6], "see": [1, 3, 5, 6], "seed": [2, 6], "seek": 0, "seek_global_minimum": [0, 2, 6], "sensibl": [2, 6], "sep": 3, "septemb": 3, "set": [0, 1, 2, 6], "setup": [2, 5], "sever": [0, 4, 6], "shape": 6, "sheridan": [3, 6], "shift": [0, 6], "should": [0, 5, 6], "show": 6, "siam": 6, "side": 2, "similarli": 0, "simpl": 3, "simplex": 6, "simul": 4, "sinc": [1, 3, 6], "singl": 6, "singular": 6, "site": 5, "situat": 4, "size": [4, 6], "slightli": [3, 6], "slope": 0, "slow": [1, 2, 3, 6], "slow_it": 1, "small": [3, 4, 6], "smaller": 0, "smallest": 1, "smooth": 0, "so": [0, 1, 2, 3, 6], "soft": [0, 2], "softwar": [0, 3, 4, 5, 6], "soln": [1, 6], "solut": [2, 3, 4, 5, 6], "solv": [0, 1, 3, 4, 6], "solver": [0, 2, 3, 4, 6], "some": [0, 3, 6], "sourc": 5, "space": 4, "specifi": [0, 6], "squar": [1, 3, 4], "stai": 4, "start": [2, 6], "statu": 6, "step": [0, 1, 2, 4, 6], "still": [0, 6], "stochast": [3, 6], "stop": 2, "store": [0, 2], "str": 6, "string": 6, "structur": 3, "subproblem": [0, 2, 4, 5, 6], "success": [0, 1, 6], "successfulli": 6, "sudo": [], "suffici": 6, "sum": 1, "sum_": 6, "supervis": 3, "support": [2, 3, 5, 6], "suppos": 6, "sure": [4, 5], "symmetr": 2, "system": [0, 1, 5, 6], "t": [2, 3, 4, 6], "tabl": 6, "take": [4, 6], "task": 4, "technic": [4, 6], "termin": [1, 3, 6], "test": [3, 6], "text": [0, 1, 3, 4, 6], "textbook": 6, "than": [0, 2, 6], "thei": [0, 4, 6], "them": [2, 4], "therefor": 6, "thi": [0, 1, 2, 3, 4, 5, 6], "thresh_for_slow": 0, "threshold": 0, "through": [0, 2], "time": [0, 1, 4, 6], "to_csv": 1, "toler": 0, "toml": 2, "top": 5, "total": [0, 1, 6], "tr_radiu": 0, "train": 3, "tran": 6, "transact": [0, 3, 4, 6], "trend": 0, "trial": 4, "triangular": 2, "trigger": 0, "troubl": 6, "true": [0, 1, 6], "trust": [2, 3, 4, 5, 6], "trustregion": [2, 5], "try": [0, 3, 6], "tupl": 6, "turn": 1, "two": [0, 4, 6], "type": [1, 4], "unabl": 6, "unconstrain": 6, "under": 3, "underdetermin": 0, "uninstal": 3, "unit": 6, "univers": 4, "unless": 6, "unsuccess": 0, "updat": 2, "upgrad": 5, "upper": [2, 6], "us": [0, 1, 2, 3], "usag": [3, 6], "use_old_fk": 0, "use_restart": 0, "use_soft_restart": 0, "user": [0, 4, 6], "user_param": [0, 1, 6], "usual": 6, "v1": 3, "val1": 6, "val2": 6, "valu": [1, 2, 3, 4, 6], "vari": 0, "variabl": [2, 3, 6], "vast": 4, "vector": [0, 6], "veri": [0, 4], "version": [3, 5], "via": 6, "violat": [3, 6], "visibl": 6, "w": 6, "wa": [1, 3, 5, 6], "wai": [0, 6], "want": 6, "warn": [2, 6], "we": [0, 1, 4, 6], "well": 4, "what": 1, "when": [0, 2, 3, 6], "where": [0, 1, 6], "whether": [0, 6], "which": [0, 1, 2, 3, 4, 6], "why": 6, "wish": [3, 6], "within": [0, 2, 6], "without": [0, 3, 4], "work": 5, "wors": 6, "written": 5, "www": 5, "x": [0, 3, 4, 6], "x0": [0, 1, 6], "x_": [4, 6], "x_0": 6, "x_1": 6, "x_2": 6, "x_b": 0, "x_i": 6, "x_j": 6, "x_k": [0, 4], "xk": 1, "xmin": 6, "y": 6, "y_k": [0, 1], "y_t": 0, "you": [3, 4, 5, 6], "your": [5, 6], "zenodo": 2, "zero": 2}, "titles": ["Advanced Usage", "Diagnostic Information", "Version History", "Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization", "Overview", "Installing Py-BOBYQA", "Using Py-BOBYQA"], "titleterms": {"0": 2, "1": 2, "11": 2, "14": 2, "16": 2, "2": 2, "20": 2, "2018": 2, "2019": 2, "2020": 2, "2021": 2, "2023": 2, "2024": 2, "24": 2, "25": 2, "3": 2, "4": 2, "5": 2, "6": 2, "9": [], "A": 6, "acknowledg": 3, "ad": 6, "advanc": 0, "algorithm": [0, 1, 4], "apr": 2, "argument": 6, "bobyqa": [3, 4, 5, 6], "bound": [3, 6], "constrain": 3, "constraint": [0, 6], "content": 3, "convex": [0, 6], "count": 1, "current": 1, "dec": 2, "deriv": 3, "detail": 4, "diagnost": 1, "evalu": 6, "exampl": 6, "feb": 2, "free": 3, "gener": [0, 6], "global": 6, "histori": 2, "how": 6, "inform": [0, 1], "initi": 0, "instal": 5, "interpol": [0, 1], "iter": 1, "jun": 2, "log": 0, "mai": 2, "manag": 0, "manual": 5, "minim": [3, 6], "model": 1, "more": 6, "multipl": 0, "nois": 0, "noisi": 6, "nonlinear": 6, "object": [0, 6], "optim": [3, 6], "option": 6, "output": [0, 6], "overview": 4, "paramet": 0, "pip": 5, "point": 0, "progress": [0, 1], "py": [3, 4, 5, 6], "refer": [0, 4, 6], "region": [0, 1], "requir": 5, "restart": 0, "sep": 2, "simpl": 6, "slow": 0, "small": 0, "stochast": 0, "termin": 0, "test": 5, "trust": [0, 1], "uninstal": 5, "us": [4, 5, 6], "usag": 0, "valu": 0, "version": 2, "when": 4}}) \ No newline at end of file diff --git a/docs/build/html/userguide.html b/docs/build/html/userguide.html index a1892b7..e7d4a22 100644 --- a/docs/build/html/userguide.html +++ b/docs/build/html/userguide.html @@ -4,7 +4,7 @@ - Using Py-BOBYQA — Py-BOBYQA v1.4.1 documentation + Using Py-BOBYQA — Py-BOBYQA v1.5.0 documentation @@ -15,8 +15,8 @@ - - + + @@ -38,7 +38,7 @@ Py-BOBYQA
    - 1.4.1 + 1.5.0
    @@ -58,6 +58,7 @@
  • Optional Arguments
  • A Simple Example
  • Adding Bounds and More Output
  • +
  • Adding General Convex Constraints
  • Example: Noisy Objective Evaluation
  • Example: Global Optimization
  • References
  • @@ -100,10 +101,16 @@

    Nonlinear MinimizationPy-BOBYQA is designed to solve the local optimization problem

    \[\begin{split}\min_{x\in\mathbb{R}^n} &\quad f(x) \\ -\text{s.t.} &\quad a \leq x \leq b\end{split}\]
    -

    where the bound constraints \(a \leq x \leq b\) are optional. The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). The objective function \(f(x)\) is usually nonlinear and nonquadratic. If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see here for details).

    +\text{s.t.} &\quad a \leq x \leq b\\ +&\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex}\end{split}\]

    +

    where the bound constraints \(a \leq x \leq b\) and general convex constraints \(x \in C\) are optional. +The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). +The general convex constraints are also non-relaxable, but they may be slightly violated at some points from rounding errors. +The objective function \(f(x)\) is usually nonlinear and nonquadratic. +If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see here for details).

    Py-BOBYQA iteratively constructs an interpolation-based model for the objective, and determines a step using a trust-region framework. -For an in-depth technical description of the algorithm see the paper [CFMR2018], and for the global optimization heuristic, see [CRO2022].

    +For an in-depth technical description of the algorithm see the paper [CFMR2018], and for the global optimization heuristic, see [CRO2022]. +For details about how Py-BOBYQA handles general convex constraints, see [R2024].

    How to use Py-BOBYQA

    @@ -151,12 +158,12 @@

    How to use Py-BOBYQAOptional Arguments

    The solve function has several optional arguments which the user may provide:

    -
    pybobyqa.solve(objfun, x0, args=(), bounds=None, npt=None,
    -            rhobeg=None, rhoend=1e-8, maxfun=None, nsamples=None,
    -            user_params=None, objfun_has_noise=False,
    -            seek_global_minimum=False,
    -            scaling_within_bounds=False,
    -            do_logging=True, print_progress=False)
    +
    pybobyqa.solve(objfun, x0, args=(), bounds=None, projections=None,
    +               npt=None, rhobeg=None, rhoend=1e-8, maxfun=None,
    +               nsamples=None, user_params=None, objfun_has_noise=False,
    +               seek_global_minimum=False,
    +               scaling_within_bounds=False,
    +               do_logging=True, print_progress=False)
     
    @@ -164,6 +171,7 @@

    Optional Arguments
  • args - a tuple of extra arguments passed to the objective function.

  • bounds - a tuple (lower, upper) with the vectors \(a\) and \(b\) of lower and upper bounds on \(x\) (default is \(a_i=-10^{20}\) and \(b_i=10^{20}\)). To set bounds for either lower or upper, but not both, pass a tuple (lower, None) or (None, upper).

  • +
  • projections - a list of functions defining the Euclidean projections for each general convex constraint \(C_i\). Each element of the list projections is a function that takes an input vector \(x\) and returns the closest point to \(x\) that is in \(C_i\). An example of using this is given below.

  • npt - the number of interpolation points to use (default is \(2n+1\) for a problem with len(x0)=n if objfun_has_noise=False, otherwise it is set to \((n+1)(n+2)/2\)). Py-BOBYQA requires \(n+1 \leq npt \leq (n+1)(n+2)/2\). Larger values are particularly useful for noisy problems.

  • rhobeg - the initial value of the trust region radius (default is 0.1 if scaling_within_bounds=True, otherwise \(0.1\max(\|x_0\|_{\infty}, 1)\)).

  • rhoend - minimum allowed value of trust region radius, which determines when a successful termination occurs (default is \(10^{-8}\)).

  • @@ -301,6 +309,75 @@

    Adding Bounds and More Output +

    Adding General Convex Constraints

    +

    We can also add more general convex constraints \(x \in C := C_1 \cap \cdots \cap C_n\) to our problem, where +each \(C_i\) is a convex set. To do this, we need to know the Euclidean projection operator for each \(C_i\):

    +
    +\[\operatorname{proj}_{C_i}(x) := \operatorname{argmin}_{y\in C_i} \|y-x\|_2^2.\]
    +

    i.e. given a point \(x\), return the closest point to \(x\) in the set \(C_i\). +There are many examples of simple convex sets \(C_i\) for which this function has a known, simple form, such as:

    +
      +
    • Bound constraints (but since Py-BOBYQA supports this directly, it is better to give these explicitly via the bounds input, as above)

    • +
    • Euclidean ball constraints: \(\|x-c\|_2 \leq r\)

    • +
    • Unit simplex: \(x_i \geq 0\) and \(\sum_{i=1}^{n} x_i \leq 1\)

    • +
    • Linear inequalities: \(a^T x \geq b\)

    • +
    +

    In Py-BOBYQA, set the input projections to be a list of projection functions, one per \(C_i\). +Internally, Py-BOBYQA computes the projection onto the intersection of these sets and the bound constraints +using Dykstra’s projection algorithm.

    +

    For the explicit expressions for the above projections, and more examples, see for example this online database +or Section 6.4.6 of the textbook [B2017].

    +

    As an example, let’s minimize the above Rosenbrock function with different bounds, and with a Euclidean +ball constraint, namely \((x_1-0.5)^2 + (x_2-1)^2 \leq 0.25^2\).

    +

    To do this, we can run

    +
    +
    import numpy as np
    +import pybobyqa
    +
    +# Define the objective function
    +def rosenbrock(x):
    +    return 100.0 * (x[1] - x[0] ** 2) ** 2 + (1.0 - x[0]) ** 2
    +
    +# Define the starting point
    +x0 = np.array([-1.2, 1.0])
    +
    +# Define bound constraints (lower <= x <= upper)
    +lower = np.array([0.7, -2.0])
    +upper = np.array([1.0, 2.0])
    +
    +# Define the ball constraint ||x-center|| <= radius, and its projection operator
    +center = np.array([0.5, 1.0])
    +radius = 0.25
    +ball_proj = lambda x: center + (radius/max(np.linalg.norm(x-center), radius)) * (x-center)
    +
    +# Call Py-BOBYQA (with bounds and projection operator)
    +# Note: it is better to provide bounds explicitly, instead of using the corresponding
    +#       projection function
    +# Note: input 'projections' must be a list of projection functions
    +soln = pybobyqa.solve(rosenbrock, x0, bounds=(lower,upper), projections=[ball_proj])
    +
    +print(soln)
    +
    +
    +
    +

    Py-BOBYQA correctly finds the solution to the constrained problem:

    +
    +
    ****** Py-BOBYQA Results ******
    +Solution xmin = [0.70424386 0.85583188]
    +Objective value f(xmin) = 13.03829114
    +Needed 25 objective evaluations (at 25 points)
    +Approximate gradient = [-101.9667031    71.97449424]
    +Approximate Hessian = [[ 253.11858775 -279.39193327]
    + [-279.39193327  201.49725358]]
    +Exit flag = 0
    +Success: rho has reached rhoend
    +******************************
    +
    +
    +
    +

    Just like for bound constraints, Py-BOBYQA will automatically ensure the starting point is feasible with respect to all constraints (bounds and general convex constraints).

    +

    Example: Noisy Objective Evaluation

    As described in Overview, derivative-free algorithms such as Py-BOBYQA are particularly useful when objfun has noise. Let’s modify the previous example to include random noise in our objective evaluation, and compare it to a derivative-based solver:

    @@ -483,7 +560,7 @@

    Example: Global Optimizationseek_global_minimum flag helped Py-BOBYQA escape the local minimum from the first run, and find the global minimum. More details are given in [CRO2022].

    +

    As we can see, the seek_global_minimum flag helped Py-BOBYQA escape the local minimum from the first run, and find the global minimum. More details are given in [CRO2022].

    References

    @@ -494,9 +571,17 @@

    References [CRO2022] -(1,2) +(1,2)

    Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, Escaping local minima with derivative-free methods: a numerical investigation, Optimization, 71:8 (2022), pp. 2343-2373. [arXiv preprint: 1812.11343]

    +
    +[R2024] +

    Lindon Roberts, Model Construction for Convex-Constrained Derivative-Free Optimization, arXiv preprint arXiv:2403.14960 (2024).

    +
    +
    +[B2017] +

    Amir Beck, First-Order Methods in Optimization, SIAM (2017).

    +
    diff --git a/docs/build/latex/Py-BOBYQA.aux b/docs/build/latex/Py-BOBYQA.aux index ab79441..45294d4 100644 --- a/docs/build/latex/Py-BOBYQA.aux +++ b/docs/build/latex/Py-BOBYQA.aux @@ -35,8 +35,6 @@ \newlabel{install:testing}{{1.4}{4}{Testing}{section.1.4}{}} \@writefile{toc}{\contentsline {section}{\numberline {1.5}Uninstallation}{4}{section.1.5}\protected@file@percent } \newlabel{install:uninstallation}{{1.5}{4}{Uninstallation}{section.1.5}{}} -\citation{info:powell2009} -\citation{userguide:cfmr2018} \@writefile{toc}{\contentsline {chapter}{\numberline {2}Overview}{5}{chapter.2}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} @@ -46,10 +44,13 @@ \newlabel{info:when-to-use-py-bobyqa}{{2.1}{5}{When to use Py\sphinxhyphen {}BOBYQA}{section.2.1}{}} \@writefile{toc}{\contentsline {section}{\numberline {2.2}Details of the Py\sphinxhyphen {}BOBYQA Algorithm}{5}{section.2.2}\protected@file@percent } \newlabel{info:details-of-the-py-bobyqa-algorithm}{{2.2}{5}{Details of the Py\sphinxhyphen {}BOBYQA Algorithm}{section.2.2}{}} +\citation{info:powell2009} +\citation{userguide:cfmr2018} \@writefile{toc}{\contentsline {section}{\numberline {2.3}References}{6}{section.2.3}\protected@file@percent } \newlabel{info:references}{{2.3}{6}{References}{section.2.3}{}} \citation{userguide:cfmr2018} \citation{userguide:cro2022} +\citation{userguide:r2024} \@writefile{toc}{\contentsline {chapter}{\numberline {3}Using Py\sphinxhyphen {}BOBYQA}{7}{chapter.3}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} @@ -65,85 +66,94 @@ \newlabel{userguide:a-simple-example}{{3.4}{10}{A Simple Example}{section.3.4}{}} \@writefile{toc}{\contentsline {section}{\numberline {3.5}Adding Bounds and More Output}{11}{section.3.5}\protected@file@percent } \newlabel{userguide:adding-bounds-and-more-output}{{3.5}{11}{Adding Bounds and More Output}{section.3.5}{}} -\@writefile{toc}{\contentsline {section}{\numberline {3.6}Example: Noisy Objective Evaluation}{12}{section.3.6}\protected@file@percent } -\newlabel{userguide:example-noisy-objective-evaluation}{{3.6}{12}{Example: Noisy Objective Evaluation}{section.3.6}{}} -\@writefile{toc}{\contentsline {section}{\numberline {3.7}Example: Global Optimization}{14}{section.3.7}\protected@file@percent } -\newlabel{userguide:example-global-optimization}{{3.7}{14}{Example: Global Optimization}{section.3.7}{}} +\citation{userguide:b2017} +\@writefile{toc}{\contentsline {section}{\numberline {3.6}Adding General Convex Constraints}{12}{section.3.6}\protected@file@percent } +\newlabel{userguide:adding-general-convex-constraints}{{3.6}{12}{Adding General Convex Constraints}{section.3.6}{}} +\@writefile{toc}{\contentsline {section}{\numberline {3.7}Example: Noisy Objective Evaluation}{13}{section.3.7}\protected@file@percent } +\newlabel{userguide:example-noisy-objective-evaluation}{{3.7}{13}{Example: Noisy Objective Evaluation}{section.3.7}{}} +\@writefile{toc}{\contentsline {section}{\numberline {3.8}Example: Global Optimization}{15}{section.3.8}\protected@file@percent } +\newlabel{userguide:example-global-optimization}{{3.8}{15}{Example: Global Optimization}{section.3.8}{}} \citation{userguide:cro2022} -\@writefile{toc}{\contentsline {section}{\numberline {3.8}References}{16}{section.3.8}\protected@file@percent } -\newlabel{userguide:references}{{3.8}{16}{References}{section.3.8}{}} +\@writefile{toc}{\contentsline {section}{\numberline {3.9}References}{17}{section.3.9}\protected@file@percent } +\newlabel{userguide:references}{{3.9}{17}{References}{section.3.9}{}} \citation{userguide:cfmr2018} -\@writefile{toc}{\contentsline {chapter}{\numberline {4}Advanced Usage}{17}{chapter.4}\protected@file@percent } +\@writefile{toc}{\contentsline {chapter}{\numberline {4}Advanced Usage}{19}{chapter.4}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} -\newlabel{advanced:advanced-usage}{{4}{17}{Advanced Usage}{chapter.4}{}} -\newlabel{advanced::doc}{{4}{17}{Advanced Usage}{chapter.4}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.1}General Algorithm Parameters}{17}{section.4.1}\protected@file@percent } -\newlabel{advanced:general-algorithm-parameters}{{4.1}{17}{General Algorithm Parameters}{section.4.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.2}Logging and Output}{17}{section.4.2}\protected@file@percent } -\newlabel{advanced:logging-and-output}{{4.2}{17}{Logging and Output}{section.4.2}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.3}Initialization of Points}{18}{section.4.3}\protected@file@percent } -\newlabel{advanced:initialization-of-points}{{4.3}{18}{Initialization of Points}{section.4.3}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.4}Trust Region Management}{18}{section.4.4}\protected@file@percent } -\newlabel{advanced:trust-region-management}{{4.4}{18}{Trust Region Management}{section.4.4}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.5}Termination on Small Objective Value}{18}{section.4.5}\protected@file@percent } -\newlabel{advanced:termination-on-small-objective-value}{{4.5}{18}{Termination on Small Objective Value}{section.4.5}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.6}Termination on Slow Progress}{18}{section.4.6}\protected@file@percent } -\newlabel{advanced:termination-on-slow-progress}{{4.6}{18}{Termination on Slow Progress}{section.4.6}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.7}Stochastic Noise Information}{19}{section.4.7}\protected@file@percent } -\newlabel{advanced:stochastic-noise-information}{{4.7}{19}{Stochastic Noise Information}{section.4.7}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.8}Interpolation Management}{19}{section.4.8}\protected@file@percent } -\newlabel{advanced:interpolation-management}{{4.8}{19}{Interpolation Management}{section.4.8}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.9}Multiple Restarts}{19}{section.4.9}\protected@file@percent } -\newlabel{advanced:multiple-restarts}{{4.9}{19}{Multiple Restarts}{section.4.9}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4.10}References}{20}{section.4.10}\protected@file@percent } -\newlabel{advanced:references}{{4.10}{20}{References}{section.4.10}{}} -\@writefile{toc}{\contentsline {chapter}{\numberline {5}Diagnostic Information}{21}{chapter.5}\protected@file@percent } +\newlabel{advanced:advanced-usage}{{4}{19}{Advanced Usage}{chapter.4}{}} +\newlabel{advanced::doc}{{4}{19}{Advanced Usage}{chapter.4}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.1}General Algorithm Parameters}{19}{section.4.1}\protected@file@percent } +\newlabel{advanced:general-algorithm-parameters}{{4.1}{19}{General Algorithm Parameters}{section.4.1}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.2}Logging and Output}{19}{section.4.2}\protected@file@percent } +\newlabel{advanced:logging-and-output}{{4.2}{19}{Logging and Output}{section.4.2}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.3}Initialization of Points}{20}{section.4.3}\protected@file@percent } +\newlabel{advanced:initialization-of-points}{{4.3}{20}{Initialization of Points}{section.4.3}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.4}Trust Region Management}{20}{section.4.4}\protected@file@percent } +\newlabel{advanced:trust-region-management}{{4.4}{20}{Trust Region Management}{section.4.4}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.5}Termination on Small Objective Value}{20}{section.4.5}\protected@file@percent } +\newlabel{advanced:termination-on-small-objective-value}{{4.5}{20}{Termination on Small Objective Value}{section.4.5}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.6}Termination on Slow Progress}{20}{section.4.6}\protected@file@percent } +\newlabel{advanced:termination-on-slow-progress}{{4.6}{20}{Termination on Slow Progress}{section.4.6}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.7}Stochastic Noise Information}{21}{section.4.7}\protected@file@percent } +\newlabel{advanced:stochastic-noise-information}{{4.7}{21}{Stochastic Noise Information}{section.4.7}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.8}Interpolation Management}{21}{section.4.8}\protected@file@percent } +\newlabel{advanced:interpolation-management}{{4.8}{21}{Interpolation Management}{section.4.8}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.9}Multiple Restarts}{21}{section.4.9}\protected@file@percent } +\newlabel{advanced:multiple-restarts}{{4.9}{21}{Multiple Restarts}{section.4.9}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.10}General Convex Constraints}{22}{section.4.10}\protected@file@percent } +\newlabel{advanced:general-convex-constraints}{{4.10}{22}{General Convex Constraints}{section.4.10}{}} +\@writefile{toc}{\contentsline {section}{\numberline {4.11}References}{22}{section.4.11}\protected@file@percent } +\newlabel{advanced:references}{{4.11}{22}{References}{section.4.11}{}} +\@writefile{toc}{\contentsline {chapter}{\numberline {5}Diagnostic Information}{23}{chapter.5}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} -\newlabel{diagnostic:diagnostic-information}{{5}{21}{Diagnostic Information}{chapter.5}{}} -\newlabel{diagnostic::doc}{{5}{21}{Diagnostic Information}{chapter.5}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.1}Current Iterate}{21}{section.5.1}\protected@file@percent } -\newlabel{diagnostic:current-iterate}{{5.1}{21}{Current Iterate}{section.5.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.2}Trust Region}{21}{section.5.2}\protected@file@percent } -\newlabel{diagnostic:trust-region}{{5.2}{21}{Trust Region}{section.5.2}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.3}Model Interpolation}{22}{section.5.3}\protected@file@percent } -\newlabel{diagnostic:model-interpolation}{{5.3}{22}{Model Interpolation}{section.5.3}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.4}Iteration Count}{22}{section.5.4}\protected@file@percent } -\newlabel{diagnostic:iteration-count}{{5.4}{22}{Iteration Count}{section.5.4}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.5}Algorithm Progress}{22}{section.5.5}\protected@file@percent } -\newlabel{diagnostic:algorithm-progress}{{5.5}{22}{Algorithm Progress}{section.5.5}{}} -\@writefile{toc}{\contentsline {chapter}{\numberline {6}Version History}{23}{chapter.6}\protected@file@percent } +\newlabel{diagnostic:diagnostic-information}{{5}{23}{Diagnostic Information}{chapter.5}{}} +\newlabel{diagnostic::doc}{{5}{23}{Diagnostic Information}{chapter.5}{}} +\@writefile{toc}{\contentsline {section}{\numberline {5.1}Current Iterate}{23}{section.5.1}\protected@file@percent } +\newlabel{diagnostic:current-iterate}{{5.1}{23}{Current Iterate}{section.5.1}{}} +\@writefile{toc}{\contentsline {section}{\numberline {5.2}Trust Region}{23}{section.5.2}\protected@file@percent } +\newlabel{diagnostic:trust-region}{{5.2}{23}{Trust Region}{section.5.2}{}} +\@writefile{toc}{\contentsline {section}{\numberline {5.3}Model Interpolation}{24}{section.5.3}\protected@file@percent } +\newlabel{diagnostic:model-interpolation}{{5.3}{24}{Model Interpolation}{section.5.3}{}} +\@writefile{toc}{\contentsline {section}{\numberline {5.4}Iteration Count}{24}{section.5.4}\protected@file@percent } +\newlabel{diagnostic:iteration-count}{{5.4}{24}{Iteration Count}{section.5.4}{}} +\@writefile{toc}{\contentsline {section}{\numberline {5.5}Algorithm Progress}{24}{section.5.5}\protected@file@percent } +\newlabel{diagnostic:algorithm-progress}{{5.5}{24}{Algorithm Progress}{section.5.5}{}} +\@writefile{toc}{\contentsline {chapter}{\numberline {6}Version History}{25}{chapter.6}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} -\newlabel{history:version-history}{{6}{23}{Version History}{chapter.6}{}} -\newlabel{history::doc}{{6}{23}{Version History}{chapter.6}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.1}Version 1.0 (6 Feb 2018)}{23}{section.6.1}\protected@file@percent } -\newlabel{history:version-1-0-6-feb-2018}{{6.1}{23}{Version 1.0 (6 Feb 2018)}{section.6.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.2}Version 1.0.1 (20 Feb 2018)}{23}{section.6.2}\protected@file@percent } -\newlabel{history:version-1-0-1-20-feb-2018}{{6.2}{23}{Version 1.0.1 (20 Feb 2018)}{section.6.2}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.3}Version 1.0.2 (20 Jun 2018)}{23}{section.6.3}\protected@file@percent } -\newlabel{history:version-1-0-2-20-jun-2018}{{6.3}{23}{Version 1.0.2 (20 Jun 2018)}{section.6.3}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.4}Version 1.1 (24 Dec 2018)}{23}{section.6.4}\protected@file@percent } -\newlabel{history:version-1-1-24-dec-2018}{{6.4}{23}{Version 1.1 (24 Dec 2018)}{section.6.4}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.5}Version 1.1.1 (5 Apr 2019)}{24}{section.6.5}\protected@file@percent } -\newlabel{history:version-1-1-1-5-apr-2019}{{6.5}{24}{Version 1.1.1 (5 Apr 2019)}{section.6.5}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.6}Version 1.2 (25 Feb 2020)}{24}{section.6.6}\protected@file@percent } -\newlabel{history:version-1-2-25-feb-2020}{{6.6}{24}{Version 1.2 (25 Feb 2020)}{section.6.6}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.7}Version 1.3 (14 Apr 2021)}{24}{section.6.7}\protected@file@percent } -\newlabel{history:version-1-3-14-apr-2021}{{6.7}{24}{Version 1.3 (14 Apr 2021)}{section.6.7}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.8}Version 1.4 (16 May 2023)}{24}{section.6.8}\protected@file@percent } -\newlabel{history:version-1-4-16-may-2023}{{6.8}{24}{Version 1.4 (16 May 2023)}{section.6.8}{}} -\@writefile{toc}{\contentsline {section}{\numberline {6.9}Version 1.4.1 (11 Apr 2024)}{24}{section.6.9}\protected@file@percent } -\newlabel{history:version-1-4-1-11-apr-2024}{{6.9}{24}{Version 1.4.1 (11 Apr 2024)}{section.6.9}{}} -\@writefile{toc}{\contentsline {chapter}{\numberline {7}Acknowledgements}{25}{chapter.7}\protected@file@percent } +\newlabel{history:version-history}{{6}{25}{Version History}{chapter.6}{}} +\newlabel{history::doc}{{6}{25}{Version History}{chapter.6}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.1}Version 1.0 (6 Feb 2018)}{25}{section.6.1}\protected@file@percent } +\newlabel{history:version-1-0-6-feb-2018}{{6.1}{25}{Version 1.0 (6 Feb 2018)}{section.6.1}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.2}Version 1.0.1 (20 Feb 2018)}{25}{section.6.2}\protected@file@percent } +\newlabel{history:version-1-0-1-20-feb-2018}{{6.2}{25}{Version 1.0.1 (20 Feb 2018)}{section.6.2}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.3}Version 1.0.2 (20 Jun 2018)}{25}{section.6.3}\protected@file@percent } +\newlabel{history:version-1-0-2-20-jun-2018}{{6.3}{25}{Version 1.0.2 (20 Jun 2018)}{section.6.3}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.4}Version 1.1 (24 Dec 2018)}{25}{section.6.4}\protected@file@percent } +\newlabel{history:version-1-1-24-dec-2018}{{6.4}{25}{Version 1.1 (24 Dec 2018)}{section.6.4}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.5}Version 1.1.1 (5 Apr 2019)}{26}{section.6.5}\protected@file@percent } +\newlabel{history:version-1-1-1-5-apr-2019}{{6.5}{26}{Version 1.1.1 (5 Apr 2019)}{section.6.5}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.6}Version 1.2 (25 Feb 2020)}{26}{section.6.6}\protected@file@percent } +\newlabel{history:version-1-2-25-feb-2020}{{6.6}{26}{Version 1.2 (25 Feb 2020)}{section.6.6}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.7}Version 1.3 (14 Apr 2021)}{26}{section.6.7}\protected@file@percent } +\newlabel{history:version-1-3-14-apr-2021}{{6.7}{26}{Version 1.3 (14 Apr 2021)}{section.6.7}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.8}Version 1.4 (16 May 2023)}{26}{section.6.8}\protected@file@percent } +\newlabel{history:version-1-4-16-may-2023}{{6.8}{26}{Version 1.4 (16 May 2023)}{section.6.8}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.9}Version 1.4.1 (11 Apr 2024)}{26}{section.6.9}\protected@file@percent } +\newlabel{history:version-1-4-1-11-apr-2024}{{6.9}{26}{Version 1.4.1 (11 Apr 2024)}{section.6.9}{}} +\@writefile{toc}{\contentsline {section}{\numberline {6.10}Version 1.5.0 (16 Sep 2024)}{27}{section.6.10}\protected@file@percent } +\newlabel{history:version-1-5-0-16-sep-2024}{{6.10}{27}{Version 1.5.0 (16 Sep 2024)}{section.6.10}{}} +\@writefile{toc}{\contentsline {chapter}{\numberline {7}Acknowledgements}{29}{chapter.7}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} -\newlabel{index:acknowledgements}{{7}{25}{Acknowledgements}{chapter.7}{}} +\newlabel{index:acknowledgements}{{7}{29}{Acknowledgements}{chapter.7}{}} \bibcite{info:cfmr2018}{CFMR2018} \bibcite{info:powell2009}{Powell2009} \bibcite{userguide:cfmr2018}{CFMR2018} \bibcite{userguide:cro2022}{CRO2022} +\bibcite{userguide:r2024}{R2024} +\bibcite{userguide:b2017}{B2017} \bibcite{advanced:cfmr2018}{CFMR2018} -\@writefile{toc}{\contentsline {chapter}{Bibliography}{27}{chapter*.3}\protected@file@percent } -\gdef \@abspage@last{31} +\@writefile{toc}{\contentsline {chapter}{Bibliography}{31}{chapter*.3}\protected@file@percent } +\gdef \@abspage@last{35} diff --git a/docs/build/latex/Py-BOBYQA.fdb_latexmk b/docs/build/latex/Py-BOBYQA.fdb_latexmk index c846de5..2b0c5de 100644 --- a/docs/build/latex/Py-BOBYQA.fdb_latexmk +++ b/docs/build/latex/Py-BOBYQA.fdb_latexmk @@ -1,11 +1,12 @@ # Fdb version 3 -["makeindex Py-BOBYQA.idx"] 1582610283 "Py-BOBYQA.idx" "Py-BOBYQA.ind" "Py-BOBYQA" 1712819610 - "Py-BOBYQA.idx" 1712819609 0 d41d8cd98f00b204e9800998ecf8427e "pdflatex" +["makeindex Py-BOBYQA.idx"] 1582610283 "Py-BOBYQA.idx" "Py-BOBYQA.ind" "Py-BOBYQA" 1726458096 + "Py-BOBYQA.idx" 1726458094 0 d41d8cd98f00b204e9800998ecf8427e "pdflatex" (generated) "Py-BOBYQA.ilg" "Py-BOBYQA.ind" -["pdflatex"] 1712819605 "Py-BOBYQA.tex" "Py-BOBYQA.pdf" "Py-BOBYQA" 1712819610 +["pdflatex"] 1726458090 "Py-BOBYQA.tex" "Py-BOBYQA.pdf" "Py-BOBYQA" 1726458096 "/etc/texmf/web2c/texmf.cnf" 1712803173 475 c0e671620eb5563b2130f56340a5fde8 "" + "/usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc" 1165713224 4850 80dc9bab7f31fb78a000ccfed0e27cab "" "/usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" "/usr/share/texlive/texmf-dist/fonts/tfm/jknappen/ec/ecrm1000.tfm" 1136768653 3584 adb004a0c8e7c46ee66cad73671f37b4 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" @@ -20,10 +21,15 @@ "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr17.tfm" 1136768653 1292 296a67155bdbfc32aa9c636f21e91433 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm" 1136768653 1124 6c73e740cf17375f03eec0ee63599741 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtcxsl.tfm" 1136768653 1556 6839f760c7ccf5ed87b9284aa8d08287 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmr.tfm" 1136768653 4452 0fd0a792eaab7113e4d4f1b941ff0367 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmro.tfm" 1136768653 4660 1e82d17cfff3320dd793f61bbdea044f "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbtt.tfm" 1136768653 1436 f00b2a275be56a8355f5c3b07a5a7a4c "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm" 1136768653 1384 8943063000d26272532f74ca134dfecd "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xttsl.tfm" 1136768653 1624 fb8f48c6308ace0a799f9278aba03e18 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxsl.tfm" 1136768653 1680 1b5370f9965e05efeedc424f97016c00 "" "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxtt.tfm" 1136768653 1292 b1fa6b76e852700625b1941c32e1e42e "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb" 1248133631 30251 6afa5cb1d0204815a708a080681d4674 "" "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb" 1248133631 36299 5f9df58c2139e7edcf37c8fca4bd384d "" "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi5.pfb" 1248133631 37912 77d683123f92148345f3fc36a38d9ab1 "" "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb" 1248133631 36281 c355509802a035cadc5f15869451dcee "" @@ -38,6 +44,8 @@ "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xbtt.pfb" 1136849748 26580 8886cc7827569e05fd10df25f221aef6 "" "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb" 1136849748 26301 f08b3c26ea42c3177a262c2ac37d6a91 "" "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/tcxtt.pfb" 1136849748 19223 eef9d7a2591262b80fbbebb9e94dc374 "" + "/usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmr8a.pfb" 1136849748 46026 6dab18b61c907687b520c72847215a68 "" + "/usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/tcxsl.vf" 1136768653 1016 4e04d2a05c869fe9fcb3048945c37102 "" "/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii" 1461363279 71627 94eb9990bed73c364d7f53f960cc8c5b "" "/usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty" 1575674566 24708 5584a51a7101caf7e6bbf1fc27d8f7b1 "" "/usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf" 1496785618 7008 9ff5fdcc865b01beca2b0fe4a46231d4 "" @@ -89,6 +97,9 @@ "/usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty" 1640123156 44023 c6f2f55a2bb9630fba10bfd488a5addd "" "/usr/share/texlive/texmf-dist/tex/latex/float/float.sty" 1137110151 6749 16d2656a1984957e674b149555f1ea1d "" "/usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty" 1292029257 19488 fdd52eb173b3197d748e1ec25acb042f "" + "/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty" 1622837620 1796 b613081fb73f572330a4c23f125aae34 "" + "/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def" 1622837620 107888 1633cdc16ba7668f2631413ef15f922e "" + "/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty" 1622837620 7431 6f96168cb69798b45fb68c05af9b56b0 "" "/usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty" 1338588508 22449 7ec15c16d0d66790f28e90343c5434a3 "" "/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty" 1578002852 41601 9cf6c5257b1bc7af01a58859749dd37a "" "/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg" 1459978653 1213 620bba36b25224fa9b7e1ccb4ecb76fd "" @@ -108,6 +119,9 @@ "/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def" 1623096352 117004 86586f287ddfad919a0a4bd68934277a "" "/usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty" 1602274869 22521 d2fceb764a442a2001d257ef11db7618 "" "/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def" 1642022539 29921 f0f4f870357ebfb8fe58ed9ed4ee9b92 "" + "/usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty" 1642805374 6107 429b3b241150e53f86ce666eb492861e "" + "/usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty" 1642022539 4674 ac560df2ef76ab2c406a4948a48f79f8 "" + "/usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty" 1642022539 6758 7d9d899cbbfc962fbc4bb93f4c69eec2 "" "/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg" 1279039959 678 4792914a8f45be57bb98413425e4c7af "" "/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty" 1575499565 5766 13a9e8766c47f30327caf893ece86ac8 "" "/usr/share/texlive/texmf-dist/tex/latex/mmap/oml.cmap" 1215649417 1866 c1c12138091b4a8edd4a24a940e6f792 "" @@ -157,32 +171,32 @@ "/usr/share/texmf/web2c/texmf.cnf" 1644012257 39432 7155514e09a3d69036fac785183a21c2 "" "/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map" 1712803388 4234243 4a42437c56f0785ccfd4e39da48c38dc "" "/var/lib/texmf/web2c/pdftex/pdflatex.fmt" 1712803393 1405649 09028a54f5e9b3274f4344c937e7ff76 "" - "Py-BOBYQA.aux" 1712819610 12265 8fd57504ca800691d550ffadb6f27dd4 "pdflatex" - "Py-BOBYQA.ind" 1587347533 0 d41d8cd98f00b204e9800998ecf8427e "makeindex Py-BOBYQA.idx" - "Py-BOBYQA.out" 1712819610 7797 99197217dbf95bfa156c10f98cdb064e "pdflatex" - "Py-BOBYQA.tex" 1712819599 77795 d1b74ebcabe80641f8ce276e13b1d616 "" - "Py-BOBYQA.toc" 1712819610 3960 bdc489e296b6e4a31a501400238ecc10 "pdflatex" - "sphinx.sty" 1712818543 44560 f9fbf51072c954d129c9bd5284cc4ccf "" - "sphinxhighlight.sty" 1712819600 7553 83fb52292c17957d9f4aadcb28c57a87 "" - "sphinxlatexadmonitions.sty" 1712818543 10989 c38302e64c2bb47779f086869b246760 "" - "sphinxlatexcontainers.sty" 1712818543 901 d3a3a1b7b2547f47ade2499350b5c420 "" - "sphinxlatexgraphics.sty" 1712818543 4840 a9578332b6f3b35e198751fb632c9b79 "" - "sphinxlatexindbibtoc.sty" 1712818543 2066 b93f8504d02f6337fde3074b179de55e "" - "sphinxlatexlists.sty" 1712818543 5139 c2de2a1d98d3c6ceedfe46505abd3c07 "" - "sphinxlatexliterals.sty" 1712818543 46048 2b66269d0ecf11768a14b5de4ddf9051 "" - "sphinxlatexnumfig.sty" 1712818543 4532 3633caf84afa1a98e1a060b7868202bb "" - "sphinxlatexobjects.sty" 1712818543 14354 7db81294dd9bf70f65d5cc34221a0b86 "" - "sphinxlatexshadowbox.sty" 1712818543 5066 97a2be0d1dfdc98548b7461f1949b95f "" - "sphinxlatexstyleheadings.sty" 1712818543 3445 a1582a5f3b336dcffa71b5ca3d8fc31f "" - "sphinxlatexstylepage.sty" 1712818543 3064 abce6c3018a84afee0afb08a431944ea "" - "sphinxlatexstyletext.sty" 1712818543 8589 a7e8f95eb4fef6c1cd2623cd417d6467 "" - "sphinxlatextables.sty" 1712818543 57830 16f2773b765508003aec5d08680f39b9 "" - "sphinxmanual.cls" 1712818543 4241 7b0d7a37df7b5715fb0dbd585c52ecdb "" - "sphinxmessages.sty" 1712819600 745 3f5fcd6cdd7964ed608767954a8ced6f "" - "sphinxoptionsgeometry.sty" 1712818543 2061 47bb34b8ed8a78823eb0c886abfb9f4d "" - "sphinxoptionshyperref.sty" 1712818543 1094 79beb8b8a3f10784f8cce804e0f9d3aa "" - "sphinxpackageboxes.sty" 1712818543 36615 1d74c63e665ede6c648fa08c42ea70fb "" - "sphinxpackagefootnote.sty" 1712818543 15254 d93f70cf000a9adb198015bf1b2f136c "" + "Py-BOBYQA.aux" 1726458096 13102 fe3c48df0a1188ce7d598103bfe19ae7 "pdflatex" + "Py-BOBYQA.ind" 1725497670 0 d41d8cd98f00b204e9800998ecf8427e "makeindex Py-BOBYQA.idx" + "Py-BOBYQA.out" 1726458096 8427 6b1b345f82cffc2d0fe36bfd7064b373 "pdflatex" + "Py-BOBYQA.tex" 1726458083 85873 584efc5d48381ffcd8600fd89c2fbb46 "" + "Py-BOBYQA.toc" 1726458096 4233 9a8bd0f7eab55b0b5cb6eebb91fdcd1a "pdflatex" + "sphinx.sty" 1725497883 50659 6d393be3f369a7862f0b19a359f1ab89 "" + "sphinxhighlight.sty" 1726458084 7553 83fb52292c17957d9f4aadcb28c57a87 "" + "sphinxlatexadmonitions.sty" 1725497883 18222 f3bfd316b630ed188fcc20bf320acafe "" + "sphinxlatexcontainers.sty" 1725497671 901 d3a3a1b7b2547f47ade2499350b5c420 "" + "sphinxlatexgraphics.sty" 1725497671 4840 a9578332b6f3b35e198751fb632c9b79 "" + "sphinxlatexindbibtoc.sty" 1725497671 2066 b93f8504d02f6337fde3074b179de55e "" + "sphinxlatexlists.sty" 1725497671 5139 c2de2a1d98d3c6ceedfe46505abd3c07 "" + "sphinxlatexliterals.sty" 1725497883 45679 3890d40120836f081d8920e14485124f "" + "sphinxlatexnumfig.sty" 1725497671 4532 3633caf84afa1a98e1a060b7868202bb "" + "sphinxlatexobjects.sty" 1725497671 14354 7db81294dd9bf70f65d5cc34221a0b86 "" + "sphinxlatexshadowbox.sty" 1725497671 5066 97a2be0d1dfdc98548b7461f1949b95f "" + "sphinxlatexstyleheadings.sty" 1725497671 3445 a1582a5f3b336dcffa71b5ca3d8fc31f "" + "sphinxlatexstylepage.sty" 1725497671 3064 abce6c3018a84afee0afb08a431944ea "" + "sphinxlatexstyletext.sty" 1725497883 6881 543f3cecccc7dccac396b5720cccf443 "" + "sphinxlatextables.sty" 1725497883 57644 2253ce149b29042948a000d2dbf50b50 "" + "sphinxmanual.cls" 1725497671 4241 7b0d7a37df7b5715fb0dbd585c52ecdb "" + "sphinxmessages.sty" 1726458084 745 3f5fcd6cdd7964ed608767954a8ced6f "" + "sphinxoptionsgeometry.sty" 1725497671 2061 47bb34b8ed8a78823eb0c886abfb9f4d "" + "sphinxoptionshyperref.sty" 1725497671 1094 79beb8b8a3f10784f8cce804e0f9d3aa "" + "sphinxpackageboxes.sty" 1725497883 36106 1be2053eb1cb9b083b3a75e3657bcb24 "" + "sphinxpackagefootnote.sty" 1725497883 15330 2fb656b6ce8cd1f6aba2d1c508fb51e5 "" (generated) "Py-BOBYQA.aux" "Py-BOBYQA.idx" diff --git a/docs/build/latex/Py-BOBYQA.fls b/docs/build/latex/Py-BOBYQA.fls index b3f46c6..5cd7b37 100644 --- a/docs/build/latex/Py-BOBYQA.fls +++ b/docs/build/latex/Py-BOBYQA.fls @@ -1,4 +1,4 @@ -PWD /mnt/c/Users/lindo/Documents/git/pybobyqa/docs/build/latex +PWD /mnt/c/Users/lindo/Documents/git/pybobyqa_convex_cons/docs/build/latex INPUT /etc/texmf/web2c/texmf.cnf INPUT /usr/share/texmf/web2c/texmf.cnf INPUT /usr/share/texlive/texmf-dist/web2c/texmf.cnf @@ -289,8 +289,6 @@ INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty -INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg @@ -300,6 +298,8 @@ INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty INPUT ./sphinxoptionshyperref.sty INPUT sphinxoptionshyperref.sty INPUT ./sphinxoptionshyperref.sty @@ -1038,6 +1038,67 @@ INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty @@ -1161,14 +1222,19 @@ INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm -INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xttsl.tfm INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbtt.tfm INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txtt.fd INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txtt.fd INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxtt.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xttsl.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/tcxsl.tfm INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmr.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/vf/public/txfonts/tcxsl.vf +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmro.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtcxsl.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/rtxptmr.tfm INPUT ./Py-BOBYQA.ind INPUT Py-BOBYQA.ind INPUT ./Py-BOBYQA.ind @@ -1176,8 +1242,10 @@ INPUT Py-BOBYQA.ind INPUT Py-BOBYQA.aux INPUT ./Py-BOBYQA.out INPUT ./Py-BOBYQA.out +INPUT /usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc INPUT /usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ts1.enc INPUT /usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ec.enc +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi5.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb @@ -1198,3 +1266,4 @@ INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xbtt.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/tcxtt.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmr8a.pfb diff --git a/docs/build/latex/Py-BOBYQA.log b/docs/build/latex/Py-BOBYQA.log index 664df97..3eee217 100644 --- a/docs/build/latex/Py-BOBYQA.log +++ b/docs/build/latex/Py-BOBYQA.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2024.4.11) 11 APR 2024 17:13 +This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2024.4.11) 16 SEP 2024 13:41 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -168,7 +168,7 @@ Package: fncychap 2007/07/30 v1.34 LaTeX package (Revised chapters) \c@AlphaCnt=\count274 \c@AlphaDecCnt=\count275 ) (./sphinx.sty -Package: sphinx 2023/03/19 v6.2.0 LaTeX package (Sphinx markup) +Package: sphinx 2024/07/01 v7.4.0 Sphinx LaTeX package (sphinx-doc) (/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty Package: xcolor 2021/10/31 v2.13 LaTeX color extensions (UK) @@ -309,7 +309,7 @@ File: sphinxlatexgraphics.sty 2021/01/27 graphics \spx@image@maxheight=\dimen162 \spx@image@box=\box100 ) (./sphinxpackageboxes.sty -Package: sphinxpackageboxes 2023/03/19 v6.2.0 advanced colored boxes +Package: sphinxpackageboxes 2024/07/01 v7.4.0 advanced colored boxes (/usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty Package: pict2e 2020/09/30 v0.4b Improved picture commands (HjG,RN,JT) @@ -339,49 +339,50 @@ Package: ellipse 2004/11/05 v1.0 .dtx ellipse file \@tempdimd=\dimen171 \spx@tempboxa=\box101 \spx@tempboxb=\box102 -\spx@boxes@border=\dimen172 -\spx@boxes@border@top=\dimen173 -\spx@boxes@border@right=\dimen174 -\spx@boxes@border@bottom=\dimen175 -\spx@boxes@border@left=\dimen176 -\spx@boxes@padding@top=\dimen177 -\spx@boxes@padding@right=\dimen178 -\spx@boxes@padding@bottom=\dimen179 -\spx@boxes@padding@left=\dimen180 -\spx@boxes@shadow@xoffset=\dimen181 -\spx@boxes@shadow@yoffset=\dimen182 -\spx@boxes@radius@topleft@x=\dimen183 -\spx@boxes@radius@topright@x=\dimen184 -\spx@boxes@radius@bottomright@x=\dimen185 -\spx@boxes@radius@bottomleft@x=\dimen186 -\spx@boxes@radius@topleft@y=\dimen187 -\spx@boxes@radius@topright@y=\dimen188 -\spx@boxes@radius@bottomright@y=\dimen189 -\spx@boxes@radius@bottomleft@y=\dimen190 +\spx@boxes@border@top=\dimen172 +\spx@boxes@border@right=\dimen173 +\spx@boxes@border@bottom=\dimen174 +\spx@boxes@border@left=\dimen175 +\spx@boxes@padding@top=\dimen176 +\spx@boxes@padding@right=\dimen177 +\spx@boxes@padding@bottom=\dimen178 +\spx@boxes@padding@left=\dimen179 +\spx@boxes@shadow@xoffset=\dimen180 +\spx@boxes@shadow@yoffset=\dimen181 +\spx@boxes@radius@topleft@x=\dimen182 +\spx@boxes@radius@topright@x=\dimen183 +\spx@boxes@radius@bottomright@x=\dimen184 +\spx@boxes@radius@bottomleft@x=\dimen185 +\spx@boxes@radius@topleft@y=\dimen186 +\spx@boxes@radius@topright@y=\dimen187 +\spx@boxes@radius@bottomright@y=\dimen188 +\spx@boxes@radius@bottomleft@y=\dimen189 ) (./sphinxlatexadmonitions.sty -File: sphinxlatexadmonitions.sty 2023/03/19 admonitions +File: sphinxlatexadmonitions.sty 2024/07/01 v7.4.0 admonitions (/usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty Package: framed 2011/10/22 v 0.96: framed or shaded text with page breaks \OuterFrameSep=\skip61 -\fb@frw=\dimen191 -\fb@frh=\dimen192 -\FrameRule=\dimen193 -\FrameSep=\dimen194 +\fb@frw=\dimen190 +\fb@frh=\dimen191 +\FrameRule=\dimen192 +\FrameSep=\dimen193 ) -\spx@notice@border=\dimen195 +\spx@notice@border=\dimen194 +\c@sphinxtodo=\count288 ) (./sphinxlatexliterals.sty -File: sphinxlatexliterals.sty 2023/04/01 code-blocks and parsed literals +File: sphinxlatexliterals.sty 2024/07/01 v7.4.0 code-blocks and parsed literals + (/usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty Package: fancyvrb 2021/12/21 4.1b verbatim text (tvz,hv) -\FV@CodeLineNo=\count288 +\FV@CodeLineNo=\count289 \FV@InFile=\read3 \FV@TabBox=\box103 -\c@FancyVerbLine=\count289 -\FV@StepNumber=\count290 +\c@FancyVerbLine=\count290 +\FV@StepNumber=\count291 \FV@OutFile=\write3 ) (/usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty @@ -407,26 +408,26 @@ File: sphinxlatexcontainers.sty 2021/05/03 containers (./sphinxhighlight.sty Package: sphinxhighlight 2022/06/30 stylesheet for highlighting with pygments ) (./sphinxlatextables.sty -File: sphinxlatextables.sty 2022/08/15 tables +File: sphinxlatextables.sty 2024/07/01 v7.4.0 tables (/usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty Package: tabulary 2014/06/11 v0.10 tabulary package (DPC) (/usr/share/texlive/texmf-dist/tex/latex/tools/array.sty Package: array 2021/10/04 v2.5f Tabular extension package (FMi) -\col@sep=\dimen196 +\col@sep=\dimen195 \ar@mcellbox=\box108 -\extrarowheight=\dimen197 +\extrarowheight=\dimen196 \NC@list=\toks28 \extratabsurround=\skip62 \backup@length=\skip63 \ar@cellbox=\box109 ) -\TY@count=\count291 -\TY@linewidth=\dimen198 -\tymin=\dimen199 -\tymax=\dimen256 -\TY@tablewidth=\dimen257 +\TY@count=\count292 +\TY@linewidth=\dimen197 +\tymin=\dimen198 +\tymax=\dimen199 +\TY@tablewidth=\dimen256 ) (/usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty Package: longtable 2021-09-01 v4.17 Multi-page Table package (DPC) @@ -434,54 +435,54 @@ Package: longtable 2021-09-01 v4.17 Multi-page Table package (DPC) \LTright=\skip65 \LTpre=\skip66 \LTpost=\skip67 -\LTchunksize=\count292 -\LTcapwidth=\dimen258 +\LTchunksize=\count293 +\LTcapwidth=\dimen257 \LT@head=\box110 \LT@firsthead=\box111 \LT@foot=\box112 \LT@lastfoot=\box113 \LT@gbox=\box114 -\LT@cols=\count293 -\LT@rows=\count294 -\c@LT@tables=\count295 -\c@LT@chunks=\count296 +\LT@cols=\count294 +\LT@rows=\count295 +\c@LT@tables=\count296 +\c@LT@chunks=\count297 \LT@p@ftn=\toks29 ) (/usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty Package: varwidth 2009/03/30 ver 0.92; Variable-width minipages \@vwid@box=\box115 -\sift@deathcycles=\count297 -\@vwid@loff=\dimen259 -\@vwid@roff=\dimen260 +\sift@deathcycles=\count298 +\@vwid@loff=\dimen258 +\@vwid@roff=\dimen259 ) -\sphinx@TY@tablewidth=\dimen261 +\sphinx@TY@tablewidth=\dimen260 (/usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty Package: colortbl 2020/01/04 v1.0e Color table columns (DPC) \everycr=\toks30 \minrowclearance=\skip68 ) -\rownum=\count298 +\rownum=\count299 (/usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty Package: booktabs 2020/01/12 v1.61803398 Publication quality tables -\heavyrulewidth=\dimen262 -\lightrulewidth=\dimen263 -\cmidrulewidth=\dimen264 -\belowrulesep=\dimen265 -\belowbottomsep=\dimen266 -\aboverulesep=\dimen267 -\abovetopsep=\dimen268 -\cmidrulesep=\dimen269 -\cmidrulekern=\dimen270 -\defaultaddspace=\dimen271 -\@cmidla=\count299 -\@cmidlb=\count300 -\@aboverulesep=\dimen272 -\@belowrulesep=\dimen273 -\@thisruleclass=\count301 -\@lastruleclass=\count302 -\@thisrulewidth=\dimen274 +\heavyrulewidth=\dimen261 +\lightrulewidth=\dimen262 +\cmidrulewidth=\dimen263 +\belowrulesep=\dimen264 +\belowbottomsep=\dimen265 +\aboverulesep=\dimen266 +\abovetopsep=\dimen267 +\cmidrulesep=\dimen268 +\cmidrulekern=\dimen269 +\defaultaddspace=\dimen270 +\@cmidla=\count300 +\@cmidlb=\count301 +\@aboverulesep=\dimen271 +\@belowrulesep=\dimen272 +\@thisruleclass=\count302 +\@lastruleclass=\count303 +\@thisrulewidth=\dimen273 )) (./sphinxlatexnumfig.sty File: sphinxlatexnumfig.sty 2021/01/27 numbering @@ -489,14 +490,14 @@ File: sphinxlatexnumfig.sty 2021/01/27 numbering File: sphinxlatexlists.sty 2021/12/20 lists \spx@lineitemlabel=\toks31 ) -\c@sphinxscope=\count303 +\c@sphinxscope=\count304 (./sphinxpackagefootnote.sty -Package: sphinxpackagefootnote 2022/08/15 v5.3.0 Sphinx custom footnotehyper pa +Package: sphinxpackagefootnote 2024/05/17 v7.3.x Sphinx custom footnotehyper pa ckage (Sphinx team) \FNH@notes=\box116 \FNH@toks=\toks32 -\FNH@width=\dimen275 -\c@sphinxfootnotemark=\count304 +\FNH@width=\dimen274 +\c@sphinxfootnotemark=\count305 ) (./sphinxlatexindbibtoc.sty File: sphinxlatexindbibtoc.sty 2021/01/27 index, bib., toc @@ -534,15 +535,15 @@ Package: titlesec 2021/07/05 v2.14 Sectioning titles \ttl@box=\box117 \beforetitleunit=\skip78 \aftertitleunit=\skip79 -\ttl@plus=\dimen276 -\ttl@minus=\dimen277 +\ttl@plus=\dimen275 +\ttl@minus=\dimen276 \ttl@toksa=\toks33 -\titlewidth=\dimen278 -\titlewidthlast=\dimen279 -\titlewidthfirst=\dimen280 +\titlewidth=\dimen277 +\titlewidthlast=\dimen278 +\titlewidthfirst=\dimen279 )) (./sphinxlatexstyletext.sty -File: sphinxlatexstyletext.sty 2023/07/23 text styling +File: sphinxlatexstyletext.sty 2024/07/01 v7.4.0 text styling ) (./sphinxlatexobjects.sty File: sphinxlatexobjects.sty 2023/07/23 documentation environments \sphinxsignaturesep=\skip80 @@ -560,17 +561,17 @@ Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead. (/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty Package: iftex 2020/03/06 v1.0d TeX engine tests )) -\Gm@cnth=\count305 -\Gm@cntv=\count306 -\c@Gm@tempcnt=\count307 -\Gm@bindingoffset=\dimen281 -\Gm@wd@mp=\dimen282 -\Gm@odd@mp=\dimen283 -\Gm@even@mp=\dimen284 -\Gm@layoutwidth=\dimen285 -\Gm@layoutheight=\dimen286 -\Gm@layouthoffset=\dimen287 -\Gm@layoutvoffset=\dimen288 +\Gm@cnth=\count306 +\Gm@cntv=\count307 +\c@Gm@tempcnt=\count308 +\Gm@bindingoffset=\dimen280 +\Gm@wd@mp=\dimen281 +\Gm@odd@mp=\dimen282 +\Gm@even@mp=\dimen283 +\Gm@layoutwidth=\dimen284 +\Gm@layoutheight=\dimen285 +\Gm@layouthoffset=\dimen286 +\Gm@layoutvoffset=\dimen287 \Gm@dimlist=\toks34 ) (/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty @@ -602,9 +603,9 @@ Package: letltxmacro 2019/12/03 v1.6 Let assignment for LaTeX macros (HO) (/usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty Package: auxhook 2019-12-17 v1.6 Hooks for auxiliary files (HO) ) -\@linkdim=\dimen289 -\Hy@linkcounter=\count308 -\Hy@pagecounter=\count309 +\@linkdim=\dimen288 +\Hy@linkcounter=\count309 +\Hy@pagecounter=\count310 (/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def File: pd1enc.def 2021-06-07 v7.00m Hyperref: PDFDocEncoding definition (HO) @@ -621,7 +622,7 @@ Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO) (/usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty Package: etexcmds 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO) ) -\Hy@SavedSpaceFactor=\count310 +\Hy@SavedSpaceFactor=\count311 (/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def File: puenc.def 2021-06-07 v7.00m Hyperref: PDF Unicode definition (HO) @@ -638,14 +639,14 @@ Package hyperref Info: Plain pages OFF on input line 4207. Package hyperref Info: Backreferencing OFF on input line 4212. Package hyperref Info: Implicit mode ON; LaTeX internals redefined. Package hyperref Info: Bookmarks ON on input line 4445. -\c@Hy@tempcnt=\count311 +\c@Hy@tempcnt=\count312 (/usr/share/texlive/texmf-dist/tex/latex/url/url.sty \Urlmuskip=\muskip17 Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. ) LaTeX Info: Redefining \url on input line 4804. -\XeTeXLinkMargin=\dimen290 +\XeTeXLinkMargin=\dimen289 (/usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO) @@ -654,9 +655,9 @@ Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO) Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO ) )) -\Fld@menulength=\count312 -\Field@Width=\dimen291 -\Fld@charsize=\dimen292 +\Fld@menulength=\count313 +\Field@Width=\dimen290 +\Fld@charsize=\dimen291 Package hyperref Info: Hyper figures OFF on input line 6076. Package hyperref Info: Link nesting OFF on input line 6081. Package hyperref Info: Hyper index ON on input line 6084. @@ -671,9 +672,9 @@ LaTeX Info: Redefining \pageref on input line 6150. Package: atbegshi-ltx 2021/01/10 v1.0c Emulation of the original atbegshi package with kernel methods ) -\Hy@abspage=\count313 -\c@Item=\count314 -\c@Hfootnote=\count315 +\Hy@abspage=\count314 +\c@Item=\count315 +\c@Hfootnote=\count316 ) Package hyperref Info: Driver (autodetected): hpdftex. @@ -685,8 +686,8 @@ Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend pac kage with kernel methods ) -\Fld@listcount=\count316 -\c@bookmark@seq@number=\count317 +\Fld@listcount=\count317 +\c@bookmark@seq@number=\count318 (/usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty Package: rerunfilecheck 2019/12/05 v1.9 Rerun checks for auxiliary files (HO) @@ -717,7 +718,7 @@ File: t1qtm.fd 2009/09/25 v1.2 font definition file for T1/qtm ) (/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def File: l3backend-pdftex.def 2022-01-12 L3 backend support: PDF output (pdfTeX) -\l__color_backend_stack_int=\count318 +\l__color_backend_stack_int=\count319 \l__pdf_internal_box=\box118 ) (./Py-BOBYQA.aux) @@ -744,16 +745,16 @@ LaTeX Font Info: ... okay on input line 73. (/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii [Loading MPS to PDF converter (version 2006.09.02).] -\scratchcounter=\count319 -\scratchdimen=\dimen293 +\scratchcounter=\count320 +\scratchdimen=\dimen292 \scratchbox=\box119 -\nofMPsegments=\count320 -\nofMParguments=\count321 +\nofMPsegments=\count321 +\nofMParguments=\count322 \everyMPshowfont=\toks35 -\MPscratchCnt=\count322 -\MPscratchDim=\dimen294 -\MPnumerator=\count323 -\makeMPintoPDFobject=\count324 +\MPscratchCnt=\count323 +\MPscratchDim=\dimen293 +\MPnumerator=\count324 +\makeMPintoPDFobject=\count325 \everyMPtoPDFconversion=\toks36 ) (/usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf @@ -764,7 +765,26 @@ Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4 File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv e )) -\c@literalblock=\count325 +(/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +(/usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +Package: expl3 2022-01-21 L3 programming layer (loader) +) +Package: fontawesome5 2021/06/04 v5.15.3 Font Awesome 5 + +(/usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +Package: l3keys2e 2022-01-12 LaTeX2e option processing using LaTeX3 keys +) +(/usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +Package: xparse 2022-01-12 L3 Experimental document command parser +) +(/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-help +er.sty +Package: fontawesome5-generic-helper 2021/06/04 v5.15.3 non-uTeX helper for fon +tawesome5 + +(/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def) +)) +\c@literalblock=\count326 *geometry* driver: auto-detecting *geometry* detected driver: pdftex @@ -810,7 +830,7 @@ Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO) (/usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO) ) -\c@section@level=\count326 +\c@section@level=\count327 ) LaTeX Info: Redefining \ref on input line 73. LaTeX Info: Redefining \pageref on input line 73. @@ -855,19 +875,16 @@ File: umsb.fd 2013/01/14 v3.01 AMS symbols B ] Chapter 1. LaTeX Font Info: Trying to load font information for TS1+qtm on input line 1 -46. +52. (/usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd File: ts1qtm.fd 2009/09/25 v1.2 font definition file for TS1/qtm ) LaTeX Font Info: Trying to load font information for T1+txtt on input line 1 -70. +76. (/usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd File: t1txtt.fd 2000/12/15 v3.1 -) [3] -LaTeX Font Info: Font shape `T1/txtt/m/it' in size <10> not available -(Font) Font shape `T1/txtt/m/sl' tried instead on input line 248. - [4] +) [3] [4] Chapter 2. [5 @@ -877,72 +894,85 @@ Chapter 3. ] LaTeX Font Info: Font shape `T1/txtt/b/n' in size <10> not available -(Font) Font shape `T1/txtt/bx/n' tried instead on input line 456. +(Font) Font shape `T1/txtt/bx/n' tried instead on input line 445. [8] LaTeX Font Info: Trying to load font information for TS1+txtt on input line 1. (/usr/share/texlive/texmf-dist/tex/latex/txfonts/ts1txtt.fd File: ts1txtt.fd 2000/12/15 v3.1 ) [9] -[10] [11] [12] [13] -Overfull \vbox (3.3114pt too high) detected at line 862 +LaTeX Font Info: Font shape `T1/txtt/m/it' in size <10> not available +(Font) Font shape `T1/txtt/m/sl' tried instead on input line 545. + +[10] [11] +LaTeX Font Info: Font shape `TS1/txtt/m/it' in size <10> not available +(Font) Font shape `TS1/txtt/m/sl' tried instead on input line 760. + + [12] [13] +Underfull \vbox (badness 1226) detected at line 870 [] -[14] [15] [16] -Chapter 4. -[17 +[14] [15] +Underfull \vbox (badness 1226) detected at line 990 + [] -] [18] [19] [20] -Chapter 5. -[21 +[16] [17] [18 -] [22] -Chapter 6. +] +Chapter 4. +[19] [20] [21] [22] +Chapter 5. [23 ] [24] -Chapter 7. +Chapter 6. [25 -] [26 +] [26] [27] [28 + +] +Chapter 7. +[29] [30 -] (./Py-BOBYQA.ind) [27 +] (./Py-BOBYQA.ind) [31 ] (./Py-BOBYQA.aux) Package rerunfilecheck Info: File `Py-BOBYQA.out' has not changed. -(rerunfilecheck) Checksum: 99197217DBF95BFA156C10F98CDB064E;7797. +(rerunfilecheck) Checksum: 6B1B345F82CFFC2D0FE36BFD7064B373;8427. ) Here is how much of TeX's memory you used: - 16162 strings out of 480247 - 269758 string characters out of 5896151 - 622077 words of memory out of 5000000 - 33628 multiletter control sequences out of 15000+600000 - 523539 words of font info for 71 fonts, out of 8000000 for 9000 + 19407 strings out of 480247 + 343038 string characters out of 5896151 + 672063 words of memory out of 5000000 + 36839 multiletter control sequences out of 15000+600000 + 526530 words of font info for 75 fonts, out of 8000000 for 9000 15 hyphenation exceptions out of 8191 - 70i,17n,76p,988b,609s stack positions out of 5000i,500n,10000p,200000b,80000s -{/usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ts1.enc}{/usr/share/texmf/fonts/ -enc/dvips/tex-gyre/q-ec.enc} -Output written on Py-BOBYQA.pdf (31 pages, 312953 bytes). + 70i,20n,76p,988b,603s stack positions out of 5000i,500n,10000p,200000b,80000s +{/usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc}{/usr/share/texmf/ +fonts/enc/dvips/tex-gyre/q-ts1.enc}{/usr/share/texmf/fonts/enc/dvips/tex-gyre/q +-ec.enc}< +/usr/share/texmf/fonts/type1/public/tex-gyre/qtmri.pfb> +Output written on Py-BOBYQA.pdf (35 pages, 336038 bytes). PDF statistics: - 563 PDF objects out of 1000 (max. 8388607) - 495 compressed objects within 5 object streams - 87 named destinations out of 1000 (max. 500000) - 405 words of extra memory for PDF output out of 10000 (max. 10000000) + 618 PDF objects out of 1000 (max. 8388607) + 542 compressed objects within 6 object streams + 97 named destinations out of 1000 (max. 500000) + 429 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/docs/build/latex/Py-BOBYQA.out b/docs/build/latex/Py-BOBYQA.out index c30cbe9..51cc812 100644 --- a/docs/build/latex/Py-BOBYQA.out +++ b/docs/build/latex/Py-BOBYQA.out @@ -14,35 +14,38 @@ \BOOKMARK [1][-]{section.3.3}{\376\377\000O\000p\000t\000i\000o\000n\000a\000l\000\040\000A\000r\000g\000u\000m\000e\000n\000t\000s}{chapter.3}% 14 \BOOKMARK [1][-]{section.3.4}{\376\377\000A\000\040\000S\000i\000m\000p\000l\000e\000\040\000E\000x\000a\000m\000p\000l\000e}{chapter.3}% 15 \BOOKMARK [1][-]{section.3.5}{\376\377\000A\000d\000d\000i\000n\000g\000\040\000B\000o\000u\000n\000d\000s\000\040\000a\000n\000d\000\040\000M\000o\000r\000e\000\040\000O\000u\000t\000p\000u\000t}{chapter.3}% 16 -\BOOKMARK [1][-]{section.3.6}{\376\377\000E\000x\000a\000m\000p\000l\000e\000:\000\040\000N\000o\000i\000s\000y\000\040\000O\000b\000j\000e\000c\000t\000i\000v\000e\000\040\000E\000v\000a\000l\000u\000a\000t\000i\000o\000n}{chapter.3}% 17 -\BOOKMARK [1][-]{section.3.7}{\376\377\000E\000x\000a\000m\000p\000l\000e\000:\000\040\000G\000l\000o\000b\000a\000l\000\040\000O\000p\000t\000i\000m\000i\000z\000a\000t\000i\000o\000n}{chapter.3}% 18 -\BOOKMARK [1][-]{section.3.8}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000e\000s}{chapter.3}% 19 -\BOOKMARK [0][-]{chapter.4}{\376\377\000A\000d\000v\000a\000n\000c\000e\000d\000\040\000U\000s\000a\000g\000e}{}% 20 -\BOOKMARK [1][-]{section.4.1}{\376\377\000G\000e\000n\000e\000r\000a\000l\000\040\000A\000l\000g\000o\000r\000i\000t\000h\000m\000\040\000P\000a\000r\000a\000m\000e\000t\000e\000r\000s}{chapter.4}% 21 -\BOOKMARK [1][-]{section.4.2}{\376\377\000L\000o\000g\000g\000i\000n\000g\000\040\000a\000n\000d\000\040\000O\000u\000t\000p\000u\000t}{chapter.4}% 22 -\BOOKMARK [1][-]{section.4.3}{\376\377\000I\000n\000i\000t\000i\000a\000l\000i\000z\000a\000t\000i\000o\000n\000\040\000o\000f\000\040\000P\000o\000i\000n\000t\000s}{chapter.4}% 23 -\BOOKMARK [1][-]{section.4.4}{\376\377\000T\000r\000u\000s\000t\000\040\000R\000e\000g\000i\000o\000n\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t}{chapter.4}% 24 -\BOOKMARK [1][-]{section.4.5}{\376\377\000T\000e\000r\000m\000i\000n\000a\000t\000i\000o\000n\000\040\000o\000n\000\040\000S\000m\000a\000l\000l\000\040\000O\000b\000j\000e\000c\000t\000i\000v\000e\000\040\000V\000a\000l\000u\000e}{chapter.4}% 25 -\BOOKMARK [1][-]{section.4.6}{\376\377\000T\000e\000r\000m\000i\000n\000a\000t\000i\000o\000n\000\040\000o\000n\000\040\000S\000l\000o\000w\000\040\000P\000r\000o\000g\000r\000e\000s\000s}{chapter.4}% 26 -\BOOKMARK [1][-]{section.4.7}{\376\377\000S\000t\000o\000c\000h\000a\000s\000t\000i\000c\000\040\000N\000o\000i\000s\000e\000\040\000I\000n\000f\000o\000r\000m\000a\000t\000i\000o\000n}{chapter.4}% 27 -\BOOKMARK [1][-]{section.4.8}{\376\377\000I\000n\000t\000e\000r\000p\000o\000l\000a\000t\000i\000o\000n\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t}{chapter.4}% 28 -\BOOKMARK [1][-]{section.4.9}{\376\377\000M\000u\000l\000t\000i\000p\000l\000e\000\040\000R\000e\000s\000t\000a\000r\000t\000s}{chapter.4}% 29 -\BOOKMARK [1][-]{section.4.10}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000e\000s}{chapter.4}% 30 -\BOOKMARK [0][-]{chapter.5}{\376\377\000D\000i\000a\000g\000n\000o\000s\000t\000i\000c\000\040\000I\000n\000f\000o\000r\000m\000a\000t\000i\000o\000n}{}% 31 -\BOOKMARK [1][-]{section.5.1}{\376\377\000C\000u\000r\000r\000e\000n\000t\000\040\000I\000t\000e\000r\000a\000t\000e}{chapter.5}% 32 -\BOOKMARK [1][-]{section.5.2}{\376\377\000T\000r\000u\000s\000t\000\040\000R\000e\000g\000i\000o\000n}{chapter.5}% 33 -\BOOKMARK [1][-]{section.5.3}{\376\377\000M\000o\000d\000e\000l\000\040\000I\000n\000t\000e\000r\000p\000o\000l\000a\000t\000i\000o\000n}{chapter.5}% 34 -\BOOKMARK [1][-]{section.5.4}{\376\377\000I\000t\000e\000r\000a\000t\000i\000o\000n\000\040\000C\000o\000u\000n\000t}{chapter.5}% 35 -\BOOKMARK [1][-]{section.5.5}{\376\377\000A\000l\000g\000o\000r\000i\000t\000h\000m\000\040\000P\000r\000o\000g\000r\000e\000s\000s}{chapter.5}% 36 -\BOOKMARK [0][-]{chapter.6}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\000H\000i\000s\000t\000o\000r\000y}{}% 37 -\BOOKMARK [1][-]{section.6.1}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0000\000\040\000\050\0006\000\040\000F\000e\000b\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 38 -\BOOKMARK [1][-]{section.6.2}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0000\000.\0001\000\040\000\050\0002\0000\000\040\000F\000e\000b\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 39 -\BOOKMARK [1][-]{section.6.3}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0000\000.\0002\000\040\000\050\0002\0000\000\040\000J\000u\000n\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 40 -\BOOKMARK [1][-]{section.6.4}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0001\000\040\000\050\0002\0004\000\040\000D\000e\000c\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 41 -\BOOKMARK [1][-]{section.6.5}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0001\000.\0001\000\040\000\050\0005\000\040\000A\000p\000r\000\040\0002\0000\0001\0009\000\051}{chapter.6}% 42 -\BOOKMARK [1][-]{section.6.6}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0002\000\040\000\050\0002\0005\000\040\000F\000e\000b\000\040\0002\0000\0002\0000\000\051}{chapter.6}% 43 -\BOOKMARK [1][-]{section.6.7}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0003\000\040\000\050\0001\0004\000\040\000A\000p\000r\000\040\0002\0000\0002\0001\000\051}{chapter.6}% 44 -\BOOKMARK [1][-]{section.6.8}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0004\000\040\000\050\0001\0006\000\040\000M\000a\000y\000\040\0002\0000\0002\0003\000\051}{chapter.6}% 45 -\BOOKMARK [1][-]{section.6.9}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0004\000.\0001\000\040\000\050\0001\0001\000\040\000A\000p\000r\000\040\0002\0000\0002\0004\000\051}{chapter.6}% 46 -\BOOKMARK [0][-]{chapter.7}{\376\377\000A\000c\000k\000n\000o\000w\000l\000e\000d\000g\000e\000m\000e\000n\000t\000s}{}% 47 -\BOOKMARK [0][-]{chapter*.3}{\376\377\000B\000i\000b\000l\000i\000o\000g\000r\000a\000p\000h\000y}{}% 48 +\BOOKMARK [1][-]{section.3.6}{\376\377\000A\000d\000d\000i\000n\000g\000\040\000G\000e\000n\000e\000r\000a\000l\000\040\000C\000o\000n\000v\000e\000x\000\040\000C\000o\000n\000s\000t\000r\000a\000i\000n\000t\000s}{chapter.3}% 17 +\BOOKMARK [1][-]{section.3.7}{\376\377\000E\000x\000a\000m\000p\000l\000e\000:\000\040\000N\000o\000i\000s\000y\000\040\000O\000b\000j\000e\000c\000t\000i\000v\000e\000\040\000E\000v\000a\000l\000u\000a\000t\000i\000o\000n}{chapter.3}% 18 +\BOOKMARK [1][-]{section.3.8}{\376\377\000E\000x\000a\000m\000p\000l\000e\000:\000\040\000G\000l\000o\000b\000a\000l\000\040\000O\000p\000t\000i\000m\000i\000z\000a\000t\000i\000o\000n}{chapter.3}% 19 +\BOOKMARK [1][-]{section.3.9}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000e\000s}{chapter.3}% 20 +\BOOKMARK [0][-]{chapter.4}{\376\377\000A\000d\000v\000a\000n\000c\000e\000d\000\040\000U\000s\000a\000g\000e}{}% 21 +\BOOKMARK [1][-]{section.4.1}{\376\377\000G\000e\000n\000e\000r\000a\000l\000\040\000A\000l\000g\000o\000r\000i\000t\000h\000m\000\040\000P\000a\000r\000a\000m\000e\000t\000e\000r\000s}{chapter.4}% 22 +\BOOKMARK [1][-]{section.4.2}{\376\377\000L\000o\000g\000g\000i\000n\000g\000\040\000a\000n\000d\000\040\000O\000u\000t\000p\000u\000t}{chapter.4}% 23 +\BOOKMARK [1][-]{section.4.3}{\376\377\000I\000n\000i\000t\000i\000a\000l\000i\000z\000a\000t\000i\000o\000n\000\040\000o\000f\000\040\000P\000o\000i\000n\000t\000s}{chapter.4}% 24 +\BOOKMARK [1][-]{section.4.4}{\376\377\000T\000r\000u\000s\000t\000\040\000R\000e\000g\000i\000o\000n\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t}{chapter.4}% 25 +\BOOKMARK [1][-]{section.4.5}{\376\377\000T\000e\000r\000m\000i\000n\000a\000t\000i\000o\000n\000\040\000o\000n\000\040\000S\000m\000a\000l\000l\000\040\000O\000b\000j\000e\000c\000t\000i\000v\000e\000\040\000V\000a\000l\000u\000e}{chapter.4}% 26 +\BOOKMARK [1][-]{section.4.6}{\376\377\000T\000e\000r\000m\000i\000n\000a\000t\000i\000o\000n\000\040\000o\000n\000\040\000S\000l\000o\000w\000\040\000P\000r\000o\000g\000r\000e\000s\000s}{chapter.4}% 27 +\BOOKMARK [1][-]{section.4.7}{\376\377\000S\000t\000o\000c\000h\000a\000s\000t\000i\000c\000\040\000N\000o\000i\000s\000e\000\040\000I\000n\000f\000o\000r\000m\000a\000t\000i\000o\000n}{chapter.4}% 28 +\BOOKMARK [1][-]{section.4.8}{\376\377\000I\000n\000t\000e\000r\000p\000o\000l\000a\000t\000i\000o\000n\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t}{chapter.4}% 29 +\BOOKMARK [1][-]{section.4.9}{\376\377\000M\000u\000l\000t\000i\000p\000l\000e\000\040\000R\000e\000s\000t\000a\000r\000t\000s}{chapter.4}% 30 +\BOOKMARK [1][-]{section.4.10}{\376\377\000G\000e\000n\000e\000r\000a\000l\000\040\000C\000o\000n\000v\000e\000x\000\040\000C\000o\000n\000s\000t\000r\000a\000i\000n\000t\000s}{chapter.4}% 31 +\BOOKMARK [1][-]{section.4.11}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000e\000s}{chapter.4}% 32 +\BOOKMARK [0][-]{chapter.5}{\376\377\000D\000i\000a\000g\000n\000o\000s\000t\000i\000c\000\040\000I\000n\000f\000o\000r\000m\000a\000t\000i\000o\000n}{}% 33 +\BOOKMARK [1][-]{section.5.1}{\376\377\000C\000u\000r\000r\000e\000n\000t\000\040\000I\000t\000e\000r\000a\000t\000e}{chapter.5}% 34 +\BOOKMARK [1][-]{section.5.2}{\376\377\000T\000r\000u\000s\000t\000\040\000R\000e\000g\000i\000o\000n}{chapter.5}% 35 +\BOOKMARK [1][-]{section.5.3}{\376\377\000M\000o\000d\000e\000l\000\040\000I\000n\000t\000e\000r\000p\000o\000l\000a\000t\000i\000o\000n}{chapter.5}% 36 +\BOOKMARK [1][-]{section.5.4}{\376\377\000I\000t\000e\000r\000a\000t\000i\000o\000n\000\040\000C\000o\000u\000n\000t}{chapter.5}% 37 +\BOOKMARK [1][-]{section.5.5}{\376\377\000A\000l\000g\000o\000r\000i\000t\000h\000m\000\040\000P\000r\000o\000g\000r\000e\000s\000s}{chapter.5}% 38 +\BOOKMARK [0][-]{chapter.6}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\000H\000i\000s\000t\000o\000r\000y}{}% 39 +\BOOKMARK [1][-]{section.6.1}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0000\000\040\000\050\0006\000\040\000F\000e\000b\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 40 +\BOOKMARK [1][-]{section.6.2}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0000\000.\0001\000\040\000\050\0002\0000\000\040\000F\000e\000b\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 41 +\BOOKMARK [1][-]{section.6.3}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0000\000.\0002\000\040\000\050\0002\0000\000\040\000J\000u\000n\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 42 +\BOOKMARK [1][-]{section.6.4}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0001\000\040\000\050\0002\0004\000\040\000D\000e\000c\000\040\0002\0000\0001\0008\000\051}{chapter.6}% 43 +\BOOKMARK [1][-]{section.6.5}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0001\000.\0001\000\040\000\050\0005\000\040\000A\000p\000r\000\040\0002\0000\0001\0009\000\051}{chapter.6}% 44 +\BOOKMARK [1][-]{section.6.6}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0002\000\040\000\050\0002\0005\000\040\000F\000e\000b\000\040\0002\0000\0002\0000\000\051}{chapter.6}% 45 +\BOOKMARK [1][-]{section.6.7}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0003\000\040\000\050\0001\0004\000\040\000A\000p\000r\000\040\0002\0000\0002\0001\000\051}{chapter.6}% 46 +\BOOKMARK [1][-]{section.6.8}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0004\000\040\000\050\0001\0006\000\040\000M\000a\000y\000\040\0002\0000\0002\0003\000\051}{chapter.6}% 47 +\BOOKMARK [1][-]{section.6.9}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0004\000.\0001\000\040\000\050\0001\0001\000\040\000A\000p\000r\000\040\0002\0000\0002\0004\000\051}{chapter.6}% 48 +\BOOKMARK [1][-]{section.6.10}{\376\377\000V\000e\000r\000s\000i\000o\000n\000\040\0001\000.\0005\000.\0000\000\040\000\050\0001\0006\000\040\000S\000e\000p\000\040\0002\0000\0002\0004\000\051}{chapter.6}% 49 +\BOOKMARK [0][-]{chapter.7}{\376\377\000A\000c\000k\000n\000o\000w\000l\000e\000d\000g\000e\000m\000e\000n\000t\000s}{}% 50 +\BOOKMARK [0][-]{chapter*.3}{\376\377\000B\000i\000b\000l\000i\000o\000g\000r\000a\000p\000h\000y}{}% 51 diff --git a/docs/build/latex/Py-BOBYQA.pdf b/docs/build/latex/Py-BOBYQA.pdf index 005ef9c..de9b460 100644 Binary files a/docs/build/latex/Py-BOBYQA.pdf and b/docs/build/latex/Py-BOBYQA.pdf differ diff --git a/docs/build/latex/Py-BOBYQA.tex b/docs/build/latex/Py-BOBYQA.tex index 9fdd211..2a0ddc4 100644 --- a/docs/build/latex/Py-BOBYQA.tex +++ b/docs/build/latex/Py-BOBYQA.tex @@ -64,8 +64,8 @@ \title{Py-BOBYQA Documentation} -\date{11 April 2024} -\release{1.4.1} +\date{16 September 2024} +\release{1.5.0} \author{Lindon Roberts} \newcommand{\sphinxlogo}{\vbox{}} \renewcommand{\releasename}{Release} @@ -86,25 +86,27 @@ \sphinxAtStartPar -\sphinxstylestrong{Release:} 1.4.1 +\sphinxstylestrong{Release:} 1.5.0 \sphinxAtStartPar -\sphinxstylestrong{Date:} 11 April 2024 +\sphinxstylestrong{Date:} 16 September 2024 \sphinxAtStartPar \sphinxstylestrong{Author:} \sphinxhref{mailto:lindon.roberts@sydney.edu.au}{Lindon Roberts} \sphinxAtStartPar -Py\sphinxhyphen{}BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound constraints), without requiring any derivatives of the objective. Py\sphinxhyphen{}BOBYQA is a Python implementation of the \sphinxhref{http://mat.uc.pt/~zhang/software.html\#powell\_software}{BOBYQA} solver by Powell (documentation \sphinxhref{http://www.damtp.cam.ac.uk/user/na/NA\_papers/NA2009\_06.pdf}{here}). It is particularly useful when evaluations of the objective function are expensive and/or noisy. +Py\sphinxhyphen{}BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound and other convex constraints), without requiring any derivatives of the objective. Py\sphinxhyphen{}BOBYQA is a Python implementation of the \sphinxhref{http://mat.uc.pt/~zhang/software.html\#powell\_software}{BOBYQA} solver by Powell (documentation \sphinxhref{http://www.damtp.cam.ac.uk/user/na/NA\_papers/NA2009\_06.pdf}{here}). It is particularly useful when evaluations of the objective function are expensive and/or noisy. \sphinxAtStartPar That is, Py\sphinxhyphen{}BOBYQA solves \begin{equation*} \begin{split}\min_{x\in\mathbb{R}^n} &\quad f(x)\\ -\text{s.t.} &\quad a \leq x \leq b\end{split} +\text{s.t.} &\quad a \leq x \leq b \\ +&\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex}\end{split} \end{equation*} \sphinxAtStartPar -The upper and lower bounds on the variables are non\sphinxhyphen{}relaxable (i.e. Py\sphinxhyphen{}BOBYQA will never ask to evaluate a point outside the bounds). +If provided, the constraints the variables are non\sphinxhyphen{}relaxable (i.e. Py\sphinxhyphen{}BOBYQA will never ask to evaluate a point outside the bounds), +although the general \(x \in C\) constraint may be slightly violated from rounding errors. \sphinxAtStartPar Full details of the Py\sphinxhyphen{}BOBYQA algorithm are given in our papers: @@ -118,10 +120,14 @@ \sphinxAtStartPar Coralia Cartis, Lindon Roberts and Oliver Sheridan\sphinxhyphen{}Methven, \sphinxhref{https://doi.org/10.1080/02331934.2021.1883015}{Escaping local minima with derivative\sphinxhyphen{}free methods: a numerical investigation}, \sphinxstyleemphasis{Optimization}, 71:8 (2022), pp. 2343\sphinxhyphen{}2373. {[}\sphinxhref{https://arxiv.org/abs/1812.11343}{arXiv preprint: 1812.11343}{]} +\item {} +\sphinxAtStartPar +Lindon Roberts, \sphinxhref{https://arxiv.org/abs/2403.14960}{Model Construction for Convex\sphinxhyphen{}Constrained Derivative\sphinxhyphen{}Free Optimization}, \sphinxstyleemphasis{arXiv preprint arXiv:2403.14960} (2024). + \end{enumerate} \sphinxAtStartPar -Please cite {[}1{]} when using Py\sphinxhyphen{}BOBYQA for local optimization, and {[}1,2{]} when using Py\sphinxhyphen{}BOBYQA’s global optimization heuristic functionality. +Please cite {[}1{]} when using Py\sphinxhyphen{}BOBYQA for local optimization, {[}1,2{]} when using Py\sphinxhyphen{}BOBYQA’s global optimization heuristic functionality, and {[}1,3{]} if using the general convex constraints \(x \in C\) functionality. \sphinxAtStartPar If you are interested in solving least\sphinxhyphen{}squares minimization problems, you may wish to try \sphinxhref{https://github.com/numericalalgorithmsgroup/dfols}{DFO\sphinxhyphen{}LS}, which has the same features as Py\sphinxhyphen{}BOBYQA (plus some more), and exploits the least\sphinxhyphen{}squares problem structure, so performs better on such problems. @@ -173,32 +179,20 @@ \section{Requirements} \section{Installation using pip} \label{\detokenize{install:installation-using-pip}} \sphinxAtStartPar -For easy installation, use \sphinxhref{http://www.pip-installer.org/}{pip} as root: -\begin{quote} - -\begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYGZdl{}\PYG{+w}{ }\PYG{o}{[}sudo\PYG{o}{]}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }Py\PYGZhy{}BOBYQA -\end{sphinxVerbatim} -\end{quote} - -\sphinxAtStartPar -If you do not have root privileges or you want to install Py\sphinxhyphen{}BOBYQA for your private use, you can use: +For easy installation, use \sphinxhref{http://www.pip-installer.org/}{pip}: \begin{quote} \begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }\PYGZhy{}\PYGZhy{}user\PYG{+w}{ }Py\PYGZhy{}BOBYQA +\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }Py\PYGZhy{}BOBYQA \end{sphinxVerbatim} \end{quote} -\sphinxAtStartPar -which will install Py\sphinxhyphen{}BOBYQA in your home directory. - \sphinxAtStartPar Note that if an older install of Py\sphinxhyphen{}BOBYQA is present on your system you can use: \begin{quote} \begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYGZdl{}\PYG{+w}{ }\PYG{o}{[}sudo\PYG{o}{]}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }\PYGZhy{}\PYGZhy{}upgrade\PYG{+w}{ }Py\PYGZhy{}BOBYQA +\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }\PYGZhy{}\PYGZhy{}upgrade\PYG{+w}{ }Py\PYGZhy{}BOBYQA \end{sphinxVerbatim} \end{quote} @@ -223,29 +217,17 @@ \section{Manual installation} \begin{quote} \begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYGZdl{}\PYG{+w}{ }\PYG{o}{[}sudo\PYG{o}{]}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }. -\end{sphinxVerbatim} -\end{quote} - -\sphinxAtStartPar -If you do not have root privileges or you want to install Py\sphinxhyphen{}BOBYQA for your private use, you can use: -\begin{quote} - -\begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }\PYGZhy{}\PYGZhy{}user\PYG{+w}{ }. +\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }. \end{sphinxVerbatim} \end{quote} -\sphinxAtStartPar -instead. - \sphinxAtStartPar To upgrade Py\sphinxhyphen{}BOBYQA to the latest version, navigate to the top\sphinxhyphen{}level directory (i.e. the one containing \sphinxcode{\sphinxupquote{setup.py}}) and rerun the installation using \sphinxcode{\sphinxupquote{pip}}, as above: \begin{quote} \begin{sphinxVerbatim}[commandchars=\\\{\}] \PYGZdl{}\PYG{+w}{ }git\PYG{+w}{ }pull -\PYGZdl{}\PYG{+w}{ }\PYG{o}{[}sudo\PYG{o}{]}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }.\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} with admin privileges} +\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }install\PYG{+w}{ }. \end{sphinxVerbatim} \end{quote} @@ -270,7 +252,7 @@ \section{Uninstallation} \begin{quote} \begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYGZdl{}\PYG{+w}{ }\PYG{o}{[}sudo\PYG{o}{]}\PYG{+w}{ }pip\PYG{+w}{ }uninstall\PYG{+w}{ }Py\PYGZhy{}BOBYQA +\PYGZdl{}\PYG{+w}{ }pip\PYG{+w}{ }uninstall\PYG{+w}{ }Py\PYGZhy{}BOBYQA \end{sphinxVerbatim} \end{quote} @@ -286,10 +268,11 @@ \chapter{Overview} \section{When to use Py\sphinxhyphen{}BOBYQA} \label{\detokenize{info:when-to-use-py-bobyqa}} \sphinxAtStartPar -Py\sphinxhyphen{}BOBYQA is designed to solve the nonlinear least\sphinxhyphen{}squares minimization problem (with optional bound constraints) +Py\sphinxhyphen{}BOBYQA is designed to solve the nonlinear least\sphinxhyphen{}squares minimization problem (with optional bound and general convex constraints) \begin{equation*} \begin{split}\min_{x\in\mathbb{R}^n} &\quad f(x)\\ -\text{s.t.} &\quad a \leq x \leq b\end{split} +\text{s.t.} &\quad a \leq x \leq b\\ +&\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex}\end{split} \end{equation*} \sphinxAtStartPar We call \(f(x)\) the objective function. @@ -342,14 +325,20 @@ \section{Nonlinear Minimization} Py\sphinxhyphen{}BOBYQA is designed to solve the local optimization problem \begin{equation*} \begin{split}\min_{x\in\mathbb{R}^n} &\quad f(x) \\ -\text{s.t.} &\quad a \leq x \leq b\end{split} +\text{s.t.} &\quad a \leq x \leq b\\ +&\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex}\end{split} \end{equation*} \sphinxAtStartPar -where the bound constraints \(a \leq x \leq b\) are optional. The upper and lower bounds on the variables are non\sphinxhyphen{}relaxable (i.e. Py\sphinxhyphen{}BOBYQA will never ask to evaluate a point outside the bounds). The objective function \(f(x)\) is usually nonlinear and nonquadratic. If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see \sphinxhref{https://neos-guide.org/Optimization-Guide}{here} for details). +where the bound constraints \(a \leq x \leq b\) and general convex constraints \(x \in C\) are optional. +The upper and lower bounds on the variables are non\sphinxhyphen{}relaxable (i.e. Py\sphinxhyphen{}BOBYQA will never ask to evaluate a point outside the bounds). +The general convex constraints are also non\sphinxhyphen{}relaxable, but they may be slightly violated at some points from rounding errors. +The objective function \(f(x)\) is usually nonlinear and nonquadratic. +If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see \sphinxhref{https://neos-guide.org/Optimization-Guide}{here} for details). \sphinxAtStartPar Py\sphinxhyphen{}BOBYQA iteratively constructs an interpolation\sphinxhyphen{}based model for the objective, and determines a step using a trust\sphinxhyphen{}region framework. For an in\sphinxhyphen{}depth technical description of the algorithm see the paper \sphinxcite{userguide:cfmr2018}, and for the global optimization heuristic, see \sphinxcite{userguide:cro2022}. +For details about how Py\sphinxhyphen{}BOBYQA handles general convex constraints, see \sphinxcite{userguide:r2024}. \section{How to use Py\sphinxhyphen{}BOBYQA} @@ -466,12 +455,12 @@ \section{Optional Arguments} \begin{quote} \begin{sphinxVerbatim}[commandchars=\\\{\}] -\PYG{n}{pybobyqa}\PYG{o}{.}\PYG{n}{solve}\PYG{p}{(}\PYG{n}{objfun}\PYG{p}{,} \PYG{n}{x0}\PYG{p}{,} \PYG{n}{args}\PYG{o}{=}\PYG{p}{(}\PYG{p}{)}\PYG{p}{,} \PYG{n}{bounds}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{npt}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} - \PYG{n}{rhobeg}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{rhoend}\PYG{o}{=}\PYG{l+m+mf}{1e\PYGZhy{}8}\PYG{p}{,} \PYG{n}{maxfun}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{nsamples}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} - \PYG{n}{user\PYGZus{}params}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{objfun\PYGZus{}has\PYGZus{}noise}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{,} - \PYG{n}{seek\PYGZus{}global\PYGZus{}minimum}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{,} - \PYG{n}{scaling\PYGZus{}within\PYGZus{}bounds}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{,} - \PYG{n}{do\PYGZus{}logging}\PYG{o}{=}\PYG{k+kc}{True}\PYG{p}{,} \PYG{n}{print\PYGZus{}progress}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{)} +\PYG{n}{pybobyqa}\PYG{o}{.}\PYG{n}{solve}\PYG{p}{(}\PYG{n}{objfun}\PYG{p}{,} \PYG{n}{x0}\PYG{p}{,} \PYG{n}{args}\PYG{o}{=}\PYG{p}{(}\PYG{p}{)}\PYG{p}{,} \PYG{n}{bounds}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{projections}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} + \PYG{n}{npt}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{rhobeg}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{rhoend}\PYG{o}{=}\PYG{l+m+mf}{1e\PYGZhy{}8}\PYG{p}{,} \PYG{n}{maxfun}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} + \PYG{n}{nsamples}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{user\PYGZus{}params}\PYG{o}{=}\PYG{k+kc}{None}\PYG{p}{,} \PYG{n}{objfun\PYGZus{}has\PYGZus{}noise}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{,} + \PYG{n}{seek\PYGZus{}global\PYGZus{}minimum}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{,} + \PYG{n}{scaling\PYGZus{}within\PYGZus{}bounds}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{,} + \PYG{n}{do\PYGZus{}logging}\PYG{o}{=}\PYG{k+kc}{True}\PYG{p}{,} \PYG{n}{print\PYGZus{}progress}\PYG{o}{=}\PYG{k+kc}{False}\PYG{p}{)} \end{sphinxVerbatim} \end{quote} @@ -486,6 +475,10 @@ \section{Optional Arguments} \sphinxAtStartPar \sphinxcode{\sphinxupquote{bounds}} \sphinxhyphen{} a tuple \sphinxcode{\sphinxupquote{(lower, upper)}} with the vectors \(a\) and \(b\) of lower and upper bounds on \(x\) (default is \(a_i=-10^{20}\) and \(b_i=10^{20}\)). To set bounds for either \sphinxcode{\sphinxupquote{lower}} or \sphinxcode{\sphinxupquote{upper}}, but not both, pass a tuple \sphinxcode{\sphinxupquote{(lower, None)}} or \sphinxcode{\sphinxupquote{(None, upper)}}. +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{projections}} \sphinxhyphen{} a list of functions defining the Euclidean projections for each general convex constraint \(C_i\). Each element of the list \sphinxcode{\sphinxupquote{projections}} is a function that takes an input vector \(x\) and returns the closest point to \(x\) that is in \(C_i\). An example of using this is given below. + \item {} \sphinxAtStartPar \sphinxcode{\sphinxupquote{npt}} \sphinxhyphen{} the number of interpolation points to use (default is \(2n+1\) for a problem with \sphinxcode{\sphinxupquote{len(x0)=n}} if \sphinxcode{\sphinxupquote{objfun\_has\_noise=False}}, otherwise it is set to \((n+1)(n+2)/2\)). Py\sphinxhyphen{}BOBYQA requires \(n+1 \leq npt \leq (n+1)(n+2)/2\). Larger values are particularly useful for noisy problems. @@ -694,6 +687,105 @@ \section{Adding Bounds and More Output} \end{quote} +\section{Adding General Convex Constraints} +\label{\detokenize{userguide:adding-general-convex-constraints}} +\sphinxAtStartPar +We can also add more general convex constraints \(x \in C := C_1 \cap \cdots \cap C_n\) to our problem, where +each \(C_i\) is a convex set. To do this, we need to know the Euclidean projection operator for each \(C_i\): +\begin{equation*} +\begin{split}\operatorname{proj}_{C_i}(x) := \operatorname{argmin}_{y\in C_i} \|y-x\|_2^2.\end{split} +\end{equation*} +\sphinxAtStartPar +i.e. given a point \(x\), return the closest point to \(x\) in the set \(C_i\). +There are many examples of simple convex sets \(C_i\) for which this function has a known, simple form, such as: +\begin{itemize} +\item {} +\sphinxAtStartPar +Bound constraints (but since Py\sphinxhyphen{}BOBYQA supports this directly, it is better to give these explicitly via the \sphinxcode{\sphinxupquote{bounds}} input, as above) + +\item {} +\sphinxAtStartPar +Euclidean ball constraints: \(\|x-c\|_2 \leq r\) + +\item {} +\sphinxAtStartPar +Unit simplex: \(x_i \geq 0\) and \(\sum_{i=1}^{n} x_i \leq 1\) + +\item {} +\sphinxAtStartPar +Linear inequalities: \(a^T x \geq b\) + +\end{itemize} + +\sphinxAtStartPar +In Py\sphinxhyphen{}BOBYQA, set the input \sphinxcode{\sphinxupquote{projections}} to be a list of projection functions, one per \(C_i\). +Internally, Py\sphinxhyphen{}BOBYQA computes the projection onto the intersection of these sets and the bound constraints +using \sphinxhref{https://en.wikipedia.org/wiki/Dykstra\%27s\_projection\_algorithm}{Dykstra’s projection algorithm}. + +\sphinxAtStartPar +For the explicit expressions for the above projections, and more examples, see for example \sphinxhref{https://proximity-operator.net/indicatorfunctions.html}{this online database} +or Section 6.4.6 of the textbook \sphinxcite{userguide:b2017}. + +\sphinxAtStartPar +As an example, let’s minimize the above Rosenbrock function with different bounds, and with a Euclidean +ball constraint, namely \((x_1-0.5)^2 + (x_2-1)^2 \leq 0.25^2\). + +\sphinxAtStartPar +To do this, we can run +\begin{quote} + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{k+kn}{import} \PYG{n+nn}{numpy} \PYG{k}{as} \PYG{n+nn}{np} +\PYG{k+kn}{import} \PYG{n+nn}{pybobyqa} + +\PYG{c+c1}{\PYGZsh{} Define the objective function} +\PYG{k}{def} \PYG{n+nf}{rosenbrock}\PYG{p}{(}\PYG{n}{x}\PYG{p}{)}\PYG{p}{:} + \PYG{k}{return} \PYG{l+m+mf}{100.0} \PYG{o}{*} \PYG{p}{(}\PYG{n}{x}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]} \PYG{o}{\PYGZhy{}} \PYG{n}{x}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]} \PYG{o}{*}\PYG{o}{*} \PYG{l+m+mi}{2}\PYG{p}{)} \PYG{o}{*}\PYG{o}{*} \PYG{l+m+mi}{2} \PYG{o}{+} \PYG{p}{(}\PYG{l+m+mf}{1.0} \PYG{o}{\PYGZhy{}} \PYG{n}{x}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{p}{)} \PYG{o}{*}\PYG{o}{*} \PYG{l+m+mi}{2} + +\PYG{c+c1}{\PYGZsh{} Define the starting point} +\PYG{n}{x0} \PYG{o}{=} \PYG{n}{np}\PYG{o}{.}\PYG{n}{array}\PYG{p}{(}\PYG{p}{[}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.2}\PYG{p}{,} \PYG{l+m+mf}{1.0}\PYG{p}{]}\PYG{p}{)} + +\PYG{c+c1}{\PYGZsh{} Define bound constraints (lower \PYGZlt{}= x \PYGZlt{}= upper)} +\PYG{n}{lower} \PYG{o}{=} \PYG{n}{np}\PYG{o}{.}\PYG{n}{array}\PYG{p}{(}\PYG{p}{[}\PYG{l+m+mf}{0.7}\PYG{p}{,} \PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{2.0}\PYG{p}{]}\PYG{p}{)} +\PYG{n}{upper} \PYG{o}{=} \PYG{n}{np}\PYG{o}{.}\PYG{n}{array}\PYG{p}{(}\PYG{p}{[}\PYG{l+m+mf}{1.0}\PYG{p}{,} \PYG{l+m+mf}{2.0}\PYG{p}{]}\PYG{p}{)} + +\PYG{c+c1}{\PYGZsh{} Define the ball constraint ||x\PYGZhy{}center|| \PYGZlt{}= radius, and its projection operator} +\PYG{n}{center} \PYG{o}{=} \PYG{n}{np}\PYG{o}{.}\PYG{n}{array}\PYG{p}{(}\PYG{p}{[}\PYG{l+m+mf}{0.5}\PYG{p}{,} \PYG{l+m+mf}{1.0}\PYG{p}{]}\PYG{p}{)} +\PYG{n}{radius} \PYG{o}{=} \PYG{l+m+mf}{0.25} +\PYG{n}{ball\PYGZus{}proj} \PYG{o}{=} \PYG{k}{lambda} \PYG{n}{x}\PYG{p}{:} \PYG{n}{center} \PYG{o}{+} \PYG{p}{(}\PYG{n}{radius}\PYG{o}{/}\PYG{n+nb}{max}\PYG{p}{(}\PYG{n}{np}\PYG{o}{.}\PYG{n}{linalg}\PYG{o}{.}\PYG{n}{norm}\PYG{p}{(}\PYG{n}{x}\PYG{o}{\PYGZhy{}}\PYG{n}{center}\PYG{p}{)}\PYG{p}{,} \PYG{n}{radius}\PYG{p}{)}\PYG{p}{)} \PYG{o}{*} \PYG{p}{(}\PYG{n}{x}\PYG{o}{\PYGZhy{}}\PYG{n}{center}\PYG{p}{)} + +\PYG{c+c1}{\PYGZsh{} Call Py\PYGZhy{}BOBYQA (with bounds and projection operator)} +\PYG{c+c1}{\PYGZsh{} Note: it is better to provide bounds explicitly, instead of using the corresponding} +\PYG{c+c1}{\PYGZsh{} projection function} +\PYG{c+c1}{\PYGZsh{} Note: input \PYGZsq{}projections\PYGZsq{} must be a list of projection functions} +\PYG{n}{soln} \PYG{o}{=} \PYG{n}{pybobyqa}\PYG{o}{.}\PYG{n}{solve}\PYG{p}{(}\PYG{n}{rosenbrock}\PYG{p}{,} \PYG{n}{x0}\PYG{p}{,} \PYG{n}{bounds}\PYG{o}{=}\PYG{p}{(}\PYG{n}{lower}\PYG{p}{,}\PYG{n}{upper}\PYG{p}{)}\PYG{p}{,} \PYG{n}{projections}\PYG{o}{=}\PYG{p}{[}\PYG{n}{ball\PYGZus{}proj}\PYG{p}{]}\PYG{p}{)} + +\PYG{n+nb}{print}\PYG{p}{(}\PYG{n}{soln}\PYG{p}{)} +\end{sphinxVerbatim} +\end{quote} + +\sphinxAtStartPar +Py\sphinxhyphen{}BOBYQA correctly finds the solution to the constrained problem: +\begin{quote} + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +****** Py\PYGZhy{}BOBYQA Results ****** +Solution xmin = [0.70424386 0.85583188] +Objective value f(xmin) = 13.03829114 +Needed 25 objective evaluations (at 25 points) +Approximate gradient = [\PYGZhy{}101.9667031 71.97449424] +Approximate Hessian = [[ 253.11858775 \PYGZhy{}279.39193327] + [\PYGZhy{}279.39193327 201.49725358]] +Exit flag = 0 +Success: rho has reached rhoend +****************************** +\end{sphinxVerbatim} +\end{quote} + +\sphinxAtStartPar +Just like for bound constraints, Py\sphinxhyphen{}BOBYQA will automatically ensure the starting point is feasible with respect to all constraints (bounds and general convex constraints). + + \section{Example: Noisy Objective Evaluation} \label{\detokenize{userguide:example-noisy-objective-evaluation}} \sphinxAtStartPar @@ -961,15 +1053,15 @@ \section{Initialization of Points} \label{\detokenize{advanced:initialization-of-points}}\begin{itemize} \item {} \sphinxAtStartPar -\sphinxcode{\sphinxupquote{init.random\_initial\_directions}} \sphinxhyphen{} Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is \sphinxcode{\sphinxupquote{True}}. +\sphinxcode{\sphinxupquote{init.random\_initial\_directions}} \sphinxhyphen{} Build the initial interpolation set using random directions (as opposed to coordinate directions). Default is \sphinxcode{\sphinxupquote{True}}. Not used if general convex constraints provided. \item {} \sphinxAtStartPar -\sphinxcode{\sphinxupquote{init.random\_directions\_make\_orthogonal}} \sphinxhyphen{} If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is \sphinxcode{\sphinxupquote{True}}. +\sphinxcode{\sphinxupquote{init.random\_directions\_make\_orthogonal}} \sphinxhyphen{} If building initial interpolation set with random directions, whether or not these should be orthogonalized. Default is \sphinxcode{\sphinxupquote{True}}. Not used if general convex constraints provided. \item {} \sphinxAtStartPar -\sphinxcode{\sphinxupquote{init.run\_in\_parallel}} \sphinxhyphen{} If using random directions, whether or not to ask for all \sphinxcode{\sphinxupquote{objfun}} to be evaluated at all points without any intermediate processing. Default is \sphinxcode{\sphinxupquote{False}}. +\sphinxcode{\sphinxupquote{init.run\_in\_parallel}} \sphinxhyphen{} If using random directions, whether or not to ask for all \sphinxcode{\sphinxupquote{objfun}} to be evaluated at all points without any intermediate processing. Default is \sphinxcode{\sphinxupquote{False}}. Not used if general convex constraints provided. \end{itemize} @@ -1128,6 +1220,27 @@ \section{Multiple Restarts} \end{itemize} +\section{General Convex Constraints} +\label{\detokenize{advanced:general-convex-constraints}}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{projections.dykstra.d\_tol}} \sphinxhyphen{} termination tolerance for Dykstra’s algorithm for computing the projection onto the intersection of all convex constraints. Default is \(10^{-10}\). + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{projections.dykstra.max\_iters}} \sphinxhyphen{} maximum iterations of Dykstra’s algorithm for computing the projection onto the intersection of all convex constraints. Default is 100. + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{projections.feasible\_tol}} \sphinxhyphen{} tolerance for checking feasibility of initial points with respect to general convex constraints. Default is \(10^{-10}\). + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{projections.pgd\_tol}} \sphinxhyphen{} termination tolerance for trust\sphinxhyphen{}region and geometry\sphinxhyphen{}improving subproblems. Default is \(10^{-8}\). + +\end{itemize} + + \section{References} \label{\detokenize{advanced:references}} \sphinxstepscope @@ -1413,10 +1526,20 @@ \section{Version 1.4.1 (11 Apr 2024)} \end{itemize} +\section{Version 1.5.0 (16 Sep 2024)} +\label{\detokenize{history:version-1-5-0-16-sep-2024}}\begin{itemize} +\item {} +\sphinxAtStartPar +Added support for general convex constraints + +\end{itemize} + + \chapter{Acknowledgements} \label{\detokenize{index:acknowledgements}} \sphinxAtStartPar -This software was developed under the supervision of \sphinxhref{https://www.maths.ox.ac.uk/people/coralia.cartis}{Coralia Cartis}, and was supported by the EPSRC Centre For Doctoral Training in \sphinxhref{https://www.maths.ox.ac.uk/study-here/postgraduate-study/industrially-focused-mathematical-modelling-epsrc-cdt}{Industrially Focused Mathematical Modelling} (EP/L015803/1) in collaboration with the \sphinxhref{http://www.nag.com/}{Numerical Algorithms Group}. +This software was initially developed under the supervision of \sphinxhref{https://www.maths.ox.ac.uk/people/coralia.cartis}{Coralia Cartis}, and was supported by the EPSRC Centre For Doctoral Training in \sphinxhref{https://www.maths.ox.ac.uk/study-here/postgraduate-study/industrially-focused-mathematical-modelling-epsrc-cdt}{Industrially Focused Mathematical Modelling} (EP/L015803/1) in collaboration with the \sphinxhref{http://www.nag.com/}{Numerical Algorithms Group}. +Development of Py\sphinxhyphen{}BOBYQA has also been supported by the Australian Research Council (DE240100006). \begin{sphinxthebibliography}{Powell20} \bibitem[CFMR2018]{info:cfmr2018} @@ -1431,6 +1554,12 @@ \chapter{Acknowledgements} \bibitem[CRO2022]{userguide:cro2022} \sphinxAtStartPar Coralia Cartis, Lindon Roberts and Oliver Sheridan\sphinxhyphen{}Methven, \sphinxhref{https://doi.org/10.1080/02331934.2021.1883015}{Escaping local minima with derivative\sphinxhyphen{}free methods: a numerical investigation}, \sphinxstyleemphasis{Optimization}, 71:8 (2022), pp. 2343\sphinxhyphen{}2373. {[}\sphinxhref{https://arxiv.org/abs/1812.11343}{arXiv preprint: 1812.11343}{]} +\bibitem[R2024]{userguide:r2024} +\sphinxAtStartPar +Lindon Roberts, \sphinxhref{https://arxiv.org/abs/2403.14960}{Model Construction for Convex\sphinxhyphen{}Constrained Derivative\sphinxhyphen{}Free Optimization}, \sphinxstyleemphasis{arXiv preprint arXiv:2403.14960} (2024). +\bibitem[B2017]{userguide:b2017} +\sphinxAtStartPar +Amir Beck, \sphinxhref{https://doi.org/10.1137/1.9781611974997}{First\sphinxhyphen{}Order Methods in Optimization}, SIAM (2017). \bibitem[CFMR2018]{advanced:cfmr2018} \sphinxAtStartPar Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, \sphinxhref{https://doi.org/10.1145/3338517}{Improving the Flexibility and Robustness of Model\sphinxhyphen{}Based Derivative\sphinxhyphen{}Free Optimization Solvers}, \sphinxstyleemphasis{ACM Transactions on Mathematical Software}, 45:3 (2019), pp. 32:1\sphinxhyphen{}32:41 {[}\sphinxhref{https://arxiv.org/abs/1804.00154}{preprint}{]} diff --git a/docs/build/latex/Py-BOBYQA.toc b/docs/build/latex/Py-BOBYQA.toc index 8200b5c..4cb4e41 100644 --- a/docs/build/latex/Py-BOBYQA.toc +++ b/docs/build/latex/Py-BOBYQA.toc @@ -15,35 +15,38 @@ \contentsline {section}{\numberline {3.3}Optional Arguments}{8}{section.3.3}% \contentsline {section}{\numberline {3.4}A Simple Example}{10}{section.3.4}% \contentsline {section}{\numberline {3.5}Adding Bounds and More Output}{11}{section.3.5}% -\contentsline {section}{\numberline {3.6}Example: Noisy Objective Evaluation}{12}{section.3.6}% -\contentsline {section}{\numberline {3.7}Example: Global Optimization}{14}{section.3.7}% -\contentsline {section}{\numberline {3.8}References}{16}{section.3.8}% -\contentsline {chapter}{\numberline {4}Advanced Usage}{17}{chapter.4}% -\contentsline {section}{\numberline {4.1}General Algorithm Parameters}{17}{section.4.1}% -\contentsline {section}{\numberline {4.2}Logging and Output}{17}{section.4.2}% -\contentsline {section}{\numberline {4.3}Initialization of Points}{18}{section.4.3}% -\contentsline {section}{\numberline {4.4}Trust Region Management}{18}{section.4.4}% -\contentsline {section}{\numberline {4.5}Termination on Small Objective Value}{18}{section.4.5}% -\contentsline {section}{\numberline {4.6}Termination on Slow Progress}{18}{section.4.6}% -\contentsline {section}{\numberline {4.7}Stochastic Noise Information}{19}{section.4.7}% -\contentsline {section}{\numberline {4.8}Interpolation Management}{19}{section.4.8}% -\contentsline {section}{\numberline {4.9}Multiple Restarts}{19}{section.4.9}% -\contentsline {section}{\numberline {4.10}References}{20}{section.4.10}% -\contentsline {chapter}{\numberline {5}Diagnostic Information}{21}{chapter.5}% -\contentsline {section}{\numberline {5.1}Current Iterate}{21}{section.5.1}% -\contentsline {section}{\numberline {5.2}Trust Region}{21}{section.5.2}% -\contentsline {section}{\numberline {5.3}Model Interpolation}{22}{section.5.3}% -\contentsline {section}{\numberline {5.4}Iteration Count}{22}{section.5.4}% -\contentsline {section}{\numberline {5.5}Algorithm Progress}{22}{section.5.5}% -\contentsline {chapter}{\numberline {6}Version History}{23}{chapter.6}% -\contentsline {section}{\numberline {6.1}Version 1.0 (6 Feb 2018)}{23}{section.6.1}% -\contentsline {section}{\numberline {6.2}Version 1.0.1 (20 Feb 2018)}{23}{section.6.2}% -\contentsline {section}{\numberline {6.3}Version 1.0.2 (20 Jun 2018)}{23}{section.6.3}% -\contentsline {section}{\numberline {6.4}Version 1.1 (24 Dec 2018)}{23}{section.6.4}% -\contentsline {section}{\numberline {6.5}Version 1.1.1 (5 Apr 2019)}{24}{section.6.5}% -\contentsline {section}{\numberline {6.6}Version 1.2 (25 Feb 2020)}{24}{section.6.6}% -\contentsline {section}{\numberline {6.7}Version 1.3 (14 Apr 2021)}{24}{section.6.7}% -\contentsline {section}{\numberline {6.8}Version 1.4 (16 May 2023)}{24}{section.6.8}% -\contentsline {section}{\numberline {6.9}Version 1.4.1 (11 Apr 2024)}{24}{section.6.9}% -\contentsline {chapter}{\numberline {7}Acknowledgements}{25}{chapter.7}% -\contentsline {chapter}{Bibliography}{27}{chapter*.3}% +\contentsline {section}{\numberline {3.6}Adding General Convex Constraints}{12}{section.3.6}% +\contentsline {section}{\numberline {3.7}Example: Noisy Objective Evaluation}{13}{section.3.7}% +\contentsline {section}{\numberline {3.8}Example: Global Optimization}{15}{section.3.8}% +\contentsline {section}{\numberline {3.9}References}{17}{section.3.9}% +\contentsline {chapter}{\numberline {4}Advanced Usage}{19}{chapter.4}% +\contentsline {section}{\numberline {4.1}General Algorithm Parameters}{19}{section.4.1}% +\contentsline {section}{\numberline {4.2}Logging and Output}{19}{section.4.2}% +\contentsline {section}{\numberline {4.3}Initialization of Points}{20}{section.4.3}% +\contentsline {section}{\numberline {4.4}Trust Region Management}{20}{section.4.4}% +\contentsline {section}{\numberline {4.5}Termination on Small Objective Value}{20}{section.4.5}% +\contentsline {section}{\numberline {4.6}Termination on Slow Progress}{20}{section.4.6}% +\contentsline {section}{\numberline {4.7}Stochastic Noise Information}{21}{section.4.7}% +\contentsline {section}{\numberline {4.8}Interpolation Management}{21}{section.4.8}% +\contentsline {section}{\numberline {4.9}Multiple Restarts}{21}{section.4.9}% +\contentsline {section}{\numberline {4.10}General Convex Constraints}{22}{section.4.10}% +\contentsline {section}{\numberline {4.11}References}{22}{section.4.11}% +\contentsline {chapter}{\numberline {5}Diagnostic Information}{23}{chapter.5}% +\contentsline {section}{\numberline {5.1}Current Iterate}{23}{section.5.1}% +\contentsline {section}{\numberline {5.2}Trust Region}{23}{section.5.2}% +\contentsline {section}{\numberline {5.3}Model Interpolation}{24}{section.5.3}% +\contentsline {section}{\numberline {5.4}Iteration Count}{24}{section.5.4}% +\contentsline {section}{\numberline {5.5}Algorithm Progress}{24}{section.5.5}% +\contentsline {chapter}{\numberline {6}Version History}{25}{chapter.6}% +\contentsline {section}{\numberline {6.1}Version 1.0 (6 Feb 2018)}{25}{section.6.1}% +\contentsline {section}{\numberline {6.2}Version 1.0.1 (20 Feb 2018)}{25}{section.6.2}% +\contentsline {section}{\numberline {6.3}Version 1.0.2 (20 Jun 2018)}{25}{section.6.3}% +\contentsline {section}{\numberline {6.4}Version 1.1 (24 Dec 2018)}{25}{section.6.4}% +\contentsline {section}{\numberline {6.5}Version 1.1.1 (5 Apr 2019)}{26}{section.6.5}% +\contentsline {section}{\numberline {6.6}Version 1.2 (25 Feb 2020)}{26}{section.6.6}% +\contentsline {section}{\numberline {6.7}Version 1.3 (14 Apr 2021)}{26}{section.6.7}% +\contentsline {section}{\numberline {6.8}Version 1.4 (16 May 2023)}{26}{section.6.8}% +\contentsline {section}{\numberline {6.9}Version 1.4.1 (11 Apr 2024)}{26}{section.6.9}% +\contentsline {section}{\numberline {6.10}Version 1.5.0 (16 Sep 2024)}{27}{section.6.10}% +\contentsline {chapter}{\numberline {7}Acknowledgements}{29}{chapter.7}% +\contentsline {chapter}{Bibliography}{31}{chapter*.3}% diff --git a/docs/build/latex/sphinx.sty b/docs/build/latex/sphinx.sty index 6c31f32..633b244 100644 --- a/docs/build/latex/sphinx.sty +++ b/docs/build/latex/sphinx.sty @@ -3,10 +3,13 @@ % % Adapted from the old python.sty, mostly written by Fred Drake, % by Georg Brandl. -% +% This has now grown to become a full-fledged LaTeX support, split +% among multiple files, some of which provide features unavailable +% from usual LaTeX packages in interaction with the mark-up produced +% by the Sphinx LaTeX writer. \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{sphinx}[2023/03/19 v6.2.0 LaTeX package (Sphinx markup)] +\ProvidesPackage{sphinx}[2024/07/01 v7.4.0 Sphinx LaTeX package (sphinx-doc)] % provides \ltx@ifundefined % (many packages load ltxcmds: graphicx does for pdftex and lualatex but @@ -34,26 +37,26 @@ } %% important build warnings use an undefined reference to induce latexmk %% into complaining (once per warning) at very end of console output -\newcommand\sphinxbuildwarning[1]{% - \ifcsname sphinx_emitted_#1\endcsname +\newcommand\sphinxbuildwarning[2][]{% + \ifcsname sphinx_emitted_#2\endcsname \else - \global\expandafter\let\csname sphinx_emitted_#1\endcsname\@empty + \global\expandafter\let\csname sphinx_emitted_#2\endcsname\@empty \AtEndDocument{\hbox{% should the printing of text be made conditional on - % some boolean? + % some boolean? (7.4.0 answers this by adding an + % optional argument and testing it here for emptiness + % but no usage is made of this novelty yet.) + \if\relax\detokenize{#1}\relax + % No [], print a red warning text at very end of document \bfseries\color{red}% - \@nameuse{sphinx_buildwarning_#1}% + \@nameuse{sphinx_buildwarning_#2}% + \fi % place an undefined reference deliberately \let\nfss@text\@gobble % no ?? - \ref{!!\@nameuse{sphinx_buildwarning_#1}}% - }}% + \ref{!!\@nameuse{sphinx_buildwarning_#2}}% + }% + }% \fi } -\@namedef{sphinx_buildwarning_coloursyntax}{% - The colours whose definition used xcolor syntax were set to white - as xcolor was not found; check the latex log warnings for details} -\@namedef{sphinx_buildwarning_colorblend}{% - Command \string\sphinxcolorblend\space seen but ignored in tables - as xcolor was not found; check the latex log warnings for details} \@namedef{sphinx_buildwarning_badtitlesec}{% Your system has titlesec version 2.10.1 which causes disappearance of section numbers; check the latex log warning for details} @@ -63,29 +66,28 @@ \@namedef{sphinx_buildwarning_badfootnotes}{% Footnote rendering may have had problems, due to extra package or document class; check latex log for instructions}% - +\@namedef{sphinx_buildwarning_badiconpackage}{% + You have set iconpackage=\spx@opt@iconpackage, but this LaTeX package + is not found}% %% OPTION HANDLING % - % We generally first handle options then load packages, but we need -% \definecolor from xcolor/color to handle the options. +% \definecolor and \colorlet from xcolor to handle the options. +% Support for colour options +% -------------------------- +% At 7.4.0, package xcolor is required (which has allowed to get rid of +% annoying fall-back branches). Internals here got refactored to some extent. +% % MEMO: xcolor \fcolorbox coloured boxes render better in some PDF viewers % than with color package \fcolorbox. Since 1.6.3, Sphinx uses only its own % custom variant of \fcolorbox when handling code-blocks. But \fcolorbox -% appears also in Pygmentize output mark-up. Also, since 5.3.0, 'sphinxsetup' -% color options get a richer input syntax if Sphinx knows xcolor is loaded, -% and the \sphinxcolorblend (for tables) is made available only if xcolor is -% loaded. -\IfFileExists{xcolor.sty}{ +% appears also in Pygmentize output mark-up. % Should Sphinx load xcolor with its dvipsnames and svgnames options? - \RequirePackage{xcolor} -}{ - \RequirePackage{color} -} +\RequirePackage{xcolor} -% the \colorlet of xcolor (if at all loaded) is overkill for most internal use +% the \colorlet of xcolor is overkill for our internal usage here \newcommand{\sphinxcolorlet}[2] {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname \csname\@backslashchar color@#2\endcsname } @@ -93,6 +95,8 @@ % (5.3.0) Allow colour options to use both the \definecolor and the \colorlet % syntaxes, for example VerbatimColor={gray}{0.9} or VerbatimColor=red!10 % In the latter case we need the real \colorlet from xcolor package. +% Prior to 7.4.0 xcolor was not required and thus \spx@colorlet was configured +% to raise a warning in case of absence of xcolor. \def\spx@defineorletcolor#1{% \def\spx@definedcolor{{#1}}% \futurelet\spx@token\spx@defineorlet} @@ -101,21 +105,17 @@ \expandafter\spx@definecolor\else\expandafter\spx@colorlet\fi} \def\spx@colorlet#1\relax{\expandafter\colorlet\spx@definedcolor{#1}} \def\spx@definecolor{\expandafter\definecolor\spx@definedcolor} -% -\@ifpackageloaded{xcolor}% - {}% - {% xcolor not loaded because it was not found in the LaTeX installation -\def\spx@colorlet#1\relax{% - \sphinxbuildwarning{coloursyntax}% - \PackageWarning{sphinx}{% -Sorry, the #1 syntax requires package xcolor,\MessageBreak -which was not found on your TeX/LaTeX installation.\MessageBreak -\@spaces\expandafter\@firstofone\spx@definedcolor\MessageBreak -will be set to white}% - \expandafter\definecolor\spx@definedcolor{rgb}{1,1,1}% - }% end of redefinition of \spx@colorlet - }% end of xcolor not found branch - +% These internals refactored at 7.4.0: +\newcommand*{\spx@DeclareColorOption}[3][]{% +% #1 = almost always "sphinx" but left empty for a few for legacy reasons +% #2 = option name, but internal colour name is #1#2 (i.e. with prefix) +% #3 = initial default colour with either \definecolor or \colorlet syntax + % Set the initial default + \spx@defineorletcolor{#1#2}#3\relax + % Set the key handler to accept both \definecolor and \colorlet syntax + % The key name does not have the #1 prefix from the colour name + \define@key{sphinx}{#2}{\spx@defineorletcolor{#1#2}##1\relax}% +}% % Handle options via "kvoptions" (later loaded by hyperref anyhow) \RequirePackage{kvoptions} @@ -159,10 +159,15 @@ will be set to white}% \define@key{sphinx}{bookmarksdepth}{\AtBeginDocument{\hypersetup{bookmarksdepth=#1}}} \AtBeginDocument{\define@key{sphinx}{bookmarksdepth}{\hypersetup{bookmarksdepth=#1}}} % \DeclareBoolOption[false]{usespart}% not used + +% Code-blocks +% ----------- +% % INFO: the keys for padding and border widths were extended at 5.1.0, % and legacy names for user interface were kept, but their definitions % are delayed further down. The legacy internally used dimen registers % \sphinxverbatimborder and \sphinxverbatimsep got removed at 6.2.0. +% More code-blocks related options are found in "CSS" part below. \DeclareBoolOption[true]{verbatimwithframe} \DeclareBoolOption[true]{verbatimwrapslines} \DeclareBoolOption[false]{verbatimforcewraps} @@ -180,70 +185,50 @@ will be set to white}% \DeclareStringOption % must use braces to hide the brackets [{\makebox[2\fontcharwd\font`\x][r]{\textcolor{red}{\tiny$\m@th\hookrightarrow$}}}]% {verbatimcontinued} -% topic boxes + +% Topic boxes +% ----------- % % 5.1.0 added new keys for configuration. The legacy keys shadowsep, -% shadowsize, shadowrule were kept for backward compatibility. Unfortunately -% this had bugs due to typos, which got fixed later at 6.1.2. +% shadowsize, shadowrule were kept for backward compatibility. +% 5.1.2 fixed some bugs. % % All configuration is now to be found in the "CSS" section below. % -% \sphinxshadowsep, \sphinxshadowsize, \sphinxshadowrule \dimen registers -% became at 5.1.0 either no-op or, for the latter, were used under an aliased -% name. They got removed at 6.2.0. -% -% notices/admonitions -% -% 5.1.0 added much customizability to warning, caution, attention, danger and -% error types of notices via an enhanced sphinxheavybox environment. -% -% 6.2.0 added the possibility to use the same kind of rendering also for -% note, hint, important, and tip. -% -% Legacy user interface for options was kept working. All of it is handled in -% the "CSS" section below. -% -% These 6.2.0 added booleans serve internally. There is no reason for user to -% know about them, except if it is desired to toggle mid-way in the document -% whether note, hint, important, and tip should use the "lightbox" or the -% "heavybox" rendering. -\DeclareBoolOption[false]{heavynote} -\DeclareBoolOption[false]{heavyhint} -\DeclareBoolOption[false]{heavyimportant} -\DeclareBoolOption[false]{heavytip} -% footnotes +% 6.2.0 removed \sphinxshadowsep, \sphinxshadowsize, \sphinxshadowrule +% \dimen registers + +% Footnotes +% --------- \DeclareStringOption[\mbox{ }]{AtStartFootnote} % we need a public macro name for direct use in latex file \newcommand*{\sphinxAtStartFootnote}{\spx@opt@AtStartFootnote} % no such need for this one, as it is used inside other macros \DeclareStringOption[\leavevmode\unskip]{BeforeFootnote} -% some font styling. + +% Some font styling +% ----------------- +% TODO: the replacement of old syntax \py@HeaderFamily as used +% in sphinxlatexstyle{page,headings}.sty and sphinx{manual,howto}.cls +% has never been really put in place. Hence this isolated tidbit here. \DeclareStringOption[\sffamily\bfseries]{HeaderFamily} -% colours -% same problems as for dimensions: we want the key handler to use \definecolor. -% first, some colours with no prefix, for backward compatibility -\newcommand*{\sphinxDeclareColorOption}[2]{% - % set the initial default; only \definecolor syntax for defaults! - \definecolor{#1}#2% - % set the key handler to accept both \definecolor and \colorlet syntax - \define@key{sphinx}{#1}{\spx@defineorletcolor{#1}##1\relax}% -}% -\sphinxDeclareColorOption{TitleColor}{{rgb}{0.126,0.263,0.361}} -\sphinxDeclareColorOption{InnerLinkColor}{{rgb}{0.208,0.374,0.486}} -\sphinxDeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} -\sphinxDeclareColorOption{VerbatimColor}{{gray}{0.95}} -\sphinxDeclareColorOption{VerbatimBorderColor}{{RGB}{32,32,32}} -% all other colours will be named with a "sphinx" prefix -\newcommand*{\sphinxDeclareSphinxColorOption}[2]{% - % set the initial default; only \definecolor syntax for defaults! - \definecolor{sphinx#1}#2% - % set the key handler to accept both \definecolor and \colorlet syntax - \define@key{sphinx}{#1}{\spx@defineorletcolor{sphinx#1}##1\relax}% -}% -% table row colors -\sphinxDeclareSphinxColorOption{TableRowColorHeader}{{gray}{0.86}} -\sphinxDeclareSphinxColorOption{TableRowColorOdd}{{gray}{0.92}} -\sphinxDeclareSphinxColorOption{TableRowColorEven}{{gray}{0.98}} + +% Some legacy colour options +% -------------------------- +% +\spx@DeclareColorOption{TitleColor}{{rgb}{0.126,0.263,0.361}} +\spx@DeclareColorOption{InnerLinkColor}{{rgb}{0.208,0.374,0.486}} +\spx@DeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} +% The Verbatim ones are "legacy" only since 5.1.0... call it "new-legacy" ;-) +\spx@DeclareColorOption{VerbatimColor}{{RGB}{242,242,242}}% same as {gray}{0.95} +\spx@DeclareColorOption{VerbatimBorderColor}{{RGB}{32,32,32}} +% All other colours will be internally assigned a "sphinx" prefix + +% Table row colors (since 6.0.0) +% ---------------- +\spx@DeclareColorOption[sphinx]{TableRowColorHeader}{{gray}{0.86}} +\spx@DeclareColorOption[sphinx]{TableRowColorOdd}{{gray}{0.92}} +\spx@DeclareColorOption[sphinx]{TableRowColorEven}{{gray}{0.98}} % if not set, the "Merge" colour will keep in sync with the "Row" colour \def\sphinxTableMergeColorHeader{sphinxTableRowColorHeader} \define@key{sphinx}{TableMergeColorHeader}{% @@ -261,37 +246,67 @@ will be set to white}% \def\sphinxTableMergeColorEven{sphinxTableMergeColorEven}% }% % Default color chosen to be as in minted.sty LaTeX package! -\sphinxDeclareSphinxColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} -% admonition boxes, "light" style -% border color defaults to black -% at 6.2.0 also background color is possible, but it then triggers -% usage of the "sphinxheavybox" from sphinxlatexadmonitions.sty. -\sphinxDeclareSphinxColorOption{noteBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{hintBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{importantBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{tipBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{noteBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{hintBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{importantBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{tipBgColor}{{rgb}{1,1,1}} -% admonition boxes, "heavy" style -% border color defaults to black and background color to white -% As long as the color are not explicitly set via user options, -% the sphinxpackageboxes.sty code will actually not use them anyhow. -\sphinxDeclareSphinxColorOption{warningBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{cautionBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{attentionBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{dangerBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareSphinxColorOption{errorBorderColor}{{rgb}{0,0,0}} -% BgColor should have been from the start BackgroundColor for better -% match with CSS property names, but this is legacy interface -% which is too late to change because the internal color names -% and not only the option names have been documented at user level. -\sphinxDeclareSphinxColorOption{warningBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{cautionBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{attentionBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{dangerBgColor}{{rgb}{1,1,1}} -\sphinxDeclareSphinxColorOption{errorBgColor}{{rgb}{1,1,1}} +\spx@DeclareColorOption[sphinx]{VerbatimHighlightColor}{{rgb}{0.878,1,1}} + +% Notices/admonitions +% ------------------- +% +% 5.1.0 added much customizability to warning, caution, attention, danger and +% error types of notices via an enhanced sphinxheavybox environment. +% +% 6.2.0 added the possibility to use the same kind of rendering also for +% note, hint, important, and tip. +% +% Legacy user interface for options was kept working. All of it is handled in +% the "CSS" section below. +% +% 6.2.0 added booleans to serve internally as a record of whether the +% note, hint, important and tip admonitions used the legacy "lightbox" or +% the then enhanced "heavybox" environment. +% +% 7.4.0 uses "heavybox" environment from sphinxlatexadmonitions in all cases, +% hence the booleans mentioned above have been removed as well as the rather +% complex TeX code which was done so that these booleans were made true if +% and only if the CSS-named keys had been made usage of via 'sphinxsetup'. +% +% The "light style" implemented in sphinxlatexadmonitions.sty as +% "sphinxlightbox" is not used. Also, admonitions by default have a "title +% row", and the corresponding options are only named in the CSS style which is +% implemented further below. Here we define options having a legacy name. +% +% seealso directive is also using "heavybox" at 7.4.0 acquiring the same +% customizability as admonitions. +% todo directive also. +\definecolor{sphinx-admonition-bgcolor} {RGB}{247, 247, 247}% #F7F7F7 +\definecolor{sphinx-admonition-bordercolor} {RGB}{134, 152, 155}% #86989B +\definecolor{sphinx-warning-bordercolor} {RGB}{148, 0, 0}% #940000 +\definecolor{sphinx-error-bordercolor} {RGB}{180, 0, 0}% #B40000 +\spx@DeclareColorOption[sphinx]{noteBorderColor} {sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{hintBorderColor} {sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{importantBorderColor}{sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{tipBorderColor} {sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{seealsoBorderColor} {sphinx-admonition-bordercolor}% 7.4.0 +\spx@DeclareColorOption[sphinx]{todoBorderColor} {sphinx-admonition-bordercolor}% 7.4.0 +% +\spx@DeclareColorOption[sphinx]{noteBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{hintBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{importantBgColor}{sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{tipBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{seealsoBgColor} {sphinx-admonition-bgcolor}% 7.4.0 +\spx@DeclareColorOption[sphinx]{todoBgColor} {sphinx-admonition-bgcolor}% 7.4.0 +% +\spx@DeclareColorOption[sphinx]{warningBorderColor} {sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{cautionBorderColor} {sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{attentionBorderColor}{sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{dangerBorderColor} {sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{errorBorderColor} {sphinx-error-bordercolor} +% +\spx@DeclareColorOption[sphinx]{warningBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{cautionBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{attentionBgColor}{sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{dangerBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{errorBgColor} {sphinx-admonition-bgcolor} +% %%%%%%%% % % Additions of CSS-like keys at 5.1.0 (and possibility of rounded boxes) @@ -324,14 +339,25 @@ will be set to white}% % finally been removed entirely. No more \dimen register is used here only % storage in macros. % +% Restyling at 7.4.0 with new defaults for all admonition types +% ------------------------------------------------------------- +% +% So far the 5.1.0 added possibilities for fancier boxes had been used by +% default only for code-blocks, and admonitions kept their old-fashioned +% legacy styles. At 7.4.0, as a follow-up to the revamped styles of +% admonitions in the HTML sphinx13 theme (PR #12439), it is decided to +% apply similar styling for PDF output. Also the seealso directive +% is handled as an admonition with the same customizability. And the +% todo directive. +% \def\spxstring@none{none} \def\spxstring@clone{clone} % % Border keys -% +% At 7.4.0 refactoring to avoid defining legacy \spx@@border +% macros which are (now) used nowhere, only @top, @right, @bottom, @left. \def\spx@tempa#1{% #1 = macro prefix \expandafter\spx@tempb - \csname #1border\expandafter\endcsname \csname #1border@top\expandafter\endcsname \csname #1border@right\expandafter\endcsname \csname #1border@bottom\expandafter\endcsname @@ -340,99 +366,100 @@ will be set to white}% \csname #1border@opentrue\expandafter\endcsname \csname #1border@openfalse\endcsname }% -\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #9 = option prefix - \define@key{sphinx}{#9border-top-width}{\def#2{##1}}% - \define@key{sphinx}{#9border-right-width}{\def#3{##1}}% - \define@key{sphinx}{#9border-bottom-width}{\def#4{##1}}% - \define@key{sphinx}{#9border-left-width}{\def#5{##1}}% - \define@key{sphinx}{#9border-width}{% - \def#1{##1}% MEMO: not immediately expanded, should this be changed? - \def#2{#1}\let#3#2\let#4#2\let#5#2% +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #8 = option prefix + \define@key{sphinx}{#8border-top-width}{\def#1{##1}}% + \define@key{sphinx}{#8border-right-width}{\def#2{##1}}% + \define@key{sphinx}{#8border-bottom-width}{\def#3{##1}}% + \define@key{sphinx}{#8border-left-width}{\def#4{##1}}% + \define@key{sphinx}{#8border-width}{% + % MEMO: not immediately expanded, should this be changed? + \def#1{##1}\let#2#1\let#3#1\let#4#1% }% - \newif#6% - \define@key{sphinx}{#9box-decoration-break}% + \newif#5% + % 6.2.0 has added support for box-decoration-break also to admonition + % directives, formerly the option setting was ignored for them. + \define@key{sphinx}{#8box-decoration-break}% {\begingroup\edef\spx@tempa{##1}\expandafter\endgroup - \ifx\spx@tempa\spxstring@clone#8\else#7\fi}% - \spx@tempc{#9}% option prefix -} -\def\spx@tempc #1#2{% #1 = option prefix, #2 = legacy option name + \ifx\spx@tempa\spxstring@clone#7\else#6\fi}% + % 7.4.0 sets the default behaviour to "slice" not only for code-blocks but + % also for admonitions, as the latter now have a background colour each. + #6% + % #8 = option prefix (with underscore), #9 = legacy option name % keep legacy option names as aliases to new-named options - \expandafter\let\csname KV@sphinx@#2\expandafter\endcsname - \csname KV@sphinx@#1border-width\endcsname + \expandafter\let\csname KV@sphinx@#9\expandafter\endcsname + \csname KV@sphinx@#8border-width\endcsname % init border-width (fetches next argument) - \csname KV@sphinx@#1border-width\endcsname + \csname KV@sphinx@#8border-width\endcsname } -% MEMO: prior to 6.2.0 the \fboxrule value (0.4pt, a priori) was frozen here via -% a \dimen assignment done immediately. Now it remains \fboxrule until being used. +% MEMO: from 6.2.0 to 7.4.0 (excluive) \fboxrule was used in the first +% two, and was resolved only at location of use. At 7.4.0, we again +% use 0.4pt rather and not \fboxrule dimen register. % macro prefix option prefix legacy option init value -\spx@tempa{spx@pre@} {pre_} {verbatimborder} \fboxrule -\spx@tempa{spx@topic@} {div.topic_} {shadowrule} \fboxrule +\spx@tempa{spx@pre@} {pre_} {verbatimborder} {0.4pt} +\spx@tempa{spx@topic@} {div.topic_} {shadowrule} {0.5pt}% mod. at 7.4.0 \spx@tempa{spx@note@} {div.note_} {noteborder} {0.5pt} \spx@tempa{spx@hint@} {div.hint_} {hintborder} {0.5pt} \spx@tempa{spx@important@}{div.important_}{importantborder}{0.5pt} \spx@tempa{spx@tip@} {div.tip_} {tipborder} {0.5pt} +\spx@tempa{spx@seealso@} {div.seealso_} {seealsoborder} {0.5pt}% new at 7.4.0 +\spx@tempa{spx@todo@} {div.todo_} {todoborder} {0.5pt}% new at 7.4.0 \spx@tempa{spx@warning@} {div.warning_} {warningborder} {1pt} \spx@tempa{spx@caution@} {div.caution_} {cautionborder} {1pt} \spx@tempa{spx@attention@}{div.attention_}{attentionborder}{1pt} \spx@tempa{spx@danger@} {div.danger_} {dangerborder} {1pt} -\spx@tempa{spx@error@} {div.error_} {errorborder} {1pt} +\spx@tempa{spx@error@} {div.error_} {errorborder} {1.25pt}% mod. at 7.4.0 % this one new at 6.2.0: (we do not create a "legacy name" for it) -\spx@tempa{spx@box@} {box_} {box_border-width}\fboxrule -% Set default box-decoration-break style for codeblocks to slice -\spx@pre@border@opentrue % new default at 6.0.0: slice, not clone -% 6.2.0 has added support for box-decoration-break=slice to all -% other directives, formerly the option setting was ignored for them. +\spx@tempa{spx@box@} {box_} {box_border-width}{0.4pt} +% Reset default box-decoration-break style to "clone" for \sphinxbox, +% but anyhow this is ignored as \sphinxbox produces unbreakable boxes. +\spx@box@border@openfalse % Padding keys -% +% At 7.4.0, \spx@@padding internal macros removed, only @top, @right, +% @bottom, @left are actually needed by sphinxpackageboxes.sty. \def\spx@tempa#1{% \expandafter\spx@tempb - \csname #1padding\expandafter\endcsname \csname #1padding@top\expandafter\endcsname \csname #1padding@right\expandafter\endcsname \csname #1padding@bottom\expandafter\endcsname \csname #1padding@left\endcsname }% -\def\spx@tempb #1#2#3#4#5#6{% #6 = option prefix - \define@key{sphinx}{#6padding-top}{\def#2{##1}}% - \define@key{sphinx}{#6padding-right}{\def#3{##1}}% - \define@key{sphinx}{#6padding-bottom}{\def#4{##1}}% - \define@key{sphinx}{#6padding-left}{\def#5{##1}}% - \define@key{sphinx}{#6padding}{% - \def#1{##1}% - \def#2{#1}\let#3#2\let#4#2\let#5#2% +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #5 = option prefix + \define@key{sphinx}{#5padding-top}{\def#1{##1}}% + \define@key{sphinx}{#5padding-right}{\def#2{##1}}% + \define@key{sphinx}{#5padding-bottom}{\def#3{##1}}% + \define@key{sphinx}{#5padding-left}{\def#4{##1}}% + \define@key{sphinx}{#5padding}{% + \def#1{##1}\let#2#1\let#3#1\let#4#1% }% - % initialization (will fetch "init" argument next): - \csname KV@sphinx@#6padding\endcsname + % initial defaults + \def#1{#6}\def#2{#7}\def#3{#8}\def#4{#9}% } % MEMO: prior to 6.2.0 the \fboxsep value (3pt, a priori) was frozen here via -% a \dimen assignment done immediately. Now it remains \fboxsep until being used. -% #1 macro prefix #6 option prefix init value -\spx@tempa{spx@pre@} {pre_} \fboxsep -\spx@tempa{spx@topic@} {div.topic_} {5pt} -% MEMO: prior to 6.2.0, "note" type admonitions used sphinxlightbox automatically -% and had no interface to set the padding parameters needed by sphinxheavybox. -% At 6.2.0 they acquired such interface and the default is set as for legacy -% default of "warning" type. I hesitated using \fboxsep, but if I did I would -% then need to explain how to change "note etc..." into behaving exactly -% as "warning etc...", which goes via the \dimexpr here which is too scary to -% put sanely into documentation. -\spx@tempa{spx@note@} {div.note_} {\dimexpr.6\baselineskip-\spx@note@border\relax} -\spx@tempa{spx@hint@} {div.hint_} {\dimexpr.6\baselineskip-\spx@hint@border\relax} -\spx@tempa{spx@important@}{div.important_} {\dimexpr.6\baselineskip-\spx@important@border\relax} -\spx@tempa{spx@tip@} {div.tip_} {\dimexpr.6\baselineskip-\spx@tip@border\relax} -% MEMO: prior to 5.1.0 padding was not separately customizable from border -% width for warning type admonitions. The below keeps the legacy behavior of a -% constant borderwidth+padding. The dim expression is not evaluated yet, only -% at time of use (so that it dynamically adapts to the border width setting). -% MEMO: I could use everywhere \spx@notice@border, as sphinxadmonition environment -% configures it to hold the \spx@@border value. -\spx@tempa{spx@warning@} {div.warning_} {\dimexpr.6\baselineskip-\spx@warning@border\relax} -\spx@tempa{spx@caution@} {div.caution_} {\dimexpr.6\baselineskip-\spx@caution@border\relax} -\spx@tempa{spx@attention@}{div.attention_} {\dimexpr.6\baselineskip-\spx@attention@border\relax} -\spx@tempa{spx@danger@} {div.danger_} {\dimexpr.6\baselineskip-\spx@danger@border\relax} -\spx@tempa{spx@error@} {div.error_} {\dimexpr.6\baselineskip-\spx@error@border\relax} -\spx@tempa{spx@box@} {box_} \fboxsep +% a \dimen assignment done immediately. From 6.2.0 to 7.4.0 an unfrozen +% \fboxsep was used, and at 7.4.0 it is again explicit 3pt. +% The defaults for admonitions were all modified at 7.4.0. +% For topic/contents and all admonitions the horizontal padding plus borders +% are put inside the text area (i.e. do not go into the margins). +% In order for perfect exact same vertical alignment of contents from all such +% directives, the value of horizontal border-width+padding is kept constant +% (equal to 7.5pt since 7.4.0). +% #1 macro prefix #6 option prefix top right bottom left +\spx@tempa{spx@pre@} {pre_} {3pt}{3pt}{3pt}{3pt} +\spx@tempa{spx@topic@} {div.topic_} {10pt}{7pt}{12pt}{7pt} +% 7.4.0 drops legacy settings which linked strangely padding with border width +\spx@tempa{spx@note@} {div.note_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@hint@} {div.hint_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@important@}{div.important_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@tip@} {div.tip_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@seealso@} {div.seealso_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@todo@} {div.todo_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@warning@} {div.warning_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@caution@} {div.caution_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@attention@}{div.attention_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@danger@} {div.danger_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@error@} {div.error_} {6pt}{6.25pt}{6pt}{6.25pt} +\spx@tempa{spx@box@} {box_} {3pt}{3pt}{3pt}{3pt} % define legacy verbatimsep key as alias of pre_padding key \expandafter\let\expandafter\KV@sphinx@verbatimsep\csname KV@sphinx@pre_padding\endcsname % define legacy shadowsep key as alias of div.topic_padding key @@ -450,30 +477,35 @@ will be set to white}% \csname #1radius@bottomright\expandafter\endcsname \csname #1radius@bottomleft\endcsname }% -\def\spx@tempb #1#2#3#4#5{% #5 = option prefix +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #5 = option prefix \define@key{sphinx}{#5border-top-left-radius}{\def#1{##1}}% \define@key{sphinx}{#5border-top-right-radius}{\def#2{##1}}% \define@key{sphinx}{#5border-bottom-right-radius}{\def#3{##1}}% \define@key{sphinx}{#5border-bottom-left-radius}{\def#4{##1}}% \define@key{sphinx}{#5border-radius}{\def#1{##1}\let#2#1\let#3#1\let#4#1}% - \csname KV@sphinx@#5border-radius\endcsname % fetches next argument + \def#1{#6}\def#2{#7}\def#3{#8}\def#4{#9}% } % The init value for corner radius in code-blocks was \z@ (i.e. 0pt) prior -% to 6.0.0., then 3pt, then \fboxsep at 6.2.0 as padding is \fboxsep, -% and \fboxsep=3pt per default (also with platex). -% macro prefix option prefix init value -\spx@tempa{spx@pre@} {pre_} \fboxsep -\spx@tempa{spx@topic@} {div.topic_} \z@ -\spx@tempa{spx@note@} {div.note_} \z@ -\spx@tempa{spx@hint@} {div.hint_} \z@ -\spx@tempa{spx@important@}{div.important_} \z@ -\spx@tempa{spx@tip@} {div.tip_} \z@ -\spx@tempa{spx@warning@} {div.warning_} \z@ -\spx@tempa{spx@caution@} {div.caution_} \z@ -\spx@tempa{spx@attention@}{div.attention_} \z@ -\spx@tempa{spx@danger@} {div.danger_} \z@ -\spx@tempa{spx@error@} {div.error_} \z@ -\spx@tempa{spx@box@} {box_} \fboxsep +% to 6.0.0., then 3pt, then \fboxsep at 6.2.0 as padding was also \fboxsep. +% At 7.4.0: +% - the 3pt is used (which is normal value of \fboxsep). +% - some admonitions use rounded corners as well. +% - topic boxed have only their bottom right corner rounded. +% macro prefix option prefix tl tr br bl +\spx@tempa{spx@pre@} {pre_} {3pt}{3pt}{3pt}{3pt} +\spx@tempa{spx@topic@} {div.topic_} \z@ \z@ {12pt} \z@ +\spx@tempa{spx@note@} {div.note_} {5pt}{5pt}{5pt}{5pt} +\spx@tempa{spx@hint@} {div.hint_} {5pt}{5pt}{5pt}{5pt} +\spx@tempa{spx@important@}{div.important_} \z@\z@\z@\z@ +\spx@tempa{spx@tip@} {div.tip_} {5pt}{5pt}{5pt}{5pt} +\spx@tempa{spx@seealso@} {div.seealso_} \z@\z@\z@\z@ +\spx@tempa{spx@todo@} {div.todo_} \z@\z@\z@\z@ +\spx@tempa{spx@warning@} {div.warning_} \z@\z@\z@\z@ +\spx@tempa{spx@caution@} {div.caution_} \z@\z@\z@\z@ +\spx@tempa{spx@attention@}{div.attention_} \z@\z@\z@\z@ +\spx@tempa{spx@danger@} {div.danger_} \z@\z@\z@\z@ +\spx@tempa{spx@error@} {div.error_} \z@\z@\z@\z@ +\spx@tempa{spx@box@} {box_} {3pt}{3pt}{3pt}{3pt} % Shadow keys % @@ -494,6 +526,8 @@ will be set to white}% \spx@tempa{spx@hint@} \spx@tempa{spx@important@} \spx@tempa{spx@tip@} +\spx@tempa{spx@seealso@}% 7.4.0 +\spx@tempa{spx@todo@}% 7.4.0 \spx@tempa{spx@warning@} \spx@tempa{spx@caution@} \spx@tempa{spx@attention@} @@ -541,6 +575,8 @@ will be set to white}% \spx@tempa{spx@hint@} {div.hint_} \spx@tempa{spx@important@}{div.important_} \spx@tempa{spx@tip@} {div.tip_} +\spx@tempa{spx@seealso@} {div.seealso_} +\spx@tempa{spx@todo@} {div.todo_} \spx@tempa{spx@warning@} {div.warning_} \spx@tempa{spx@caution@} {div.caution_} \spx@tempa{spx@attention@}{div.attention_} @@ -552,7 +588,6 @@ will be set to white}% % This definition was broken due to a typo at 5.1.0 and got fixed at 6.1.2 % MEMO: at 6.2.0 this no longer does \number\dimexpr in an \edef. Reason is to % keep in sync with div.topic_box-shadow handling of xoffset and yoffset. -% Attention in particular to \ifdim context, we add a \dimexpr to the one here. \define@key{sphinx}{shadowsize}{% \def\spx@topic@shadow@xoffset{#1}% \let\spx@topic@shadow@yoffset\spx@topic@shadow@xoffset @@ -564,8 +599,9 @@ will be set to white}% \fi }% -% Color keys -% (four of them: border, background, shadow and the text color) +% Color keys, TeXextras key, keys for admonition titles with icon +% +% Historical remarks to be removed at some point: % % Some problems due to legacy naming scheme which had diverging conventions % for code-blocks (VerbatimBorderColor, VerbatimColor) and admonitions @@ -574,27 +610,31 @@ will be set to white}% % example sphinxwarningBgColor are also documented at user level, they are not % only internally used. % -% For topic directive, "legacy" (by this I mean Sphinx around 2016-2017 after -% my first additions to LaTeX) had no interface for colors, so I could change -% some internals with no breakage during 5.x up to 6.2.0. So topic -% (shadowbox) could be unified with admonitions (sphinxheavybox), and the -% "set-up" macros could all be moved into a single one in the -% sphinxpackageboxes.sty file, with only one argument holding the directive -% type. +% For topic directive, "legacy" (around 2016-2017) had no interface for +% colours, so some internals could be changed with no breakage during 5.x up +% to 6.2.0. For example topic (shadowbox) could be unified with admonitions +% (sphinxheavybox), and the "setup" macros could all be moved into a single +% one in the sphinxpackageboxes.sty file, with only one argument holding the +% directive type. % -% It was then needed only for sphinxlatexliterals.sty to let its +% It was then needed only by sphinxlatexliterals.sty to let its emitted % \spx@verb@boxes@fcolorbox@setup incorporate some extra adjustment. % -% We associate a boolean to each color, so that the box code can -% decide to insert a \color command or consider it is not needed. +% 7.4.0 removes usages of booleans relative to usage of a colour for +% background or border which were there to optimize the boxing code from +% sphinxpackageboxes.sty when colours where not needed. These were internal +% macros so their removal should not be considered breaking. +% We keep the infrastructure for "shadowcolor" and "textcolor" because the +% defaults for them remain not to have specific colour. +% +% 7.4.0 adds keys for admonition titles: for background and foreground colors, +% and for icons (whose defaults are picked from Free Fontawesome 5). \def\spx@tempa#1{% \expandafter\spx@tempb \csname if#1withshadowcolor\expandafter\endcsname - \csname if#1withbordercolor\expandafter\endcsname - \csname if#1withbackgroundcolor\expandafter\endcsname \csname if#1withtextcolor\endcsname }% -\def\spx@tempb#1#2#3#4{\newif#1\newif#2\newif#3\newif#4}% +\def\spx@tempb#1#2{\newif#1\newif#2}% % macro prefix \spx@tempa{spx@pre@} \spx@tempa{spx@topic@} @@ -602,6 +642,8 @@ will be set to white}% \spx@tempa{spx@hint@} \spx@tempa{spx@important@} \spx@tempa{spx@tip@} +\spx@tempa{spx@seealso@} +\spx@tempa{spx@todo@} \spx@tempa{spx@warning@} \spx@tempa{spx@caution@} \spx@tempa{spx@attention@} @@ -611,29 +653,36 @@ will be set to white}% % \def\spx@tempa#1{% #1 = macro prefix \expandafter\spx@tempb - \csname #1withbordercolortrue\expandafter\endcsname - \csname #1withbackgroundcolortrue\expandafter\endcsname \csname #1withshadowcolortrue\expandafter\endcsname - \csname #1withtextcolortrue\endcsname + \csname #1withtextcolortrue\expandafter\endcsname + \csname #1TeXextras\endcsname } -\def\spx@tempb#1#2#3#4#5#6{% #5 = option prefix, #6 = color name prefix - \define@key{sphinx}{#5border-TeXcolor}% - {#1\spx@defineorletcolor{#6BorderColor}##1\relax}% - \define@key{sphinx}{#5background-TeXcolor}% - {#2\spx@defineorletcolor{#6BgColor}##1\relax}% - \define@key{sphinx}{#5box-shadow-TeXcolor}% - {#3\spx@defineorletcolor{#6ShadowColor}##1\relax}% - \define@key{sphinx}{#5TeXcolor}% - {#4\spx@defineorletcolor{#6TextColor}##1\relax}% +% 7.4.0 adds options for a title. They have an action only for admonitions, +% seealso and todo directives. +\def\spx@tempb#1#2#3#4#5{% #4 = option prefix, #5 = color name prefix + \define@key{sphinx}{#4border-TeXcolor}% + {\spx@defineorletcolor{#5BorderColor}##1\relax}% + \define@key{sphinx}{#4background-TeXcolor}% + {\spx@defineorletcolor{#5BgColor}##1\relax}% + \define@key{sphinx}{#4title-background-TeXcolor}% + {\spx@defineorletcolor{#5TtlBgColor}##1\relax}% + \define@key{sphinx}{#4title-foreground-TeXcolor}% + {\spx@defineorletcolor{#5TtlFgColor}##1\relax}% + \define@key{sphinx}{#4title-icon}% + {\@namedef{#5TtlIcon}{##1}}% + \define@key{sphinx}{#4box-shadow-TeXcolor}% + {#1\spx@defineorletcolor{#5ShadowColor}##1\relax}% + \define@key{sphinx}{#4TeXcolor}% + {#2\spx@defineorletcolor{#5TextColor}##1\relax}% + \define@key{sphinx}{#4TeXextras}% + {\def#3{##1}}% } % macro prefix option prefix color name prefix \spx@tempa{spx@pre@} {pre_} {Verbatim} % (memo: internal VerbatimShadowColor was formerly sphinxVerbatimShadowColor) % internal legacy color name is VerbatimColor not VerbatimBgColor, so redefine: \define@key{sphinx}{pre_background-TeXcolor}% - {\spx@pre@withbackgroundcolortrue\spx@defineorletcolor{VerbatimColor}#1\relax}% - \spx@pre@withbordercolortrue % 6.0.0 VerbatimBorderColor {RGB}{32,32,32} - \spx@pre@withbackgroundcolortrue % 6.0.0 VerbatimColor {gray}{0.95} + {\spx@defineorletcolor{VerbatimColor}#1\relax}% % Keep legacy option names working \expandafter\let\expandafter\KV@sphinx@VerbatimBorderColor \csname KV@sphinx@pre_border-TeXcolor\endcsname @@ -646,6 +695,8 @@ will be set to white}% \spx@tempa{spx@hint@} {div.hint_} {sphinxhint} \spx@tempa{spx@important@}{div.important_} {sphinximportant} \spx@tempa{spx@tip@} {div.tip_} {sphinxtip} +\spx@tempa{spx@seealso@} {div.seealso_} {sphinxseealso} +\spx@tempa{spx@todo@} {div.todo_} {sphinxtodo} \spx@tempa{spx@warning@} {div.warning_} {sphinxwarning} \spx@tempa{spx@caution@} {div.caution_} {sphinxcaution} \spx@tempa{spx@attention@}{div.attention_} {sphinxattention} @@ -666,11 +717,12 @@ will be set to white}% \spx@tempa{div.error_} {error} % Keep legacy sphinxsetup BorderColor for =note, hint, ... - % which will not trigger sphinxheavybox - % Add "legacy" hintTextColor etc... that will not trigger sphinxheavybox + % Add "legacy" names BgColor (added at 7.4.0) and TextColor \def\spx@tempa#1#2{% #1 = CSS like option prefix, #2 = legacy option prefix \expandafter\let\csname KV@sphinx@#2BorderColor\expandafter\endcsname \csname KV@sphinx@#1border-TeXcolor\endcsname + \expandafter\let\csname KV@sphinx@#2BgColor\expandafter\endcsname + \csname KV@sphinx@#1background-TeXcolor\endcsname \expandafter\let\csname KV@sphinx@#2TextColor\expandafter\endcsname \csname KV@sphinx@#1TeXcolor\endcsname } @@ -679,28 +731,7 @@ will be set to white}% \spx@tempa{div.important_} {important} \spx@tempa{div.tip_} {tip} -% The TeXextras key -% -\def\spx@tempa#1{% #1 = macro prefix - \expandafter\spx@tempb\csname #1TeXextras\endcsname -} -\def\spx@tempb#1#2{% #2 = option prefix - \define@key{sphinx}{#2TeXextras}{\def#1{##1}}% -} -% macro prefix option prefix -\spx@tempa{spx@pre@} {pre_} -\spx@tempa{spx@topic@} {div.topic_} -\spx@tempa{spx@note@} {div.note_} -\spx@tempa{spx@hint@} {div.hint_} -\spx@tempa{spx@important@}{div.important_} -\spx@tempa{spx@tip@} {div.tip_} -\spx@tempa{spx@warning@} {div.warning_} -\spx@tempa{spx@caution@} {div.caution_} -\spx@tempa{spx@attention@}{div.attention_} -\spx@tempa{spx@danger@} {div.danger_} -\spx@tempa{spx@error@} {div.error_} -\spx@tempa{spx@box@} {box_} - % Add "legacy" hintTeXextras etc... that will not trigger sphinxheavybox + % Add "legacy" hintTeXextras etc... \def\spx@tempa#1#2{% #1 = CSS like option prefix, #2 = legacy option prefix \expandafter\let\csname KV@sphinx@#2TeXextras\expandafter\endcsname \csname KV@sphinx@#1TeXextras\endcsname @@ -710,64 +741,147 @@ will be set to white}% \spx@tempa{div.important_} {important} \spx@tempa{div.tip_} {tip} -% For note type admonitions, redefine all CSS-like named options to trigger -% the "heavybox" path. + % At 7.4.0, let topic/contents boxes acquire background and border colours + % and give the shadow some colour other than black + \setkeys{sphinx}{div.topic_border-TeXcolor=sphinx-admonition-bordercolor, + div.topic_background-TeXcolor=sphinx-admonition-bgcolor, + div.topic_box-shadow-TeXcolor={RGB}{108,108,108}, + } + + +% 7.4.0 lets all types of admonitions style especially their titlss. +% The Sphinx default colours for admonition titles are copied from PR #12486 +% which modified sphinx13.css (see also earlier #12439) +% The actual code using the colours and icons whose defaults are set here +% is to be found in sphinxlatexadmonitions.sty. +% +% MEMO: unfortunately xcolor does NOT implement HSL but only HSB! +% So the sphinx13.css colours specified via hsl() got converted to RGB here +\definecolor{sphinx-admonition-title-bgcolor}{RGB}{229,229,229} % hsl(0, 0%, 90%); +\definecolor{sphinx-admonition-title-fgcolor}{RGB}{127,127,127} % hsl(0, 0%, 50%); +\definecolor{sphinx-warning-title-bgcolor} {RGB}{248,228,210} % hsl(28.5, 74%, 90%); +\definecolor{sphinx-warning-title-fgcolor} {RGB}{221,122,33} % hsl(28.5, 74%, 50%); +\definecolor{sphinx-note-title-bgcolor} {RGB}{208,222,250} % hsl(219.5, 84%, 90%); +\definecolor{sphinx-note-title-fgcolor} {RGB}{20,93,234} % hsl(219.5, 84%, 50%); +\definecolor{sphinx-success-title-bgcolor} {RGB}{220,239,230} % hsl(150, 36.7%, 90%); +\definecolor{sphinx-success-title-fgcolor} {RGB}{81,174,128} % hsl(150, 36.7%, 50%); +\definecolor{sphinx-error-title-bgcolor} {RGB}{238,220,220} % hsl(0, 37%, 90%); +\definecolor{sphinx-error-title-fgcolor} {RGB}{174,80,80} % hsl(0, 37%, 50%); +\definecolor{sphinx-todo-title-bgcolor} {RGB}{226,204,254} % hsl(266.8, 100%, 90%); +\definecolor{sphinx-todo-title-fgcolor} {RGB}{113,0,255} % hsl(266.8, 100%, 50%); + +% Now use the above colours as default settings, following the choices +% done in sphinx13.css +\setkeys{sphinx}{ + div.note_title-background-TeXcolor=sphinx-note-title-bgcolor, + div.note_title-foreground-TeXcolor=sphinx-note-title-fgcolor, +% + div.hint_title-background-TeXcolor=sphinx-success-title-bgcolor, + div.hint_title-foreground-TeXcolor=sphinx-success-title-fgcolor, + div.tip_title-background-TeXcolor=sphinx-success-title-bgcolor, + div.tip_title-foreground-TeXcolor=sphinx-success-title-fgcolor, + div.seealso_title-background-TeXcolor=sphinx-success-title-bgcolor, + div.seealso_title-foreground-TeXcolor=sphinx-success-title-fgcolor, + div.todo_title-background-TeXcolor=sphinx-todo-title-bgcolor, + div.todo_title-foreground-TeXcolor=sphinx-todo-title-fgcolor, +% + div.important_title-background-TeXcolor=sphinx-warning-title-bgcolor, + div.important_title-foreground-TeXcolor=sphinx-warning-title-fgcolor, + div.caution_title-background-TeXcolor=sphinx-warning-title-bgcolor, + div.caution_title-foreground-TeXcolor=sphinx-warning-title-fgcolor, + div.warning_title-background-TeXcolor=sphinx-warning-title-bgcolor, + div.warning_title-foreground-TeXcolor=sphinx-warning-title-fgcolor, % -% MEMO: the noteBorderColor and noteborder legacy options have already been -% re-created and they do not trigger the "heavybox" as their meaning will not -% be modified in the loop below contrarily to their CSS counterparts -% div.note_border-TeXcolor and div.note_border-width, and to the noteBgColor -% etc... which are handled below. + div.attention_title-background-TeXcolor=sphinx-error-title-bgcolor, + div.attention_title-foreground-TeXcolor=sphinx-error-title-fgcolor, + div.danger_title-background-TeXcolor=sphinx-error-title-bgcolor, + div.danger_title-foreground-TeXcolor=sphinx-error-title-fgcolor, + div.error_title-background-TeXcolor=sphinx-error-title-bgcolor, + div.error_title-foreground-TeXcolor=sphinx-error-title-fgcolor, % -% This goes via rather hardcore TeX here. -\def\spx@tempa#1{\if\relax#1\expandafter\@gobble +% TODO: implement todo (sic) +% +} + +% 7.4.0 Support for icons in admonition titles +% We try to +% - get Sphinx PDF builds to process fine in absence of fontawesome5 +% - use fontawesome5 if present, but not if user prefers another package +% - provide an interface for using other LaTeX code for icons +% - provide an interface for using some other package than fontawesome5 +% Indeed we can't load fontawesome5 unconditionally even if available, +% as it proves incompatible with fontawesome package. +% We thus must delay its loading. +\IfFileExists{fontawesome5.sty}{% + \DeclareStringOption[fontawesome5]{iconpackage}% +}% +{% + \IfFileExists{fontawesome.sty} + {\DeclareStringOption[fontawesome]{iconpackage}} + {\DeclareStringOption[none]{iconpackage}}% +}% +\newcommand\spx@faIcon[3][]{}% +% The hacky definition of \spx@faIcon above is to let it by default swallow +% the icon macro and the \sphinxtitlerowaftericonspacecmd (see +% \sphinxdotitlerowwithicon in sphinxlatexadmonitions.sty) which inserts +% a space between it and title. See how \spx@faIcon is used below. +% +% If user sets a title-icon key to some LaTeX code of their own, of course +% \spx@faIcon is not executed and the inserted space will thus be there, as +% expected. +% +\def\spxstring@fontawesome{fontawesome} +\def\spxstring@fontawesomev{fontawesome5} +\AtBeginDocument{% + \ifx\spx@opt@iconpackage\spxstring@none \else - \toks@{##1}% - \expandafter\def\csname KV@sphinx@div.note_#1\expandafter\endcsname - \the\toks0\expandafter{% - \csname spx@opt@heavynotetrue\expandafter\expandafter\expandafter\endcsname - \csname KV@sphinx@div.note_#1\endcsname{##1}}% - \expandafter\def\csname KV@sphinx@div.hint_#1\expandafter\endcsname - \the\toks0\expandafter{% - \csname spx@opt@heavyhinttrue\expandafter\expandafter\expandafter\endcsname - \csname KV@sphinx@div.hint_#1\endcsname{##1}}% - \expandafter\def\csname KV@sphinx@div.important_#1\expandafter\endcsname - \the\toks0\expandafter{% - \csname spx@opt@heavyimportanttrue\expandafter\expandafter\expandafter\endcsname - \csname KV@sphinx@div.important_#1\endcsname{##1}}% - \expandafter\def\csname KV@sphinx@div.tip_#1\expandafter\endcsname - \the\toks0\expandafter{% - \csname spx@opt@heavytiptrue\expandafter\expandafter\expandafter\endcsname - \csname KV@sphinx@div.tip_#1\endcsname{##1}}% + \IfFileExists{\spx@opt@iconpackage.sty} + {\RequirePackage{\spx@opt@iconpackage}% + \ifx\spx@opt@iconpackage\spxstring@fontawesomev + \renewcommand\spx@faIcon{\faIcon}% + \else + \ifx\spx@opt@iconpackage\spxstring@fontawesome + \renewcommand\spx@faIcon[2][]{\faicon{##2}}% + % The \ifdefined's are a bit silly because we know that + % fontawesome.sty does not provide it, but perhaps + % there can be some new release of that package? + \ifdefined\faicon@lightbulb\else + \let\faicon@lightbulb\faLightbulbO + \fi + \ifdefined\faicon@radiation\else + \let\faicon@radiation\faBolt + \fi + \ifdefined\faicon@pen\else + \let\faicon@pen\faPencil + \fi + % if neither has been required, \spx@faIcon will simply swallow + % its argument (and follwing space macro) and it is up to user + % to set the keys appropriately. + \fi\fi % + }% + {% + \sphinxbuildwarning{badiconpackage}% + \PackageWarningNoLine{sphinx}{% + You have set iconpackage=\spx@opt@iconpackage\MessageBreak + But \spx@opt@iconpackage.sty is not found by LaTeX} + }% \fi - \spx@tempa } -\spx@tempa{border-width}% - {border-top-width}{border-right-width}{border-bottom-width}{border-left-width}% - {box-decoration-break}% - {padding}% - {padding-top}{padding-right}{padding-bottom}{padding-left}% - {border-radius}% - {border-top-left-radius}{border-top-right-radius}% - {border-bottom-right-radius}{border-bottom-left-radius}% - {box-shadow}% - {border-TeXcolor}{background-TeXcolor}{box-shadow-TeXcolor}{TeXcolor}% - {TeXextras}% -\relax - -% Now we add at 6.2.0 BgColor et al. options which will trigger the -% "heavybox" as they are \let to the div._background-TeXColor option -% which has already been enhanced to set the boolean for rendering via -% "heavybox". This is in contrast with legacy BorderColor, -% and with the new TeXcolor and TeXextras. - \def\spx@tempa#1#2{% #1 = CSS like option prefix, #2 = legacy style option prefix - \expandafter\let\csname KV@sphinx@#2BgColor\expandafter\endcsname - \csname KV@sphinx@#1background-TeXcolor\endcsname - } - \spx@tempa{div.note_} {note} - \spx@tempa{div.hint_} {hint} - \spx@tempa{div.important_} {important} - \spx@tempa{div.tip_} {tip} + +\setkeys{sphinx}{ +% Icon defaults. + div.note_title-icon = \spx@faIcon{info-circle}, + div.hint_title-icon = \spx@faIcon[regular]{lightbulb}, + div.tip_title-icon = \spx@faIcon[regular]{lightbulb}, + div.seealso_title-icon = \spx@faIcon{share}, + div.todo_title-icon = \spx@faIcon{pen}, + div.important_title-icon = \spx@faIcon{pause-circle}, + div.caution_title-icon = \spx@faIcon{radiation}, + div.warning_title-icon = \spx@faIcon{exclamation-triangle}, + div.attention_title-icon = \spx@faIcon{exclamation-triangle}, + div.danger_title-icon = \spx@faIcon{radiation}, + div.error_title-icon = \spx@faIcon{times-circle}, +} \newif\ifspx@opt@box@addstrut \expandafter\def\csname KV@sphinx@box_addstrut\endcsname#1{% @@ -918,20 +1032,23 @@ will be set to white}% } % Some of these defaults got already set. But we now list them all explicitly % for a complete initial configuration of reset storage. -% +% At 7.4.0, \fboxrule and \fboxsep replaced by 0.4pt and 3pt which are anyhow +% the defaults for these LaTeX dimensions. \let\spx@boxes@sphinxbox@defaults\@gobble \sphinxboxsetup{% - border-width=\fboxrule,% <-not really needed to avoid EOL space - padding=\fboxsep,% but done here out of habit - border-radius=\fboxsep,% - box-shadow=none,% -% As xcolor is perhaps not loaded we can not use background-TeXcolor=VerbatimColor -% which would not be compatible with \definecolor syntax. - border-TeXcolor={RGB}{32,32,32},% the default VerbatimBorderColor - background-TeXcolor={gray}{0.95},% the default VerbatimColor - box-shadow-TeXcolor={rgb}{0,0,0},% - TeXextras={},% - addstrut=false% (a final comma here would not hurt) + border-width=0.4pt, + padding=3pt, + border-radius=0.4pt, + box-shadow=none, +% MEMO: as xcolor is loaded, \spx@defineorletcolor has a "\colorlet" branch +% which makes this syntax acceptable and avoids duplicating here the values. + border-TeXcolor=VerbatimBorderColor, + background-TeXcolor=VerbatimColor, +% 7.4.0 modified the color of the shadow (anyhow box-shadow is set above to none +% so no shadow is drawn), to be as the new shadow colour of topic boxes. + box-shadow-TeXcolor={RGB}{108,108,108}, + TeXextras={}, + addstrut=false, }% \RequirePackage{sphinxpackageboxes} \input{sphinxlatexadmonitions.sty} diff --git a/docs/build/latex/sphinx.xdy b/docs/build/latex/sphinx.xdy index 0dcf113..8df526e 100644 --- a/docs/build/latex/sphinx.xdy +++ b/docs/build/latex/sphinx.xdy @@ -99,7 +99,7 @@ ;; file, with a blank space after \IeC ;; Details of the syntax are explained at -;; http://xindy.sourceforge.net/doc/manual-3.html +;; https://xindy.sourceforge.net/doc/manual-3.html ;; In absence of :string, "xindy uses an auto-detection mechanism to decide, ;; if the pattern is a regular expression or not". But it is not obvious to ;; guess, for example "\\_" is not detected as RE but "\\P\{\}" is, so for diff --git a/docs/build/latex/sphinxlatexadmonitions.sty b/docs/build/latex/sphinxlatexadmonitions.sty index a31ae4c..c0f6578 100644 --- a/docs/build/latex/sphinxlatexadmonitions.sty +++ b/docs/build/latex/sphinxlatexadmonitions.sty @@ -1,25 +1,51 @@ %% NOTICES AND ADMONITIONS % % change this info string if making any custom modification -\ProvidesFile{sphinxlatexadmonitions.sty}[2023/03/19 admonitions] +\ProvidesFile{sphinxlatexadmonitions.sty}[2024/07/01 v7.4.0 admonitions] % Provides support for this output mark-up from Sphinx latex writer: % -% - sphinxseealso environment added at 6.1.0 +% - sphinxseealso environment added at 6.1.0. +% +% At 7.4.0 it too now uses sphinxheavybox, and has the same associated +% sphinxsetup CSS keys as admonitions do. +% +% - sphinxtodo environment added at 7.4.0. % % - sphinxadmonition (environment) -% This is a dispatch supporting +% This is a dispatch which formerly configured +% +% - note, hint, important, tip to use sphinxlightbox (or optionally +% sphinxheavybox since 6.2.0), +% - warning, caution, attention, danger, error to use sphinxheavybox. % -% - note, hint, important, tip (via sphinxlightbox) -% (also optionally via sphinxheavybox since 6.2.0) -% - warning, caution, attention, danger, error (via sphinxheavybox) +% At 7.4.0 all admonitions use sphinxheavybox. % -% Each sphinx environment can be redefined by user. -% The defaults are customizable via various colour and dimension -% settings, cf sphinx docs (latex customization). +% - All environments sphinxnote, sphinxwarning, etc... can be redefined as +% will by user. Thay have a single parameter #1 which is the title. +% +% - The default sphinxnote, sphinxwarning, etc... use associated +% one-argument macros \sphinxstylenotetitle, \sphinxstylewarningtitle, etc +% which can be redefined. Their default is to use \sphinxdotitlerowwithicon +% to typeset the title in a coloured header row at top of the +% admonition. (new with 7.4.0) +% +% The sphinxlightbox environment is kept for backward compatiblity, for user +% custom code which used it via custom definitions done in preamble or via +% raw latex directive. +% MEMO: here is for example how sphinxnote was formerly defined: +% (where #1 is the localized string Note, followed with a colon) +% \newenvironment{sphinxnote}[1] +% {\begin{sphinxlightbox}\sphinxstrong{#1} } +% {\end{sphinxlightbox}} +% Use this if you want to revert the 7.4.0 switch to usage of sphinxheavybox. +% (the 7.4.0 redefined \sphinxstylenotetitle will not work in sphinxlightbox, +% so \sphinxstrong{#1} which was its former default is used above). + % % Requires: \RequirePackage{sphinxpackageboxes} +% 7.4.0 removes unneeded \spx@boxes@border \RequirePackage{framed}% used by sphinxheavybox % % Dependencies (they do not need to be defined at time of loading): @@ -29,25 +55,17 @@ % - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty % % - \savenotes/\spewnotes from sphinxpackagefootnote (for sphinxheavybox) -% -% - \sphinxstylenotetitle, ..., \sphinxstylewarningtitle, etc... which are used by -% default in the corresponding sphinx environments to replace at 6.2.0 -% formerly hard-coded \sphinxstrong{#1} -% Their definitions are in sphinxlatexstyletext.sty. - % Provides: (also in sphinxlatexliterals.sty) +% Only needed here by legacy (deprecated) sphinxlightbox environment. \providecommand*\sphinxvspacefixafterfrenchlists{% \ifvmode\ifdim\lastskip<\z@ \vskip\parskip\fi\else\par\fi } -% Some are quite plain -\newenvironment{sphinxseealso}[1]{\sphinxstyleseealsotitle{#1}}{} - % This \dimen register is a legacy relic from Sphinx 1.5 which is used now % only for sphinxlightbox. It is set in the sphinxadmonition environment. \newdimen\spx@notice@border - +% sphinxlightbox is now also a legacy relic, not used by Sphinx anymore \newenvironment{sphinxlightbox}{% \par \noindent{\color{spx@notice@bordercolor}% @@ -65,55 +83,28 @@ {\linewidth}{\spx@notice@border}}\hss}\allowbreak }% end of sphinxlightbox environment definition -% note/hint/important/tip notices -% -% Since 1.5 these environments are named individually to allow user to -% redefine them entirely. +% Since 1.5 these environments are named individually sphinxnote, sphinxhint, +% etc... to allow user to redefine them entirely. % -% The Sphinx definitions were done like this, prior to 6.2.0: +% The Sphinx definitions for note/hint/important/tip notices were done like +% this, prior to 6.2.0: % % \newenvironment{sphinxhint}[1] % {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}} % -% The more complex definition below will branch to sphinxheavybox if a certain -% boolean associated to the notice type is true. This boolean is set to true -% whenever a CSS-named alike options for the notice type has been used in -% sphinxsetup. The old coding as above would still work, with the new options -% being then simply ignored. A user redefinition will probably either use -% directly sphinxlightbox or sphinxheavybox or something else, with no need to -% test the boolean. -% -% 6.2.0 also adds one layer of mark-up via \sphinxnotetitle etc..., because -% the former \sphinxstrong{#1} used a too generic \sphinxstrong. But -% perhaps the #1 should be passed over to sphinx{light,heavy}box as parameter. -% Unfortunately replacing these environments with one-parameter environments -% would be potentially a breaking change. Anyway, sphinxpackageboxes.sty does not -% provide a "titled" box; the caption of code-blocks is handled by extra -% code in sphinxVerbatim. -\newenvironment{sphinxnote}[1] - {\edef\spx@env{sphinx\ifspx@opt@heavynote heavy\else light\fi box}% - \expandafter\begin\expandafter{\spx@env}\sphinxstylenotetitle{#1}} - {\expandafter\end\expandafter{\spx@env}} -\newenvironment{sphinxhint}[1] - {\edef\spx@env{sphinx\ifspx@opt@heavyhint heavy\else light\fi box}% - \expandafter\begin\expandafter{\spx@env}\sphinxstylehinttitle{#1}} - {\expandafter\end\expandafter{\spx@env}} -\newenvironment{sphinximportant}[1] - {\edef\spx@env{sphinx\ifspx@opt@heavyimportant heavy\else light\fi box}% - \expandafter\begin\expandafter{\spx@env}\sphinxstyleimportanttitle{#1}} - {\expandafter\end\expandafter{\spx@env}} -\newenvironment{sphinxtip}[1] - {\edef\spx@env{sphinx\ifspx@opt@heavytip heavy\else light\fi box}% - \expandafter\begin\expandafter{\spx@env}\sphinxstyletiptitle{#1}} - {\expandafter\end\expandafter{\spx@env}} - -% warning/caution/attention/danger/error get more distinction +% Then from 6.2.0 to 7.4.0 (exclusive) a more complex definition decided +% to use either sphinxlightbox or sphinxheavybox according to whether +% some CSS-like options had been used, for example for a background color. +% +% 6.2.0 also added one layer of mark-up via \sphinxnotetitle etc..., because +% the former \sphinxstrong{#1} used a too generic \sphinxstrong. +% +% At 7.4.0, sphinxheavybox environment is default for all types of notices +% and also for the seealso and todo directives. % % Code adapted from framed.sty's "snugshade" environment. % Nesting works (inner frames do not allow page breaks). \newenvironment{sphinxheavybox}{\par - % 6.2.0 allows to not have to distinguish here between warning type notices - % which always use sphinxheavybox or note type notices which might use it. % (MEMO: it is not a problem here if there is no sphinxShadowColor, % as it used only if set) \spx@boxes@fcolorbox@setup{\spx@noticetype}% @@ -205,16 +196,80 @@ % Example: % \renewcommand{\sphinxwarningtitle}[1]{\textbf{#1}\par\smallskip % {\color{sphinxwarningBorderColor}\hrule height1pt}\smallskip} +% +% - Since 7.4.0, all types of notices use sphinxheavybox and the default +% for \sphinxstyletitle is mapped to using \sphinxdotitlerowwithicon{} +% +% MEMO: except for the generic admonition directive (which uses "note" type) +% the argument #1 in these environments has a postfixed colon originating +% in Sphinx LaTeX writer legacy code. The +% \sphinxremovefinalcolon utility in sphinxlatexstyletext.sty can be used as +% \sphinxremovefinalcolon{#1} from inside the definitions of +% \sphinxstylenotetitle et al. commands. + +% Important: even prior to 5.1.0 it was not really possible to use directly +% sphinxheavybox if not triggered from sphinxadmonition, because some +% parameters were defined in sphinxadmonition. This meant that the +% sphinxwarning, sphinxcaution etc... environments (defined below) could not +% be used directly in a document, they had to be triggered via +% sphinxadmonition. The sole data since 5.1.0 needed by sphinxheavybox is the +% type of the notice which sphinxadmonition stores into \spx@noticetype. +% +% In order to facilitate recycling or imitation of the sphinx +% environments, 7.4.0 inserts an extra \def\spx@noticetype{} in their +% definitions, so that they can be used independently of sphinxadmonition +% dispatcher. +% +% MEMO: direct usage of these environments does not execute the div._TeXextras +% and div._TexColor code, there are only done from the sphinxadmonition wrapper. +\newenvironment{sphinxnote}[1] + {\def\spx@noticetype{note}\begin{sphinxheavybox}\sphinxstylenotetitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxhint}[1] + {\def\spx@noticetype{hint}\begin{sphinxheavybox}\sphinxstylehinttitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxtip}[1] + {\def\spx@noticetype{tip}\begin{sphinxheavybox}\sphinxstyletiptitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinximportant}[1] + {\def\spx@noticetype{important}\begin{sphinxheavybox}\sphinxstyleimportanttitle{#1}} + {\end{sphinxheavybox}} \newenvironment{sphinxwarning}[1] - {\begin{sphinxheavybox}\sphinxstylewarningtitle{#1}}{\end{sphinxheavybox}} + {\def\spx@noticetype{warning}\begin{sphinxheavybox}\sphinxstylewarningtitle{#1}} + {\end{sphinxheavybox}} \newenvironment{sphinxcaution}[1] - {\begin{sphinxheavybox}\sphinxstylecautiontitle{#1}}{\end{sphinxheavybox}} + {\def\spx@noticetype{caution}\begin{sphinxheavybox}\sphinxstylecautiontitle{#1}} + {\end{sphinxheavybox}} \newenvironment{sphinxattention}[1] - {\begin{sphinxheavybox}\sphinxstyleattentiontitle{#1}}{\end{sphinxheavybox}} + {\def\spx@noticetype{attention}\begin{sphinxheavybox}\sphinxstyleattentiontitle{#1}} + {\end{sphinxheavybox}} \newenvironment{sphinxdanger}[1] - {\begin{sphinxheavybox}\sphinxstyledangertitle{#1}}{\end{sphinxheavybox}} + {\def\spx@noticetype{danger}\begin{sphinxheavybox}\sphinxstyledangertitle{#1}} + {\end{sphinxheavybox}} \newenvironment{sphinxerror}[1] - {\begin{sphinxheavybox}\sphinxstyleerrortitle{#1}}{\end{sphinxheavybox}} + {\def\spx@noticetype{error}\begin{sphinxheavybox}\sphinxstyleerrortitle{#1}} + {\end{sphinxheavybox}} +% The "see also" was quite plain until 7.4.0 as it simply did +% \newenvironment{sphinxseealso}[1]{\sphinxstyleseealsotitle{#1}}{} +% Here we need to manually insert execution of div.seealso_TeX{color,extras} values +\newenvironment{sphinxseealso}[1] + {\def\spx@noticetype{seealso}% + \begin{sphinxheavybox}\sphinxstyleseealsotitle{#1}% + \ifspx@seealso@withtextcolor\color{sphinxseealsoTextColor}\fi + \spx@seealso@TeXextras + } + {\end{sphinxheavybox}} +% There was no sphinxtodo environment until 7.4.0 because sphinx.ext.todo +% generated \begin{sphinxadmonition}{note}{Todo:} mark-up. +\newcounter{sphinxtodo}% to provide targets from todolist directive output +\newenvironment{sphinxtodo}[1] + {\refstepcounter{sphinxtodo}\def\spx@noticetype{todo}% + \begin{sphinxheavybox}\sphinxstyletodotitle{#1}% + \ifspx@todo@withtextcolor\color{sphinxtodoTextColor}\fi + \spx@todo@TeXextras + } + {\end{sphinxheavybox}} + % the main dispatch for all types of notices \newenvironment{sphinxadmonition}[2]{% #1=type, #2=heading @@ -227,16 +282,104 @@ % the more bulky "sphinx\spx@noticetype BgColor". \sphinxcolorlet{spx@notice@bordercolor}{sphinx#1BorderColor}% \sphinxcolorlet{spx@notice@bgcolor}{sphinx#1BgColor}% - \spx@notice@border \dimexpr\csname spx@#1@border\endcsname\relax + % At 7.4.0 there are no \spx@@boder macros anymore only top, left, + % bottom, right. For this legacy \spx@notice@border only needed by + % sphinxlightbox (which is not used by own Sphinx environments anymore) + % we thus use here @top + \spx@notice@border \dimexpr\csname spx@#1@border@top\endcsname\relax % trigger the sphinx environment, #2=heading is passed as argument \begin{sphinx#1}{#2}% + % MEMO: the heading #2 will be typeset before the next lines are executed % 6.2.0 support of div._TeX{color,extras} options \csname ifspx@\spx@noticetype @withtextcolor\endcsname \color{sphinx\spx@noticetype TextColor}% \fi + % Other code to be executed at start of contents (after title) \csname spx@\spx@noticetype @TeXextras\endcsname } - % workaround some LaTeX "feature" of \end command (can't use "sphinx#1" here) + % workaround some LaTeX "feature" of \end command (i.e. can't use "sphinx#1" here) {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp} +\newcommand\sphinxtitlerowtoppadding{5pt} +\newcommand\sphinxtitlerowbottompadding{3pt} +\newcommand\sphinxtitlerowaftericonspacecmd{\hskip0.5em\relax} +\newcommand\sphinxdotitlerowwithicon[2]{% #1=type, #2=heading (without final colon) + \begingroup + \kern-\spx@boxes@padding@top + \parskip\z@skip % the \parskip business is a workaround to a vertical + % glue issue showing in LaTeX earlier than 2023-06-01 + \noindent + \kern-\spx@boxes@padding@left % must have been configured by a prior + % \spx@boxes@fcolorbox@setup{} + % inherit settings from the enclosing box and modify what is needed + \spx@boxes@border@top =\z@ + \spx@boxes@border@right =\z@ + \spx@boxes@border@bottom =\z@ + \spx@boxes@border@left =\z@ + \spx@boxes@radius@bottomright@x=\z@ + \spx@boxes@radius@bottomright@y=\z@ + \spx@boxes@radius@bottomleft@x=\z@ + \spx@boxes@radius@bottomleft@x=\z@ + \spx@boxes@padding@top =\sphinxtitlerowtoppadding\relax + \spx@boxes@padding@bottom=\sphinxtitlerowbottompadding\relax + \spx@boxes@withshadowfalse + \sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1TtlBgColor}% + \spx@boxes@fcolorbox{% + \makebox[\linewidth][l]{% + \textcolor{sphinx#1TtlFgColor}{% + \@nameuse{sphinx#1TtlIcon}% + % This macro is located here and not after the closing brace + % for reasons of fall-back \spx@faIcon definition in sphinx.sty + % in case fontawesome5 package not found. + \sphinxtitlerowaftericonspacecmd + }% + \sphinxstrong{#2}% + \strut}% + }% + \kern-\spx@boxes@padding@right + \par + \endgroup + \vskip-\parskip + \kern\spx@boxes@padding@top +} + +% #1 holds the localized name of the notice, postfixed with a colon. +% \sphinxremovefinalcolon{#1} will typeset #1 without the colon. +% Legacy definitions (done in sphinxlatexstyletext.sty) were all using +% a boring plain \sphinxstrong{#1}, now we use a coloured title row. +\newcommand\sphinxstylenotetitle [1]{\sphinxdotitlerowwithicon{note}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstylehinttitle [1]{\sphinxdotitlerowwithicon{hint}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleimportanttitle[1]{\sphinxdotitlerowwithicon{important}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyletiptitle [1]{\sphinxdotitlerowwithicon{tip}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstylewarningtitle [1]{\sphinxdotitlerowwithicon{warning}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstylecautiontitle [1]{\sphinxdotitlerowwithicon{caution}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleattentiontitle[1]{\sphinxdotitlerowwithicon{attention}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyledangertitle [1]{\sphinxdotitlerowwithicon{danger}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleerrortitle [1]{\sphinxdotitlerowwithicon{error}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleseealsotitle [1]{\sphinxdotitlerowwithicon{seealso}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyletodotitle [1]{\sphinxdotitlerowwithicon{todo}{\sphinxremovefinalcolon{#1}}} +% +% A utility to remove a final colon. Removing last token is not easy in +% LaTeX, and there are additional complications: +% - some languages will make the : "active" in document body, +% - the generic admonition ends up using "note", so for \sphinxnotetitle to +% use it safely, the utility has to allow an input not having any final colon. +% - a bit far-fetched but maybe there is more than one colon inside the input +% (possible from a generic admonition title). +% Hence the scary code. +\newcommand\sphinxremovefinalcolon[1]{% #1 is the "active" : TeX token +% Prior to 7.4.0 this was defined with \protected\def but we do not +% see what usefulness this could have. +\renewcommand\sphinxremovefinalcolon[1]{% + % complications due to : possibly "active" + \begingroup\ifnum\catcode`:=\active + \def\x####1#1\relax{####1}% + \else\def\x####1:\relax{####1}\fi + \expandafter\endgroup\x##1\relax + % trick to let \x work also if input ##1 has no ending colon + \@gobblefour#1\relax:\relax\relax\relax + }% +}% end of wrapper to inject active : +\begingroup\catcode`:\active\expandafter\endgroup\sphinxremovefinalcolon: + \endinput diff --git a/docs/build/latex/sphinxlatexliterals.sty b/docs/build/latex/sphinxlatexliterals.sty index 3a73a76..8acea9f 100644 --- a/docs/build/latex/sphinxlatexliterals.sty +++ b/docs/build/latex/sphinxlatexliterals.sty @@ -1,7 +1,7 @@ %% LITERAL BLOCKS % % change this info string if making any custom modification -\ProvidesFile{sphinxlatexliterals.sty}[2023/04/01 code-blocks and parsed literals] +\ProvidesFile{sphinxlatexliterals.sty}[2024/07/01 v7.4.0 code-blocks and parsed literals] % Provides support for this output mark-up from Sphinx latex writer: % @@ -34,6 +34,7 @@ % - needspace % - sphinxpackageboxes \RequirePackage{sphinxpackageboxes} +% 7.4.0 removes unneeded usage of \spx@boxes@border % also in sphinxlatexadmonitions.sty: % This is a workaround to a "feature" of French lists, when literal block @@ -224,7 +225,6 @@ \spx@boxes@border@right\z@ \spx@boxes@border@bottom\z@ \spx@boxes@border@left\z@ - \spx@boxes@border\z@ % MEMO: rounded corners still make sense in presence of a background % color, so we do not force the fcolorbox@rectangle here \fi @@ -670,25 +670,18 @@ \def\sphinxVerbatim@Before {\sphinxVerbatim@Title\nointerlineskip \kern\dimexpr-\dp\strutbox+\sphinxbelowcaptionspace - % if no frame (code-blocks inside table cells), remove - % the top padding (better visually) - \ifspx@opt@verbatimwithframe\else - % but we must now check if there is a background color - % MEMO: "fcolorbox@setup" will have been done by time of use - \ifspx@boxes@withbackgroundcolor\else-\spx@boxes@padding@top\fi - \fi + % MEMO: prior to 7.4.0 a test was done for presence or + % not of a frame and if not top padding was removed if + % no background color. A background color is now always + % assumed, so this got removed. % caption package adds \abovecaptionskip vspace, remove it - \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax}% + \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax}% \else \vskip\sphinxverbatimsmallskipamount \def\sphinxVerbatim@After {\nointerlineskip\kern\dimexpr\dp\strutbox - \ifspx@opt@verbatimwithframe\else - % but we must now check if there is a background color - % MEMO: "fcolorbox@setup" will have been done by time of use - \ifspx@boxes@withbackgroundcolor\else-\spx@boxes@padding@bottom\fi - \fi - \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax + % MEMO: 7.4.0 removes here too an optional removal of bottom padding + \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax \sphinxVerbatim@Title}% \fi \def\@captype{literalblock}% diff --git a/docs/build/latex/sphinxlatexstyletext.sty b/docs/build/latex/sphinxlatexstyletext.sty index d900090..1655fbc 100644 --- a/docs/build/latex/sphinxlatexstyletext.sty +++ b/docs/build/latex/sphinxlatexstyletext.sty @@ -1,45 +1,11 @@ %% TEXT STYLING % % change this info string if making any custom modification -\ProvidesFile{sphinxlatexstyletext.sty}[2023/07/23 text styling] +\ProvidesFile{sphinxlatexstyletext.sty}[2024/07/01 v7.4.0 text styling] -% Basically everything here consists of macros which are part of the latex -% markup produced by the Sphinx latex writer - -% But those arise rather from the default definitions of the respective -% latex environments done in sphinxlatexadmonitions.sty -\def\sphinxstylenotetitle #1{\sphinxstrong{#1} } -\let\sphinxstylehinttitle \sphinxstylenotetitle % #1 holds the localized notice name -\let\sphinxstyleimportanttitle\sphinxstylenotetitle % followed by a colon -\let\sphinxstyletiptitle \sphinxstylenotetitle -\let\sphinxstylewarningtitle \sphinxstylenotetitle -\let\sphinxstylecautiontitle \sphinxstylenotetitle -\let\sphinxstyleattentiontitle\sphinxstylenotetitle -\let\sphinxstyledangertitle \sphinxstylenotetitle -\let\sphinxstyleerrortitle \sphinxstylenotetitle -\def\sphinxstyleseealsotitle#1{\sphinxstrong{#1}\par\nopagebreak} -% -% A utility to remove a final colon. Removing last token is not easy in -% LaTeX, and there are additional complications: -% - some languages will make the : "active" in document body, -% - the generic admonition ends up using "note", so for \sphinxnotetitle to -% use it safely, the utility has to allow an input not having any final colon. -% - a bit far-fetched but maybe there is more than one colon inside the input -% (possible from a generic admonition title). -% Hence the scary code. -\def\sphinxremovefinalcolon#1{% #1 is the "active" : TeX token -\protected\def\sphinxremovefinalcolon ##1{% - % complications due to : possibly "active" - \begingroup\ifnum\catcode`:=\active - \def\x####1#1\relax{####1}% - \else\def\x####1:\relax{####1}\fi - \expandafter\endgroup\x##1\relax - % trick to let \x work also if input ##1 has no ending colon - \@gobblefour#1\relax:\relax\relax\relax - }% -}% end of wrapper to inject active : -\begingroup\catcode`:\active\expandafter\endgroup\sphinxremovefinalcolon: -% See doc/latex.rst for an example. +% 7.4.0 has moved all that is related to admonitions to sphinxlatexadmonitions.sty +% Most everything left here consists of macros which are part of the latex markup +% produced by the Sphinx LaTeX writer. % Some custom font markup commands. \protected\def\sphinxstrong#1{\textbf{#1}} diff --git a/docs/build/latex/sphinxlatextables.sty b/docs/build/latex/sphinxlatextables.sty index 9e44532..54b42cb 100644 --- a/docs/build/latex/sphinxlatextables.sty +++ b/docs/build/latex/sphinxlatextables.sty @@ -1,7 +1,7 @@ %% TABLES (WITH SUPPORT FOR MERGED CELLS OF GENERAL CONTENTS) % % change this info string if making any custom modification -\ProvidesFile{sphinxlatextables.sty}[2022/08/15 tables]% +\ProvidesFile{sphinxlatextables.sty}[2024/07/01 v7.4.0 tables]% % Provides support for this output mark-up from Sphinx latex writer % and table templates: @@ -42,6 +42,11 @@ % - \sphinxthistablewithnocolorrowsstyle % - \sphinxthistablewithvlinesstyle % - \sphinxthistablewithnovlinesstyle +% +% Also provides user command (see docs) +% - \sphixncolorblend +% (Sphinx 7.4.0 now requires xcolor, so \sphinxcolorblend does not check +% its availability anymore) % % Executes \RequirePackage for: % @@ -103,6 +108,7 @@ \vbox{}% get correct baseline from above \LTpre\z@skip\LTpost\z@skip % set to zero longtable's own skips \edef\sphinxbaselineskip{\dimexpr\the\dimexpr\baselineskip\relax\relax}% + \spx@inframedtrue % message to sphinxheavybox }% % Compatibility with caption package \def\sphinxthelongtablecaptionisattop{% @@ -116,7 +122,9 @@ \def\sphinxatlongtableend{\@nobreakfalse % latex3/latex2e#173 \prevdepth\z@\vskip\sphinxtablepost\relax}% % B. Table with tabular or tabulary -\def\sphinxattablestart{\par\vskip\dimexpr\sphinxtablepre\relax}% +\def\sphinxattablestart{\par\vskip\dimexpr\sphinxtablepre\relax + \spx@inframedtrue % message to sphinxheavybox + }% \let\sphinxattableend\sphinxatlongtableend % This is used by tabular and tabulary templates \newcommand*\sphinxcapstartof[1]{% @@ -513,19 +521,6 @@ \fi } \def\sphinxcolorblend#1{\gdef\spx@colorblendparam{{#1}}\spx@table@hackCT@colorblend} -% Either xcolor.sty exists on user system and has been loaded by sphinx.sty, -% or it does not exist, so we can use \@ifpackageloaded without delaying. -\@ifpackageloaded{xcolor}% - {}% - {\def\sphinxcolorblend#1{% -\PackageWarning{sphinx}{This table uses \string\sphinxcolorblend\space - but xcolor is not in\MessageBreak - the TeX/LaTeX installation, the command will be\MessageBreak - ignored in this and the next tables}% - \global\let\sphinxcolorblend\@gobble - \sphinxbuildwarning{colorblend}% - }% - } %%%%%%%%%%%%%%%%%% @@ -564,7 +559,7 @@ % 99% or use case. Or perhaps some trick with storing in a \vbox and recovering % via some \vsplit but this becomes complicated... perhaps in future. % -% In passing we obtain baseline alignements across rows (only if +% In passing we obtain baseline alignments across rows (only if % \arraystretch is 1, as LaTeX's does not obey \arraystretch in "p" % multi-line contents, only first and last line...) % diff --git a/docs/build/latex/sphinxpackageboxes.sty b/docs/build/latex/sphinxpackageboxes.sty index b0d3707..2345051 100644 --- a/docs/build/latex/sphinxpackageboxes.sty +++ b/docs/build/latex/sphinxpackageboxes.sty @@ -1,7 +1,12 @@ %% COLOURED BOXES % % change this info string if making any custom modification -\ProvidesPackage{sphinxpackageboxes}[2023/03/19 v6.2.0 advanced colored boxes] +\ProvidesPackage{sphinxpackageboxes}[2024/07/01 v7.4.0 advanced colored boxes] +% 7.4.0 removes usage of some booleans "...withbackgroundcolor" and +% "...withbordercolor" as well as \spx@boxes@border dimen which was +% actually really needed nowhere. This was done in sync with changes in +% sphinx.sty, sphinxlatexadmonitions.sty and sphinxlatexliterals.sty. +% % Optionally executes \RequirePackage for: % % - pict2e. Ideally we would like to use the v0.4a 2020/08/16 release of this @@ -78,15 +83,13 @@ %%%%%%%%%%%%%%%% % Internal registers, conditionals, colors to be configured by each caller % via a preliminary "setup" call -% \newif\ifspx@boxes@withshadow \newif\ifspx@boxes@insetshadow -\newif\ifspx@boxes@withbackgroundcolor +%%% \newif\ifspx@boxes@withbackgroundcolor % removed at 7.4.0 \newif\ifspx@boxes@withshadowcolor -\newif\ifspx@boxes@withbordercolor +%%% \newif\ifspx@boxes@withbordercolor % removed at 7.4.0 \newif\ifspx@boxes@shadowinbbox % -\newdimen\spx@boxes@border \newdimen\spx@boxes@border@top \newdimen\spx@boxes@border@right \newdimen\spx@boxes@border@bottom @@ -150,7 +153,6 @@ \spx@boxes@border@right \dimexpr\@nameuse{spx@#1@border@right}\relax \spx@boxes@border@bottom\dimexpr\@nameuse{spx@#1@border@bottom}\relax \spx@boxes@border@left \dimexpr\@nameuse{spx@#1@border@left}\relax - \spx@boxes@border \dimexpr\@nameuse{spx@#1@border}\relax % \spx@boxes@padding@top \dimexpr\@nameuse{spx@#1@padding@top}\relax \spx@boxes@padding@right \dimexpr\@nameuse{spx@#1@padding@right}\relax @@ -200,19 +202,9 @@ \spx@boxes@insetshadowfalse \fi % - \@nameuse{ifspx@#1@withbordercolor}% - \spx@boxes@withbordercolortrue \sphinxcolorlet{spx@boxes@bordercolor}{sphinx#1BorderColor}% - \else - \spx@boxes@withbordercolorfalse - \fi % - \@nameuse{ifspx@#1@withbackgroundcolor}% - \spx@boxes@withbackgroundcolortrue \sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1BgColor}% - \else - \spx@boxes@withbackgroundcolorfalse - \fi % \@nameuse{ifspx@#1@withshadowcolor}% \spx@boxes@withshadowcolortrue @@ -447,14 +439,12 @@ \fi % BACKGROUND % draw background and move back to reference point - \ifspx@boxes@withbackgroundcolor {\color{spx@boxes@backgroundcolor}% \vrule\@height\ht\spx@tempboxa \@depth\dp\spx@tempboxa \@width\wd\spx@tempboxa \kern-\wd\spx@tempboxa }% - \fi % BOX SHADOW % draw shadow and move back to reference point \ifspx@boxes@withshadow @@ -494,13 +484,8 @@ }% end of \vbox \fi % end of shadow drawing, and we are back to horizontal reference point % BOX BORDER - \vbox{\ifspx@boxes@withbordercolor - \color{spx@boxes@bordercolor}% - \else - % 6.2.0: guard against a \color command in contents whose effect - % could leak to border at a pagebreak - \normalcolor - \fi + % 7.4.0 requires a set border color + \vbox{\color{spx@boxes@bordercolor}% \hrule\@height\spx@boxes@border@top \kern-\spx@boxes@border@top \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa @@ -540,14 +525,13 @@ \def\spx@boxes@fcolorbox@insetshadow{% % BACKGROUND % draw background and move back to reference point - \ifspx@boxes@withbackgroundcolor + % 7.4.0 always assumes a background color {\color{spx@boxes@backgroundcolor}% \vrule\@height\ht\spx@tempboxa \@depth\dp\spx@tempboxa \@width\wd\spx@tempboxa \kern-\wd\spx@tempboxa }% - \fi % BOX SHADOW % draw shadow and move back to reference point \ifspx@boxes@withshadow @@ -589,13 +573,8 @@ }% end of \hbox, attention its depth is only |yoffset| if yoffset<0 \fi % end of inset shadow drawing, and we are back to horizontal reference point % BOX BORDER - \vbox{\ifspx@boxes@withbordercolor - \color{spx@boxes@bordercolor}% - \else - % 6.2.0: guard against a \color command in contents whose effect - % could leak to border at a pagebreak - \normalcolor - \fi + % 7.4.0 requires a set border color + \vbox{\color{spx@boxes@bordercolor}% \hrule\@height\spx@boxes@border@top \kern-\spx@boxes@border@top \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa @@ -807,17 +786,11 @@ \fi \spx@boxes@border@defpath% must be redone after each \fillpath! (even if % was in a \put) - \ifspx@boxes@withbordercolor + % 7.4.0 requires a set border color \color{spx@boxes@bordercolor}% - \else - \normalcolor - \fi \fillpath - \ifspx@boxes@withbackgroundcolor + % and backgroundcolor command \color{spx@boxes@backgroundcolor}% - \else - \color{white}% - \fi \edef\spx@width{\number\dimexpr\spx@width-\spx@boxes@border@left -\spx@boxes@border@right sp}% \edef\spx@height{\number\dimexpr\spx@height-\spx@boxes@border@top diff --git a/docs/build/latex/sphinxpackagefootnote.sty b/docs/build/latex/sphinxpackagefootnote.sty index 5590123..7f2e291 100644 --- a/docs/build/latex/sphinxpackagefootnote.sty +++ b/docs/build/latex/sphinxpackagefootnote.sty @@ -1,6 +1,6 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{sphinxpackagefootnote}% - [2022/08/15 v5.3.0 Sphinx custom footnotehyper package (Sphinx team)] + [2024/05/17 v7.3.x Sphinx custom footnotehyper package (Sphinx team)] %% %% Package: sphinxpackagefootnote %% Version: based on footnotehyper.sty 2021/02/04 v1.1d @@ -409,9 +409,10 @@ {\gdef\@thefnmark{?}% on first LaTeX run \refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}% }% - {\sphinx@xdef@thefnmark{#1}% also defines \spx@footrefHref - \def\@makefnmark{% will be used by \H@@footnotemark + {\def\@makefnmark{% will be used by \H@@footnotemark \refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}% + \sphinx@xdef@thefnmark{#1}% also defines \spx@footrefHref + % must be executed after \refstepcounter \hyper@linkstart{link}{\spx@footrefHref}% \spx@saved@makefnmark \hyper@linkend diff --git a/docs/build/latex/sphinxpackagesubstitutefont.sty b/docs/build/latex/sphinxpackagesubstitutefont.sty new file mode 100644 index 0000000..536bf20 --- /dev/null +++ b/docs/build/latex/sphinxpackagesubstitutefont.sty @@ -0,0 +1,21 @@ +%% a stub for obsoleted LaTeX package substitutefont +% The package substitutefont stopped being distributed with TeXLive +% around August 2023 and was moved to "obsolete" section. +% cf https://ctan.org/pkg/substitutefont +% Trying to load it raises a LaTeX build error since. + +% The \substitutefont has a LaTeX kernel replacement +% \DeclareFontFamilySubstitution +% which was added to LaTeX 2020-02-02 +% The aim of this stub is to do that replacement silently. + +% change this info string if making any custom modification +\ProvidesPackage{sphinxpackagesubstitutefont}[2023/15/11 v7.3.0 substitutefont stub] + +\ifdefined\DeclareFontFamilySubstitution + \def\substitutefont{\DeclareFontFamilySubstitution} +\else + \usepackage{substitutefont} +\fi + +\endinput diff --git a/docs/history.rst b/docs/history.rst index 803d6f9..eee4b55 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -48,6 +48,10 @@ Version 1.4 (16 May 2023) * Bugfix: reset slow iteration counter when doing soft restarts Version 1.4.1 (11 Apr 2024) -------------------------- +--------------------------- * Migrate package setup to pyproject.toml (required for Python version 3.12) * Drop support for Python 2.7 and <=3.7 due to new setup process + +Version 1.5.0 (16 Sep 2024) +--------------------------- +* Added support for general convex constraints diff --git a/docs/index.rst b/docs/index.rst index f0ec695..4b54d60 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,23 +12,26 @@ Py-BOBYQA: Derivative-Free Optimizer for Bound-Constrained Minimization **Author:** `Lindon Roberts `_ -Py-BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound constraints), without requiring any derivatives of the objective. Py-BOBYQA is a Python implementation of the `BOBYQA `_ solver by Powell (documentation `here `_). It is particularly useful when evaluations of the objective function are expensive and/or noisy. +Py-BOBYQA is a flexible package for finding local solutions to nonlinear, nonconvex minimization problems (with optional bound and other convex constraints), without requiring any derivatives of the objective. Py-BOBYQA is a Python implementation of the `BOBYQA `_ solver by Powell (documentation `here `_). It is particularly useful when evaluations of the objective function are expensive and/or noisy. That is, Py-BOBYQA solves .. math:: \min_{x\in\mathbb{R}^n} &\quad f(x)\\ - \text{s.t.} &\quad a \leq x \leq b + \text{s.t.} &\quad a \leq x \leq b \\ + &\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex} -The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). +If provided, the constraints the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds), +although the general :math:`x \in C` constraint may be slightly violated from rounding errors. Full details of the Py-BOBYQA algorithm are given in our papers: 1. Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, `Improving the Flexibility and Robustness of Model-Based Derivative-Free Optimization Solvers `_, *ACM Transactions on Mathematical Software*, 45:3 (2019), pp. 32:1-32:41 [`preprint `_] -2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +2. Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +3. Lindon Roberts, `Model Construction for Convex-Constrained Derivative-Free Optimization `_, *arXiv preprint arXiv:2403.14960* (2024). -Please cite [1] when using Py-BOBYQA for local optimization, and [1,2] when using Py-BOBYQA's global optimization heuristic functionality. +Please cite [1] when using Py-BOBYQA for local optimization, [1,2] when using Py-BOBYQA's global optimization heuristic functionality, and [1,3] if using the general convex constraints :math:`x \in C` functionality. If you are interested in solving least-squares minimization problems, you may wish to try `DFO-LS `_, which has the same features as Py-BOBYQA (plus some more), and exploits the least-squares problem structure, so performs better on such problems. @@ -49,5 +52,6 @@ Py-BOBYQA is released under the GNU General Public License. Please `contact NAG Acknowledgements ---------------- -This software was developed under the supervision of `Coralia Cartis `_, and was supported by the EPSRC Centre For Doctoral Training in `Industrially Focused Mathematical Modelling `_ (EP/L015803/1) in collaboration with the `Numerical Algorithms Group `_. +This software was initially developed under the supervision of `Coralia Cartis `_, and was supported by the EPSRC Centre For Doctoral Training in `Industrially Focused Mathematical Modelling `_ (EP/L015803/1) in collaboration with the `Numerical Algorithms Group `_. +Development of Py-BOBYQA has also been supported by the Australian Research Council (DE240100006). diff --git a/docs/info.rst b/docs/info.rst index 4b60412..c289ad9 100644 --- a/docs/info.rst +++ b/docs/info.rst @@ -3,12 +3,13 @@ Overview When to use Py-BOBYQA --------------------- -Py-BOBYQA is designed to solve the nonlinear least-squares minimization problem (with optional bound constraints) +Py-BOBYQA is designed to solve the nonlinear least-squares minimization problem (with optional bound and general convex constraints) .. math:: \min_{x\in\mathbb{R}^n} &\quad f(x)\\ - \text{s.t.} &\quad a \leq x \leq b + \text{s.t.} &\quad a \leq x \leq b\\ + &\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex} We call :math:`f(x)` the objective function. diff --git a/docs/install.rst b/docs/install.rst index 94454c0..08a638c 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -17,25 +17,17 @@ Additionally, the following python packages should be installed (these will be i Installation using pip ---------------------- -For easy installation, use `pip `_ as root: +For easy installation, use `pip `_: .. code-block:: bash - $ [sudo] pip install Py-BOBYQA - -If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use: - - .. code-block:: bash - - $ pip install --user Py-BOBYQA - -which will install Py-BOBYQA in your home directory. + $ pip install Py-BOBYQA Note that if an older install of Py-BOBYQA is present on your system you can use: .. code-block:: bash - $ [sudo] pip install --upgrade Py-BOBYQA + $ pip install --upgrade Py-BOBYQA to upgrade Py-BOBYQA to the latest version. @@ -52,22 +44,14 @@ Py-BOBYQA is written in pure Python and requires no compilation. It can be insta .. code-block:: bash - $ [sudo] pip install . - -If you do not have root privileges or you want to install Py-BOBYQA for your private use, you can use: - - .. code-block:: bash - - $ pip install --user . - -instead. + $ pip install . To upgrade Py-BOBYQA to the latest version, navigate to the top-level directory (i.e. the one containing :code:`setup.py`) and rerun the installation using :code:`pip`, as above: .. code-block:: bash $ git pull - $ [sudo] pip install . # with admin privileges + $ pip install . Testing ------- @@ -84,7 +68,7 @@ If Py-BOBYQA was installed using `pip `_ you can .. code-block:: bash - $ [sudo] pip uninstall Py-BOBYQA + $ pip uninstall Py-BOBYQA If Py-BOBYQA was installed manually you have to remove the installed files by hand (located in your python site-packages directory). diff --git a/docs/userguide.rst b/docs/userguide.rst index b88d30e..5513874 100644 --- a/docs/userguide.rst +++ b/docs/userguide.rst @@ -9,12 +9,18 @@ Py-BOBYQA is designed to solve the local optimization problem .. math:: \min_{x\in\mathbb{R}^n} &\quad f(x) \\ - \text{s.t.} &\quad a \leq x \leq b + \text{s.t.} &\quad a \leq x \leq b\\ + &\quad x \in C := C_1 \cap \cdots \cap C_n, \quad \text{all $C_i$ convex} -where the bound constraints :math:`a \leq x \leq b` are optional. The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). The objective function :math:`f(x)` is usually nonlinear and nonquadratic. If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see `here `_ for details). +where the bound constraints :math:`a \leq x \leq b` and general convex constraints :math:`x \in C` are optional. +The upper and lower bounds on the variables are non-relaxable (i.e. Py-BOBYQA will never ask to evaluate a point outside the bounds). +The general convex constraints are also non-relaxable, but they may be slightly violated at some points from rounding errors. +The objective function :math:`f(x)` is usually nonlinear and nonquadratic. +If you know your objective is linear or quadratic, you should consider a solver designed for such functions (see `here `_ for details). Py-BOBYQA iteratively constructs an interpolation-based model for the objective, and determines a step using a trust-region framework. For an in-depth technical description of the algorithm see the paper [CFMR2018]_, and for the global optimization heuristic, see [CRO2022]_. +For details about how Py-BOBYQA handles general convex constraints, see [R2024]_. How to use Py-BOBYQA -------------------- @@ -65,17 +71,18 @@ The :code:`solve` function has several optional arguments which the user may pro .. code-block:: python - pybobyqa.solve(objfun, x0, args=(), bounds=None, npt=None, - rhobeg=None, rhoend=1e-8, maxfun=None, nsamples=None, - user_params=None, objfun_has_noise=False, - seek_global_minimum=False, - scaling_within_bounds=False, - do_logging=True, print_progress=False) + pybobyqa.solve(objfun, x0, args=(), bounds=None, projections=None, + npt=None, rhobeg=None, rhoend=1e-8, maxfun=None, + nsamples=None, user_params=None, objfun_has_noise=False, + seek_global_minimum=False, + scaling_within_bounds=False, + do_logging=True, print_progress=False) These arguments are: * :code:`args` - a tuple of extra arguments passed to the objective function. * :code:`bounds` - a tuple :code:`(lower, upper)` with the vectors :math:`a` and :math:`b` of lower and upper bounds on :math:`x` (default is :math:`a_i=-10^{20}` and :math:`b_i=10^{20}`). To set bounds for either :code:`lower` or :code:`upper`, but not both, pass a tuple :code:`(lower, None)` or :code:`(None, upper)`. +* :code:`projections` - a list of functions defining the Euclidean projections for each general convex constraint :math:`C_i`. Each element of the list :code:`projections` is a function that takes an input vector :math:`x` and returns the closest point to :math:`x` that is in :math:`C_i`. An example of using this is given below. * :code:`npt` - the number of interpolation points to use (default is :math:`2n+1` for a problem with :code:`len(x0)=n` if :code:`objfun_has_noise=False`, otherwise it is set to :math:`(n+1)(n+2)/2`). Py-BOBYQA requires :math:`n+1 \leq npt \leq (n+1)(n+2)/2`. Larger values are particularly useful for noisy problems. * :code:`rhobeg` - the initial value of the trust region radius (default is 0.1 if :code:`scaling_within_bounds=True`, otherwise :math:`0.1\max(\|x_0\|_{\infty}, 1)`). * :code:`rhoend` - minimum allowed value of trust region radius, which determines when a successful termination occurs (default is :math:`10^{-8}`). @@ -217,6 +224,81 @@ An alternative option available is to get Py-BOBYQA to print to terminal progres 1 132 1.00e-02 2.00e-01 1.50e-08 1.00e-08 144 1 133 1.00e-02 2.00e-01 1.50e-08 1.00e-08 145 +Adding General Convex Constraints +--------------------------------- +We can also add more general convex constraints :math:`x \in C := C_1 \cap \cdots \cap C_n` to our problem, where +each :math:`C_i` is a convex set. To do this, we need to know the Euclidean projection operator for each :math:`C_i`: + +.. math:: + + \operatorname{proj}_{C_i}(x) := \operatorname{argmin}_{y\in C_i} \|y-x\|_2^2. + +i.e. given a point :math:`x`, return the closest point to :math:`x` in the set :math:`C_i`. +There are many examples of simple convex sets :math:`C_i` for which this function has a known, simple form, such as: + +* Bound constraints (but since Py-BOBYQA supports this directly, it is better to give these explicitly via the :code:`bounds` input, as above) +* Euclidean ball constraints: :math:`\|x-c\|_2 \leq r` +* Unit simplex: :math:`x_i \geq 0` and :math:`\sum_{i=1}^{n} x_i \leq 1` +* Linear inequalities: :math:`a^T x \geq b` + +In Py-BOBYQA, set the input :code:`projections` to be a list of projection functions, one per :math:`C_i`. +Internally, Py-BOBYQA computes the projection onto the intersection of these sets and the bound constraints +using `Dykstra's projection algorithm `_. + +For the explicit expressions for the above projections, and more examples, see for example `this online database `_ +or Section 6.4.6 of the textbook [B2017]_. + +As an example, let's minimize the above Rosenbrock function with different bounds, and with a Euclidean +ball constraint, namely :math:`(x_1-0.5)^2 + (x_2-1)^2 \leq 0.25^2`. + +To do this, we can run + + .. code-block:: python + + import numpy as np + import pybobyqa + + # Define the objective function + def rosenbrock(x): + return 100.0 * (x[1] - x[0] ** 2) ** 2 + (1.0 - x[0]) ** 2 + + # Define the starting point + x0 = np.array([-1.2, 1.0]) + + # Define bound constraints (lower <= x <= upper) + lower = np.array([0.7, -2.0]) + upper = np.array([1.0, 2.0]) + + # Define the ball constraint ||x-center|| <= radius, and its projection operator + center = np.array([0.5, 1.0]) + radius = 0.25 + ball_proj = lambda x: center + (radius/max(np.linalg.norm(x-center), radius)) * (x-center) + + # Call Py-BOBYQA (with bounds and projection operator) + # Note: it is better to provide bounds explicitly, instead of using the corresponding + # projection function + # Note: input 'projections' must be a list of projection functions + soln = pybobyqa.solve(rosenbrock, x0, bounds=(lower,upper), projections=[ball_proj]) + + print(soln) + +Py-BOBYQA correctly finds the solution to the constrained problem: + + .. code-block:: none + + ****** Py-BOBYQA Results ****** + Solution xmin = [0.70424386 0.85583188] + Objective value f(xmin) = 13.03829114 + Needed 25 objective evaluations (at 25 points) + Approximate gradient = [-101.9667031 71.97449424] + Approximate Hessian = [[ 253.11858775 -279.39193327] + [-279.39193327 201.49725358]] + Exit flag = 0 + Success: rho has reached rhoend + ****************************** + +Just like for bound constraints, Py-BOBYQA will automatically ensure the starting point is feasible with respect to all constraints (bounds and general convex constraints). + Example: Noisy Objective Evaluation ----------------------------------- As described in :doc:`info`, derivative-free algorithms such as Py-BOBYQA are particularly useful when :code:`objfun` has noise. Let's modify the previous example to include random noise in our objective evaluation, and compare it to a derivative-based solver: @@ -411,3 +493,7 @@ References Coralia Cartis, Jan Fiala, Benjamin Marteau and Lindon Roberts, `Improving the Flexibility and Robustness of Model-Based Derivative-Free Optimization Solvers `_, *ACM Transactions on Mathematical Software*, 45:3 (2019), pp. 32:1-32:41 [`preprint `_] .. [CRO2022] Coralia Cartis, Lindon Roberts and Oliver Sheridan-Methven, `Escaping local minima with derivative-free methods: a numerical investigation `_, *Optimization*, 71:8 (2022), pp. 2343-2373. [`arXiv preprint: 1812.11343 `_] +.. [R2024] + Lindon Roberts, `Model Construction for Convex-Constrained Derivative-Free Optimization `_, *arXiv preprint arXiv:2403.14960* (2024). +.. [B2017] + Amir Beck, `First-Order Methods in Optimization `_, SIAM (2017). \ No newline at end of file diff --git a/examples/rosenbrock_ball.py b/examples/rosenbrock_ball.py new file mode 100644 index 0000000..d058c95 --- /dev/null +++ b/examples/rosenbrock_ball.py @@ -0,0 +1,43 @@ +# Py-BOBYQA example: minimize the Rosenbrock function with bounds and ball constraint +from __future__ import print_function +import numpy as np +import pybobyqa + +# Define the objective function +def rosenbrock(x): + return 100.0 * (x[1] - x[0] ** 2) ** 2 + (1.0 - x[0]) ** 2 + +# Define the starting point +x0 = np.array([-1.2, 1.0]) + +# Define bound constraints (lower <= x <= upper) +lower = np.array([0.7, -2.0]) +upper = np.array([1.0, 2.0]) + +# Define a Euclidean ball constraint, ||x-center|| <= radius +# This is provided to Py-BOBYQA via a projection operator, which given a point x returns +# the closest point to x which satisfies the constraint +center = np.array([0.5, 1.0]) +radius = 0.25 +# The projection operator for this constraint is: +ball_proj = lambda x: center + (radius/max(np.linalg.norm(x-center), radius)) * (x-center) + +# Many common types of constraints have simple projection operators. +# e.g. lower/upper bounds (but Py-BOBYQA supports this natively, not recommended to use projections) +# Euclidean balls +# Linear inequalities, np.dot(a, x) >= b +# Unit simplex, np.all(x) >= 0 and np.sum(x) <= 1 +# For more examples, see +# - https://proximity-operator.net/indicatorfunctions.html +# - Section 6.4.6 (pp. 155-156) of the book: A. Beck, First-Order Methods in Optimization, SIAM (2017) + +# For optional extra output details +# import logging +# logging.basicConfig(level=logging.INFO, format='%(message)s') + +# Call Py-BOBYQA (with bounds) +soln = pybobyqa.solve(rosenbrock, x0, bounds=(lower, upper), projections=[ball_proj]) # provide list of projection operators + +# Display output +print(soln) + diff --git a/manual.pdf b/manual.pdf index 005ef9c..de9b460 100644 Binary files a/manual.pdf and b/manual.pdf differ diff --git a/pybobyqa/__init__.py b/pybobyqa/__init__.py index cbfbb6c..d426887 100644 --- a/pybobyqa/__init__.py +++ b/pybobyqa/__init__.py @@ -39,7 +39,7 @@ # Ensure compatibility with Python 2 from __future__ import absolute_import, division, print_function, unicode_literals -__version__ = '1.4.1' +__version__ = '1.5.0' # Main solver & exit flags from .solver import * diff --git a/pybobyqa/controller.py b/pybobyqa/controller.py index e5dfbb9..40e5aeb 100644 --- a/pybobyqa/controller.py +++ b/pybobyqa/controller.py @@ -94,11 +94,11 @@ def able_to_do_restart(self): class Controller(object): - def __init__(self, objfun, x0, args, f0, f0_nsamples, xl, xu, npt, rhobeg, rhoend, nf, nx, maxfun, params, scaling_changes, do_logging=True): + def __init__(self, objfun, x0, args, f0, f0_nsamples, xl, xu, projections, npt, rhobeg, rhoend, nf, nx, maxfun, params, scaling_changes, do_logging=True): self.objfun = objfun self.maxfun = maxfun self.args = args - self.model = Model(npt, x0, f0, xl, xu, f0_nsamples, abs_tol=params("model.abs_tol"), + self.model = Model(npt, x0, f0, xl, xu, projections, f0_nsamples, abs_tol=params("model.abs_tol"), precondition=params("interpolation.precondition"), do_logging=do_logging) self.nf = nf self.nx = nx @@ -268,18 +268,145 @@ def initialise_random_directions(self, number_of_samples, num_directions, params return None - def trust_region_step(self): + def initialise_general_constraints(self, number_of_samples, num_directions, params): + # Initialisation when we have general projection constraints, as well as bound constraints + # Basic idea: start with bound-respecting coordinate directions, just like initialise_coordinate_directions + # Then, use geometry-improving procedures to make all these points feasible wrt projection constraints + # Only after this is all done, then evaluate the initial points + # (after the initial coordinate directions given, add points to model with nan objective value) + if self.do_logging: + module_logger.debug("Initialising to satisfy general projection constraints") + # self.model already has x0 evaluated (and x0 feasible), so only need to initialise the other points + # num_directions = params("growing.ndirs_initial") + assert self.model.num_pts <= (self.n() + 1) * (self.n() + 2) // 2, "prelim: must have npt <= (n+1)(n+2)/2" + assert 1 <= num_directions < self.model.num_pts, "Initialisation: must have 1 <= ndirs_initial < npt" + + at_lower_boundary = (self.model.sl > -0.01 * self.delta) # sl = xl - x0, should be -ve, actually < -rhobeg + at_upper_boundary = (self.model.su < 0.01 * self.delta) # su = xu - x0, should be +ve, actually > rhobeg + + # **** STEP 1 **** + # Build initial coordinate-based directions + xpts_added = np.zeros((num_directions + 1, self.n())) + for k in range(1, num_directions + 1): + # k = 0 --> base point (xpt = 0) [ not here] + # k = 1, ..., 2n --> coordinate directions [1,...,n and n+1,...,2n] + # k = 2n+1, ..., (n+1)(n+2)/2 --> off-diagonal directions + if 1 <= k < self.n() + 1: # first step along coord directions + dirn = k - 1 # direction to move in (0,...,n-1) + stepa = self.delta if not at_upper_boundary[dirn] else -self.delta + stepb = None + xpts_added[k, dirn] = stepa + + elif self.n() + 1 <= k < 2 * self.n() + 1: # second step along coord directions + dirn = k - self.n() - 1 # direction to move in (0,...,n-1) + stepa = xpts_added[k - self.n(), dirn] + stepb = -self.delta + if at_lower_boundary[dirn]: + stepb = min(2.0 * self.delta, self.model.su[dirn]) # su = xu - x0, should be +ve + if at_upper_boundary[dirn]: + stepb = max(-2.0 * self.delta, self.model.sl[dirn]) # sl = xl - x0, should be -ve + xpts_added[k, dirn] = stepb + + else: # k = 2n+1, ..., (n+1)(n+2)/2 + # p = (k - 1) % n + 1 # cycles through (1,...,n), starting at 2n+1 --> 1 + # l = (k - 2 * n - 1) / n + 1 # (1,...,1, 2, ..., 2, etc.) where each number appears n times + # q = (p + l if p + l <= n else p + l - n) + stepa = None + stepb = None + itemp = (k - self.n() - 1) // self.n() + q = k - itemp * self.n() - self.n() + p = q + itemp + if p > self.n(): + p, q = q, p - self.n() # does swap correctly in Python + + xpts_added[k, p - 1] = xpts_added[p, p - 1] + xpts_added[k, q - 1] = xpts_added[q, q - 1] + + # Add this new point to the model with a nan function value for now, since it is likely to be moved + # to ensure the projection constraints are respected + x = self.model.as_absolute_coordinates(xpts_added[k, :]) + self.model.change_point(k, x - self.model.xbase, np.nan) # expect step, not absolute x + + # (no need to switch the k-th and (k-N)-th points, since we can't compare function values at this stage) + + # **** STEP 2 **** + # Now go through all interpolation points and check if they are feasible wrt projection constraints + # If not, do a geometry-improving step (again with nan objective value) + for k in range(1, num_directions + 1): + x = self.model.as_absolute_coordinates(xpts_added[k, :]) + this_x_feasible = True + for i, proj in enumerate(self.model.projections): + if np.linalg.norm(x - proj(x)) > params("projections.feasible_tol"): + this_x_feasible = False + break # quit loop, only need to find one bad constraint + + # Calculate Lagrange polynomial and update this point + if not this_x_feasible: + try: + c, g, H = self.model.lagrange_polynomial(k) # based at xopt + if np.any(np.isinf(g)) or np.any(np.isnan(g)) or np.any(np.isinf(H)) or np.any(np.isnan(H)): + raise ValueError + xnew = ctrsbox_geometry(self.model.xbase, self.model.xopt(), c, g, H, self.model.sl, self.model.su, + self.model.projections, self.delta, + dykstra_max_iters=params("projections.dykstra.max_iters"), + dykstra_tol=params("projections.feasible_tol"), + gtol=params("projections.pgd_tol")) + except LA.LinAlgError: + exit_info = ExitInformation(EXIT_LINALG_ERROR, "Singular matrix encountered in initialization geometry step") + return exit_info # didn't fix geometry - return & quit + except ValueError: + # A ValueError may be raised if gopt or H have nan/inf values (issue #23) + # Ideally this should be picked up earlier in self.model.lagrange_polynomial(...) + exit_info = ExitInformation(EXIT_LINALG_ERROR, "Error when calculating initialization geometry-improving step") + return exit_info # didn't fix geometry - return & quit + + # Update point and fill with np.nan again, just for now + self.model.change_point(k, xnew, np.nan) # expect step, not absolute x + + # **** STEP 3 **** + # Now we are ready to evaluate our initial points + for k in range(1, num_directions + 1): + x = self.model.xpt(k, abs_coordinates=True) + f_list, num_samples_run, exit_info = self.evaluate_objective(x, number_of_samples, params) + + # Handle exit conditions (f < min obj value or maxfun reached) + if exit_info is not None: + if num_samples_run > 0: + self.model.save_point(x, np.mean(f_list[:num_samples_run]), num_samples_run, x_in_abs_coords=True) + return exit_info # didn't fix geometry - return & quit + + # Otherwise, add new results + self.model.change_point(k, x - self.model.xbase, f_list[0]) # expect step, not absolute x + for i in range(1, num_samples_run): + self.model.add_new_sample(k, f_extra=f_list[i]) + + return None # return & continue + + def trust_region_step(self, params): # Build model for full least squares objectives gopt, H = self.model.build_full_model() - try: - d, gnew, crvmin = trsbox(self.model.xopt(), gopt, H, self.model.sl, self.model.su, self.delta) - except ValueError: - # A ValueError may be raised if gopt or H have nan/inf values (issue #14) - # Although this should be picked up earlier, in this situation just return a zero - # trust-region step, which leads to a safety step being called in the main algorithm. + if np.any(np.isinf(gopt)) or np.any(np.isnan(gopt)) or np.any(np.isinf(H)) or np.any(np.isnan(H)): + # Skip computing the step if gopt or H are badly formed d = np.zeros(gopt.shape) gnew = gopt.copy() crvmin = 0.0 # this usually represents 'step on trust-region boundary' but seems to be a sensible default for errors + else: + try: + if self.model.projections is None: + d, gnew, crvmin = trsbox(self.model.xopt(), gopt, H, self.model.sl, self.model.su, self.delta) + else: + d, gnew, crvmin = ctrsbox(self.model.xbase, self.model.xopt(), gopt, H, self.model.sl, self.model.su, + self.model.projections, self.delta, + dykstra_max_iters=params("projections.dykstra.max_iters"), + dykstra_tol=params("projections.feasible_tol"), + gtol=params("projections.pgd_tol")) + except ValueError: + # A ValueError may be raised if gopt or H have nan/inf values (issue #14) + # Although this should be picked up earlier, in this situation just return a zero + # trust-region step, which leads to a safety step being called in the main algorithm. + d = np.zeros(gopt.shape) + gnew = gopt.copy() + crvmin = 0.0 # this usually represents 'step on trust-region boundary' but seems to be a sensible default for errors return d, gopt, H, gnew, crvmin def geometry_step(self, knew, adelt, number_of_samples, params): @@ -293,7 +420,16 @@ def geometry_step(self, knew, adelt, number_of_samples, params): # Solve problem: bounds are sl <= xnew <= su, and ||xnew-xopt|| <= adelt try: - xnew = trsbox_geometry(self.model.xopt(), c, g, H, self.model.sl, self.model.su, adelt) + if np.any(np.isinf(g)) or np.any(np.isnan(g)) or np.any(np.isinf(H)) or np.any(np.isnan(H)): + raise ValueError + if self.model.projections is None: + xnew = trsbox_geometry(self.model.xopt(), c, g, H, self.model.sl, self.model.su, adelt) + else: + xnew = ctrsbox_geometry(self.model.xbase, self.model.xopt(), c, g, H, self.model.sl, self.model.su, + self.model.projections, adelt, + dykstra_max_iters=params("projections.dykstra.max_iters"), + dykstra_tol=params("projections.feasible_tol"), + gtol=params("projections.pgd_tol")) except ValueError: # A ValueError may be raised if gopt or H have nan/inf values (issue #23) # Ideally this should be picked up earlier in self.model.lagrange_polynomial(...) diff --git a/pybobyqa/model.py b/pybobyqa/model.py index 454a8d5..ef1188d 100644 --- a/pybobyqa/model.py +++ b/pybobyqa/model.py @@ -36,7 +36,7 @@ from .hessian import to_upper_triangular_vector from .trust_region import trsbox_geometry -from .util import sumsq, model_value +from .util import sumsq, model_value, dykstra __all__ = ['Model'] @@ -45,7 +45,7 @@ class Model(object): - def __init__(self, npt, x0, f0, xl, xu, f0_nsamples, n=None, abs_tol=-1e20, precondition=True, do_logging=True): + def __init__(self, npt, x0, f0, xl, xu, projections, f0_nsamples, n=None, abs_tol=-1e20, precondition=True, do_logging=True): if n is None: n = len(x0) assert npt >= n + 1, "Require npt >= n+1 for quadratic models" @@ -62,6 +62,7 @@ def __init__(self, npt, x0, f0, xl, xu, f0_nsamples, n=None, abs_tol=-1e20, prec self.xbase = x0.copy() self.sl = xl - self.xbase # lower bound w.r.t. xbase (require xpt >= sl) self.su = xu - self.xbase # upper bound w.r.t. xbase (require xpt <= su) + self.projections = projections # list of projection-based constraints (excluding explicit bounds) self.points = np.zeros((npt, n)) # interpolation points w.r.t. xbase # Function values diff --git a/pybobyqa/params.py b/pybobyqa/params.py index 506e435..2f7e9f5 100644 --- a/pybobyqa/params.py +++ b/pybobyqa/params.py @@ -86,6 +86,12 @@ def __init__(self, n, npt, maxfun, objfun_has_noise=False, seek_global_minimum=F self.params["restarts.auto_detect.min_chg_model_slope"] = 1.5e-2 self.params["restarts.auto_detect.min_correl"] = 0.1 + # Projections + self.params["projections.dykstra.d_tol"] = 1e-10 + self.params["projections.dykstra.max_iters"] = 100 + self.params["projections.feasible_tol"] = 1e-10 + self.params["projections.pgd_tol"] = 1e-8 + self.params_changed = {} for p in self.params: self.params_changed[p] = False @@ -193,6 +199,14 @@ def param_type(self, key, npt): type_str, nonetype_ok, lower, upper = 'float', False, 0.0, None elif key == "restarts.auto_detect.min_correl": type_str, nonetype_ok, lower, upper = 'float', False, 0.0, 1.0 + elif key == "projections.dykstra.d_tol": + type_str, nonetype_ok, lower, upper = 'float', False, 0.0, None + elif key == "projections.dykstra.max_iters": + type_str, nonetype_ok, lower, upper = 'int', False, 1, None + elif key == "projections.feasible_tol": + type_str, nonetype_ok, lower, upper = 'float', False, 0.0, None + elif key == "projections.pgd_tol": + type_str, nonetype_ok, lower, upper = 'float', False, 0.0, None else: assert False, "ParameterList.param_type() has unknown key: %s" % key return type_str, nonetype_ok, lower, upper diff --git a/pybobyqa/solver.py b/pybobyqa/solver.py index 226e0d7..a70391f 100644 --- a/pybobyqa/solver.py +++ b/pybobyqa/solver.py @@ -96,7 +96,7 @@ def __str__(self): return output -def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_far, nf_so_far, nx_so_far, nsamples, params, +def solve_main(objfun, x0, args, xl, xu, projections, npt, rhobeg, rhoend, maxfun, nruns_so_far, nf_so_far, nx_so_far, nsamples, params, diagnostic_info, scaling_changes, f0_avg_old=None, f0_nsamples_old=None, do_logging=True, print_progress=False): # Evaluate at x0 (keep nf, nx correct and check for f small) if f0_avg_old is None: @@ -144,12 +144,16 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f nx = nx_so_far # Initialise controller - control = Controller(objfun, x0, args, f0_avg, num_samples_run, xl, xu, npt, rhobeg, rhoend, nf, nx, maxfun, params, scaling_changes, do_logging=do_logging) + control = Controller(objfun, x0, args, f0_avg, num_samples_run, xl, xu, projections, npt, rhobeg, rhoend, nf, nx, maxfun, params, scaling_changes, do_logging=do_logging) # Initialise interpolation set number_of_samples = max(nsamples(control.delta, control.rho, 0, nruns_so_far), 1) num_directions = npt - 1 - if params("init.random_initial_directions"): + if projections is not None: + if do_logging: + module_logger.info("Initialising (feasible directions for constraints)") + exit_info = control.initialise_general_constraints(number_of_samples, num_directions, params) + elif params("init.random_initial_directions"): if do_logging: module_logger.info("Initialising (random directions)") exit_info = control.initialise_random_directions(number_of_samples, num_directions, params) @@ -231,7 +235,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f # Trust region step - d, gopt, H, gnew, crvmin = control.trust_region_step() + d, gopt, H, gnew, crvmin = control.trust_region_step(params) if do_logging: module_logger.debug("Trust region step is d = " + str(d)) xnew = control.model.xopt() + d @@ -665,7 +669,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f return x, f, gradmin, hessmin, nsamples, control.nf, control.nx, nruns_so_far, exit_info, diagnostic_info -def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8, maxfun=None, nsamples=None, user_params=None, +def solve(objfun, x0, args=(), bounds=None, projections=None, npt=None, rhobeg=None, rhoend=1e-8, maxfun=None, nsamples=None, user_params=None, objfun_has_noise=False, seek_global_minimum=False, scaling_within_bounds=False, do_logging=True, print_progress=False): n = len(x0) if type(x0) == list: @@ -694,7 +698,11 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8, if (xl is None or xu is None) and scaling_within_bounds: scaling_within_bounds = False warnings.warn("Ignoring scaling_within_bounds=True for unconstrained problem/1-sided bounds", RuntimeWarning) - + + if (projections is not None) and scaling_within_bounds: + scaling_within_bounds = False + warnings.warn("Ignoring scaling_within_bounds=True for problems with projections given", RuntimeWarning) + exit_info = None if seek_global_minimum and (xl is None or xu is None): exit_info = ExitInformation(EXIT_INPUT_ERROR, "If seeking global minimum, must specify upper and lower bounds") @@ -761,6 +769,13 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8, if exit_info is None and np.min(xu - xl) < 2.0 * rhobeg: exit_info = ExitInformation(EXIT_INPUT_ERROR, "gap between lower and upper must be at least 2*rhobeg") + if exit_info is None and projections is not None and type(projections) != list: + exit_info = ExitInformation(EXIT_INPUT_ERROR, "projections must be a list of functions") + + if projections is not None and len(projections) == 0: + # empty list given + projections = None + if maxfun <= npt: warnings.warn("maxfun <= npt: Are you sure your budget is large enough?", RuntimeWarning) @@ -792,23 +807,37 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8, return results # Enforce lower & upper bounds on x0 - idx = (x0 <= xl) + idx = (x0 < xl) if np.any(idx): warnings.warn("x0 below lower bound, adjusting", RuntimeWarning) x0[idx] = xl[idx] - idx = (x0 >= xu) + idx = (x0 > xu) if np.any(idx): warnings.warn("x0 above upper bound, adjusting", RuntimeWarning) x0[idx] = xu[idx] + # Enforce feasibility of x0 with respect to projection constraints + if projections is not None: + x0_feasible = True + for i, proj in enumerate(projections): + if np.linalg.norm(x0 - proj(x0)) > params("projections.feasible_tol"): + x0_feasible = False + warnings.warn("x0 not feasible with respect to projections[%g], adjusting" % i, RuntimeWarning) + break # quit loop, only need to find one bad constraint + if not x0_feasible: + proj_box = lambda w: pbox(w, xl, xu) + P = list(projections) # make a copy of the projections list + P.append(proj_box) + x0 = dykstra(P, x0) + # Call main solver (first time) diagnostic_info = DiagnosticInfo() nruns = 0 nf = 0 nx = 0 xmin, fmin, gradmin, hessmin, nsamples_min, nf, nx, nruns, exit_info, diagnostic_info = \ - solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns, nf, nx, nsamples, params, + solve_main(objfun, x0, args, xl, xu, projections, npt, rhobeg, rhoend, maxfun, nruns, nf, nx, nsamples, params, diagnostic_info, scaling_changes, do_logging=do_logging, print_progress=print_progress) # Hard restarts loop @@ -829,11 +858,11 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8, % (fmin, nf, _rhobeg, _rhoend)) if params("restarts.hard.use_old_fk"): xmin2, fmin2, gradmin2, hessmin2, nsamples2, nf, nx, nruns, exit_info, diagnostic_info = \ - solve_main(objfun, xmin, args, xl, xu, npt, _rhobeg, _rhoend, maxfun, nruns, nf, nx, nsamples, params, + solve_main(objfun, xmin, args, xl, xu, projections, npt, _rhobeg, _rhoend, maxfun, nruns, nf, nx, nsamples, params, diagnostic_info, scaling_changes, f0_avg_old=fmin, f0_nsamples_old=nsamples_min, do_logging=do_logging, print_progress=print_progress) else: xmin2, fmin2, gradmin2, hessmin2, nsamples2, nf, nx, nruns, exit_info, diagnostic_info = \ - solve_main(objfun, xmin, args, xl, xu, npt, _rhobeg, _rhoend, maxfun, nruns, nf, nx, nsamples, params, + solve_main(objfun, xmin, args, xl, xu, projections, npt, _rhobeg, _rhoend, maxfun, nruns, nf, nx, nsamples, params, diagnostic_info, scaling_changes, do_logging=do_logging, print_progress=print_progress) if fmin2 < fmin or np.isnan(fmin): diff --git a/pybobyqa/tests/test_model.py b/pybobyqa/tests/test_model.py index 1eaa988..0989ea3 100644 --- a/pybobyqa/tests/test_model.py +++ b/pybobyqa/tests/test_model.py @@ -55,7 +55,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e20 * np.ones((n,)) xu = 1e20 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) self.assertEqual(model.npt(), npt, 'Wrong npt after initialisation') self.assertTrue(array_compare(model.xopt(abs_coordinates=True), x0), 'Wrong xopt after initialisation') self.assertTrue(array_compare(model.fopt(), rosenbrock(x0)), 'Wrong fopt after initialisation') @@ -103,7 +103,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e20 * np.ones((n,)) xu = 1e20 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) # Now add better point x1 = np.array([1.0, 0.9]) f1 = rosenbrock(x1) @@ -131,7 +131,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) self.assertTrue(array_compare(model.sl, xl - x0), 'Wrong sl after initialisation') self.assertTrue(array_compare(model.su, xu - x0), 'Wrong su after initialisation') x1 = np.array([1.0, 0.9]) @@ -204,7 +204,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) x1 = np.array([1.0, 0.9]) model.change_point(1, x1 - model.xbase, rosenbrock(x1)) x2 = np.array([1.0, 1.0]) @@ -224,13 +224,13 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) x1 = np.array([1.0, 0.9]) model.change_point(1, x1 - model.xbase, rosenbrock(x1)) x2 = np.array([2.0, 0.9]) model.change_point(2, x2 - model.xbase, rosenbrock(x2)) self.assertAlmostEqual(model.min_objective_value(), -1e20, msg='Wrong min obj value') - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1, abs_tol=1.0) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1, abs_tol=1.0) self.assertAlmostEqual(model.min_objective_value(), 1.0, msg='Wrong min obj value 3') @@ -241,7 +241,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1, precondition=False) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1, precondition=False) x1 = np.array([1.0, 0.9]) model.change_point(1, x1 - model.xbase, rosenbrock(x1)) x2 = np.array([2.0, 0.9]) @@ -280,7 +280,7 @@ def runTest(self): x0 = np.array([1.0, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1, precondition=False) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1, precondition=False) x1 = x0 + np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = x0 + np.array([0.1, 0.9]) @@ -323,7 +323,7 @@ def runTest(self): self.assertTrue(np.allclose(hess, model.model_hess), 'Bad Hessian') # Build a new model - model2 = Model(npt, x0, objfun(x0), xl, xu, 1, precondition=False) + model2 = Model(npt, x0, objfun(x0), xl, xu, [], 1, precondition=False) model2.change_point(1, x1 - model.xbase, objfun(x1)) model2.change_point(2, x2 - model.xbase, objfun(x2)) model2.change_point(3, x3 - model.xbase, objfun(x3)) @@ -350,7 +350,7 @@ def runTest(self): # print(model2.model_hess) # Build a new model - model3 = Model(npt, x0, objfun(x0), xl, xu, 1, precondition=False) + model3 = Model(npt, x0, objfun(x0), xl, xu, [], 1, precondition=False) model3.change_point(1, x1 - model.xbase, objfun(x1)) model3.change_point(2, x2 - model.xbase, objfun(x2)) model3.change_point(3, x3 - model.xbase, objfun(x3)) @@ -376,7 +376,7 @@ def runTest(self): x0 = np.array([1.0, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1, precondition=False) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1, precondition=False) x1 = x0 + np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = x0 + np.array([0.1, 0.9]) @@ -420,7 +420,7 @@ def runTest(self): self.assertTrue(np.allclose(hess, model.model_hess), 'Bad Hessian') # Build a new model - model2 = Model(npt, x0, objfun(x0), xl, xu, 1, precondition=False) + model2 = Model(npt, x0, objfun(x0), xl, xu, [], 1, precondition=False) model2.change_point(1, x1 - model.xbase, objfun(x1)) model2.change_point(2, x2 - model.xbase, objfun(x2)) model2.change_point(3, x3 - model.xbase, objfun(x3)) @@ -448,7 +448,7 @@ def runTest(self): # print(model2.model_hess) # Build a new model - model3 = Model(npt, x0, objfun(x0), xl, xu, 1, precondition=False) + model3 = Model(npt, x0, objfun(x0), xl, xu, [], 1, precondition=False) model3.change_point(1, x1 - model.xbase, objfun(x1)) model3.change_point(2, x2 - model.xbase, objfun(x2)) model3.change_point(3, x3 - model.xbase, objfun(x3)) @@ -475,7 +475,7 @@ def runTest(self): x0 = np.array([1.0, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1) x1 = x0 + np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = x0 + np.array([0.1, 0.9]) @@ -511,7 +511,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) x1 = np.array([1.0, 0.9]) model.change_point(1, x1 - model.xbase, rosenbrock(x1)) x2 = np.array([2.0, 0.9]) @@ -534,7 +534,7 @@ def runTest(self): x0 = np.array([1.0, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1) x1 = x0 + np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = x0 + np.array([0.1, 0.9]) @@ -559,7 +559,7 @@ def runTest(self): x0 = np.array([1.0, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1) x1 = x0 + np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = x0 + np.array([0.1, 0.9]) @@ -586,7 +586,7 @@ def runTest(self): x0 = np.array([1.0, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1) x1 = x0 + np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = x0 + np.array([0.1, 0.9]) @@ -616,7 +616,7 @@ def runTest(self): delta = 0.5 xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) model.add_new_sample(0, rosenbrock(x0)) x1 = x0 + delta * np.array([1.0, 0.0]) model.change_point(1, x1 - model.xbase, rosenbrock(x1)) @@ -636,7 +636,7 @@ def runTest(self): x0 = np.array([0.5, 0.5]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1) x1 = np.array([0.05, 0.1]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = np.array([0.1, 0.05]) @@ -660,7 +660,7 @@ def runTest(self): x0 = np.array([0.5, 0.5]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, objfun(x0), xl, xu, 1) + model = Model(npt, x0, objfun(x0), xl, xu, [], 1) x1 = np.array([0.524, 0.0006]) model.change_point(1, x1 - model.xbase, objfun(x1)) x2 = np.array([0.032, 0.323]) @@ -681,7 +681,7 @@ def runTest(self): x0 = np.array([-1.2, 1.0]) xl = -1e2 * np.ones((n,)) xu = 1e2 * np.ones((n,)) - model = Model(npt, x0, rosenbrock(x0), xl, xu, 1) + model = Model(npt, x0, rosenbrock(x0), xl, xu, [], 1) x1 = np.array([1.0, 0.9]) model.change_point(1, x1 - model.xbase, rosenbrock(x1)) x2 = np.array([2.0, 0.9]) diff --git a/pybobyqa/tests/test_solver.py b/pybobyqa/tests/test_solver.py index 3690566..3bbe1dc 100644 --- a/pybobyqa/tests/test_solver.py +++ b/pybobyqa/tests/test_solver.py @@ -45,6 +45,8 @@ def rosenbrock_gradient(x): def rosenbrock_hessian(x): return np.array([[2.0 + 100.0 * (8.0*x[0]**2 - 4.0*(-x[0]**2 + x[1])), -400.0*x[0]], [-400.0*x[0], 200.0]]) +def p_ball(x,c,r): + return c + (r/np.max([np.linalg.norm(x-c),r]))*(x-c) class TestRosenbrockGeneric(unittest.TestCase): # Minimise the (2d) Rosenbrock function @@ -121,7 +123,7 @@ def runTest(self): soln = pybobyqa.solve(objfun, x0) self.assertTrue(array_compare(soln.x, xmin, thresh=1e-2), "Wrong xmin") self.assertTrue(array_compare(soln.gradient, gradfun(soln.x), thresh=1e-2), "Wrong gradient") - self.assertTrue(array_compare(soln.hessian, hessfun, thresh=0.5), "Wrong Hessian") + self.assertTrue(array_compare(soln.hessian, hessfun, thresh=1.0), "Wrong Hessian") self.assertTrue(abs(soln.f - fmin) < 1e-4, "Wrong fmin") @@ -160,3 +162,23 @@ def runTest(self): # self.assertTrue(array_compare(soln.hessian, rosenbrock_hessian(soln.x), thresh=1e-0), "Wrong Hessian") self.assertLessEqual(np.max(np.abs(rosenbrock_hessian(soln.x) / soln.hessian)) - 1, 1e-1, "Wrong Hessian") self.assertTrue(abs(soln.f) < 1e-10, "Wrong fmin") + + +class TestRosenbrockBounds3(unittest.TestCase): + # Minimise the (2d) Rosenbrock function, with extra ball constraint + def runTest(self): + # n, m = 2, 2 + x0 = np.array([-1.2, 0.7]) # standard start point does not satisfy bounds + lower = np.array([0.7, -2.0]) + upper = np.array([1.0, 2.0]) + ballproj = lambda x: p_ball(x, np.array([0.5, 1]), 0.25) + xmin = np.array([0.70424386, 0.85583188]) # approximate + fmin = rosenbrock(xmin) + np.random.seed(0) + soln = pybobyqa.solve(rosenbrock, x0, bounds=(lower, upper), projections=[ballproj]) + self.assertTrue(array_compare(soln.x, xmin, thresh=1e-2), "Wrong xmin") + self.assertTrue(abs(soln.f - fmin) < 1e-4, "Wrong fmin") + self.assertTrue(array_compare(soln.gradient, rosenbrock_gradient(soln.x), thresh=1e-2), "Wrong gradient") + # Hessian entries are quite large, O(100-1000), so can have a fairly large tolerance (use relative terms) + self.assertLessEqual(np.max(np.abs(rosenbrock_hessian(soln.x) / soln.hessian)) - 1, 1e-1, "Wrong Hessian") + # self.assertTrue(array_compare(soln.hessian, rosenbrock_hessian(soln.x), thresh=1e-0), "Wrong Hessian") diff --git a/pybobyqa/tests/test_trust_region.py b/pybobyqa/tests/test_trust_region.py index 282e482..b2ea10a 100644 --- a/pybobyqa/tests/test_trust_region.py +++ b/pybobyqa/tests/test_trust_region.py @@ -27,7 +27,7 @@ import numpy as np import unittest -from pybobyqa.trust_region import trsbox, trsbox_geometry +from pybobyqa.trust_region import trsbox, trsbox_geometry, ctrsbox, ctrsbox_geometry from pybobyqa.util import model_value @@ -70,6 +70,11 @@ def cauchy_pt_box(g, hess, delta, lower, upper): crvmin = -1.0 return s, red, crvmin +def p_box(x, l, u): + return np.minimum(np.maximum(x,l), u) + +def p_ball(x, c, r): + return c + (r/np.max([np.linalg.norm(x-c),r]))*(x-c) class TestUncInternal(unittest.TestCase): def runTest(self): @@ -382,3 +387,198 @@ def runTest(self): # print(x) # print(xtrue) self.assertTrue(np.allclose(x, xtrue, atol=1e-3), "Wrong step") + + +class TestGeom3CDFO(unittest.TestCase): + def runTest(self): + n = 2 + xbase = np.zeros((n,)) + xopt = np.ones((n,)) + g = np.array([1.0, -1.0]) + a = np.array([-2.0, -2.0]) + b = np.array([1.0, 2.0]) + H = np.zeros((n, n)) + proj = lambda x: p_box(x, a, b) + delta = 5.0 + c = 3.0 # may want to max instead + x = ctrsbox_geometry(xbase, xopt, c, g, H, a, b, [proj], delta) + xtrue = np.array([1.0, -2.0]) + print("x = ", x) + print("xtrue = ", xtrue) + self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step') + + +class TestGeomWithHessianCDFO(unittest.TestCase): + def runTest(self): + n = 3 + c = -1.0 + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) + Delta = 5.0 / 12.0 + xbase = np.zeros((n,)) + xopt = np.zeros((n,)) + sl = -1e20 * np.ones((n,)) + su = 1e20 * np.ones((n,)) + proj = lambda x: p_box(x, sl, su) + x = ctrsbox_geometry(xbase, xopt, c, g, H, sl, su, [proj], Delta) + xtrue = np.array([-1.0 / 3.0, 0.0, -0.25]) + # print(x) + # print(xtrue) + self.assertTrue(np.allclose(x, xtrue, atol=5e-2), "Wrong step") + + +class TestGeomWithHessian2CDFO(unittest.TestCase): + def runTest(self): + n = 3 + c = 1.0 # changed this value to force max rather than min + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) + Delta = 5.0 / 12.0 + xbase = np.zeros((n,)) + xopt = np.zeros((n,)) + sl = -1e20 * np.ones((n,)) + su = 1e20 * np.ones((n,)) + proj = lambda x: p_box(x, sl, su) + x = ctrsbox_geometry(xbase, xopt, c, g, H, sl, su, [proj], Delta) + xtrue = np.array([0.25, 0.0, 1.0 / 3.0]) # max solution + # print(x) + # print(xtrue) + self.assertTrue(np.allclose(x, xtrue, atol=1e-3), "Wrong step") + + +class TestUncInternalCDFO(unittest.TestCase): + def runTest(self): + n = 3 + xbase = np.zeros((n,)) + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) + Delta = 2.0 + xopt = np.ones((n,)) # trying nonzero (since bounds inactive) + sl = xopt-3*Delta * np.ones((n,)) + su = xopt+3*Delta * np.ones((n,)) + proj = lambda x: p_box(x, sl, su) + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [proj], Delta) + true_d = np.array([-1.0, 0.0, -0.5]) + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt(g, H, Delta) + self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved') + self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew') + + +class TestUncBdryCDFO(unittest.TestCase): + def runTest(self): + n = 3 + xbase = np.zeros((n,)) + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) + Delta = 5.0 / 12.0 + xopt = np.zeros((n,)) + sl = xopt - 3 * Delta * np.ones((n,)) + su = xopt + 3 * Delta * np.ones((n,)) + proj = lambda x: p_box(x, sl, su) + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [proj], Delta) + true_d = np.array([-1.0 / 3.0, 0.0, -0.25]) + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt(g, H, Delta) + self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved') + self.assertTrue(np.allclose(gnew, g + H.dot(d)), 'Wrong gnew') + + +class TestUncHardCDFO(unittest.TestCase): + def runTest(self): + n = 3 + xbase = np.zeros((n,)) + g = np.array([0.0, 0.0, 1.0]) + H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]) + Delta = sqrt(2.0) + xopt = np.zeros((n,)) + sl = xopt - 3 * Delta * np.ones((n,)) + su = xopt + 3 * Delta * np.ones((n,)) + proj = lambda x: p_box(x, sl, su) + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [proj], Delta) + true_d = np.array([1.0, 0.0, -1.0]) # non-unique solution + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt(g, H, Delta) + self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved') + self.assertTrue(np.allclose(gnew, g + H.dot(d)), 'Wrong gnew') + + +class TestConInternalCDFO(unittest.TestCase): + def runTest(self): + n = 3 + xbase = np.zeros((n,)) + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) + Delta = 2.0 + xopt = np.ones((n,)) # trying nonzero (since bounds inactive) + sl = xopt + np.array([-0.5, -10.0, -10.0]) + su = xopt + np.array([10.0, 10.0, 10.0]) + proj = lambda x: p_box(x, sl, su) + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [proj], Delta) + true_d = np.array([-1.0, 0.0, -0.5]) + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt_box(g, H, Delta, sl-xopt, su-xopt) + self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved') + self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew') + + +class TestConBdryCDFO(unittest.TestCase): + def runTest(self): + n = 3 + xbase = np.ones((n,)) + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) + Delta = 5.0 / 12.0 + xopt = np.zeros((n,)) + sl = xopt + np.array([-0.3, -0.01, -0.1]) + su = xopt + np.array([10.0, 1.0, 10.0]) + proj = lambda x: p_box(x, xbase + sl, xbase + su) # xbase != 0, adjust projections accordingly + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [proj], Delta) # proj=duplicate of sl, su + true_d = np.array([-1.0 / 3.0, 0.0, -0.25]) + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt_box(g, H, Delta, sl - xopt, su - xopt) + self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved') + self.assertTrue(np.max(np.abs(gnew - g - H.dot(d))) < 1e-10, 'Wrong gnew') + + +class TestBoxBallInternalCDFO(unittest.TestCase): + def runTest(self): + n = 3 + xbase = np.zeros((n,)) + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) + Delta = 2.0 + xopt = np.ones((n,)) # trying nonzero (since bounds inactive) + sl = xopt + np.array([-0.5, -10.0, -10.0]) + su = xopt + np.array([10.0, 10.0, 10.0]) + boxproj = lambda x: p_box(x, sl, su) + ballproj = lambda x: p_ball(x, xopt, 5) + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [ballproj], Delta) + true_d = np.array([-0.5, 0.0, -0.5]) + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + self.assertTrue(est_min <= true_min + 1e-3, 'Sufficient decrease not achieved') + + +class TestBoxBallBdryCDFO(unittest.TestCase): + def runTest(self): + n = 3 + g = np.array([1.0, 0.0, 1.0]) + H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) + Delta = 5.0 / 12.0 + xbase = np.zeros((n,)) + xopt = np.zeros((n,)) + sl = xopt + np.array([-0.3, -0.01, -0.1]) + su = xopt + np.array([10.0, 1.0, 10.0]) + boxproj = lambda x: p_box(x, sl, su) + ballproj = lambda x: p_ball(x, xopt, 0.25) + d, gnew, _crvmin = ctrsbox(xbase, xopt, g, H, sl, su, [ballproj], Delta) + true_d = np.array([-0.22913085, 0.0, -0.09999527]) + est_min = model_value(g, H, d) + true_min = model_value(g, H, true_d) + self.assertTrue(est_min <= true_min + 1e-3, 'Sufficient decrease not achieved') \ No newline at end of file diff --git a/pybobyqa/trust_region.py b/pybobyqa/trust_region.py index 183cf63..16fc078 100644 --- a/pybobyqa/trust_region.py +++ b/pybobyqa/trust_region.py @@ -9,7 +9,21 @@ s.t. ||d|| <= delta sl <= xopt + d <= su The other outputs: gnew is the gradient of the model at d, and crvmin has -information about the curvature of the model at the solution. +information about the curvature of the model at the solution: +- If ||d||=delta, then crvmin = 0 +- If d is constrained in all directions by the box constraints, then crvmin = -1 +- Otherwise, crvmin > 0 is the smallest positive curvature seen in the Hessian, min_{k} (dk^T H dk / ||dk||^2) for iterates dk + +For problems with general convex constraints, we have an alternative function + d, gnew, crvmin = ctrsbox(xbase, xopt, g, H, sl, su, projections, delta) +which solves the subproblem + min_{d} g'*d + 0.5*d'*H*d + s.t. ||d|| <= delta + sl <= xopt + d <= su + xbase + xopt + d in the intersection of all convex sets C with proj_{C} in the list 'projections' +The outputs are the same as trsbox, but without the negative case for crvmin. +This version is solved using projected gradient descent; see Chapter 10 of +A. Beck, First-Order Methods in Optimization. SIAM, 2017. Notes ---- @@ -53,10 +67,10 @@ USE_FORTRAN = False -from .util import sumsq, model_value +from .util import sumsq, model_value, dykstra, pball, pbox -__all__ = ['trsbox', 'trsbox_geometry'] +__all__ = ['trsbox', 'trsbox_geometry', 'ctrsbox', 'ctrsbox_geometry'] ZERO_THRESH = 1e-14 @@ -400,3 +414,98 @@ def trsbox_geometry(xbase, c, g, H, lower, upper, Delta, use_fortran=USE_FORTRAN return xbase + smin else: return xbase + smax + + +def ctrsbox(xbase, xopt, g, H, sl, su, projections, delta, dykstra_max_iters=100, dykstra_tol=1e-10, gtol=1e-8): + if projections is None or len(projections) == 0: + return trsbox(xopt, g, H, sl, su, delta) + + n = xopt.size + assert xopt.shape == (n,), "xopt has wrong shape (should be vector)" + assert xbase.shape == (n,), "xbase and xopt has wrong shape (should be vector)" + assert g.shape == (n,), "g and xopt have incompatible sizes" + assert len(H.shape) == 2, "H must be a matrix" + assert H.shape == (n, n), "H and xopt have incompatible sizes" + if not np.allclose(H, H.T): + # Enforce symmetry + H = 0.5 * (H + H.T) + warnings.warn("Trust-region solver: fixing non-symmetric Hessian", RuntimeWarning) + assert sl.shape == (n,), "sl and xopt have incompatible sizes" + assert su.shape == (n,), "su and xopt have incompatible sizes" + assert delta > 0.0, "delta must be strictly positive" + + # Get full list of required projections (i.e. including TR constraint and box constraints) + proj_tr = lambda w: pball(w, xbase + xopt, delta) + proj_box = lambda w: pbox(w, xbase + sl, xbase + su) + P = list(projections) # make a copy of the projections list + P.append(proj_tr) + P.append(proj_box) + + # Compute the joint projection into all constraints, but using increments from xopt + def proj(d0): + p = dykstra(P, xbase + xopt + d0, max_iter=dykstra_max_iters, tol=dykstra_tol) + # we want the step only, so we subtract xbase+xopt + # from the new point: proj(xk+d) - xk + return p - xopt - xbase + + # Compute Lipschitz constant of quadratic objective, L >= ||H||_2 + # Stepsize for projected GD will be Lk=L + L = np.linalg.norm(H) # use L = ||H||_F >= ||H|_2 as valid L-smooth constant + L = max(L, delta / np.linalg.norm(g)) # another upper bound; if L~0 then will take steps (1/L)*g, and don't want to go beyond trust-region + + MAX_LOOP_ITERS = 100 * n ** 2 + + d = np.zeros((n,)) + gnew = g.copy() + crvmin = -1.0 + + # projected GD loop + for ii in range(MAX_LOOP_ITERS): + s = proj(d - (1 / L) * gnew) - d # new step is dnew = d + s + + # take the step + d += s + gnew += H.dot(s) + + # update CRVMIN + crv = np.dot(H.dot(s), s) / sumsq(s) if sumsq(s) >= ZERO_THRESH else crvmin + crvmin = min(crvmin, crv) if crvmin != -1.0 else crv + + # exit condition + if np.linalg.norm(s) <= gtol: + break + + # Lastly, ensure the explicit bounds are hard-enforced + if np.linalg.norm(d) > delta: + d *= delta / np.linalg.norm(d) + d = np.maximum(np.minimum(xopt + d, su), sl) - xopt # does not increase ||d|| + gnew = g + H.dot(d) + + if np.linalg.norm(d) >= delta - ZERO_THRESH: + crvmin = 0.0 + return d, gnew, crvmin + + +def ctrsbox_geometry(xbase, xopt, c, g, H, lower, upper, projections, Delta, dykstra_max_iters=100, dykstra_tol=1e-10, gtol=1e-8): + # Given a Lagrange polynomial defined by: L(x) = c + g' * (x - xopt) + 0.5*(x-xopt)*H*(x-xopt) + # Maximise |L(x)| in the feasible region + trust region - that is, solve: + # max_x abs(c + g' * (x - xopt) + 0.5*(x-xopt)*H*(x-xopt)) + # s.t. lower <= x <= upper + # ||x-xopt|| <= Delta + # xbase+x in the intersection of all convex sets C with proj_{C} in the list 'projections' + # Setting s = x-xbase (or x = xopt + s), this is equivalent to: + # max_s abs(c + g' * s + 0.5*s*H*s) + # s.t. lower <= xopt + s <= upper + # ||s|| <= Delta + # xbase + xopt + s in the intersection of all convex sets C with proj_{C} in the list 'projections' + if projections is None or len(projections) == 0: + return trsbox_geometry(xopt, g, H, lower, upper, Delta) + + smin, gmin, crvmin = ctrsbox(xbase, xopt, g, H, lower, upper, projections, Delta, + dykstra_max_iters=dykstra_max_iters, dykstra_tol=dykstra_tol, gtol=gtol) # minimise L(x) + smax, gmax, crvmax = ctrsbox(xbase, xopt, -g, -H, lower, upper, projections, Delta, + dykstra_max_iters=dykstra_max_iters, dykstra_tol=dykstra_tol, gtol=gtol) # maximise L(x) + if abs(c + model_value(g, H, smin)) >= abs(c + model_value(g, H, smax)): # take largest abs value + return xopt + smin + else: + return xopt + smax \ No newline at end of file diff --git a/pybobyqa/util.py b/pybobyqa/util.py index cf5df10..bed86e8 100644 --- a/pybobyqa/util.py +++ b/pybobyqa/util.py @@ -31,7 +31,8 @@ __all__ = ['sumsq', 'eval_objective', 'model_value', 'random_orthog_directions_within_bounds', - 'random_directions_within_bounds', 'apply_scaling', 'remove_scaling'] + 'random_directions_within_bounds', 'apply_scaling', 'remove_scaling', + 'dykstra', 'pball', 'pbox'] module_logger = logging.getLogger(__name__) @@ -205,3 +206,49 @@ def remove_scaling(x_scaled, scaling_changes): return x_scaled shift, scale = scaling_changes return shift + x_scaled * scale + + +def dykstra(P, x0, max_iter=100, tol=1e-10): + # Dykstra's algorithm for computing the projection of x0 into the intersection + # of several convex sets, each with its own projection operator. + # For more details, including the robust termination condition, see + # E. G. Birgin, M. Raydan. Robust Stopping Criteria for Dykstra's Algorithm. + # SIAM J. Scientific Computing, 26:4 (2005), pp. 1405-1414. + + # Here, x0 is the point to project, and P is a list of projection functions, + # i.e. proj_{ith set}(x) = P[i](x) + x = x0.copy() + p = len(P) + y = np.zeros((p, x0.shape[0])) + + n = 0 + cI = float('inf') + while n < max_iter and cI >= tol: + cI = 0.0 + for i in range(p): + # Update iterate + prev_x = x.copy() + x = P[i](prev_x - y[i,:]) + + # Update increment + prev_y = y[i, :].copy() + y[i, :] = x - (prev_x - prev_y) + + # Stop condition + cI += np.linalg.norm(prev_y - y[i, :])**2 + + n += 1 + + return x + + +def pball(x, c, r): + # Projection operator for a Euclidean ball with center c and radius r + # i.e. pball(x, c, r) = proj_{B(c,r)}(x) + return c + r/max(np.linalg.norm(x-c), r) * (x-c) + + +def pbox(x, l, u): + # Projection operator for box constraints, l <= x <= u + # i.e. pbox(x, c, r) = proj_{[l,u]}(x) + return np.minimum(np.maximum(x, l), u) \ No newline at end of file