Skip to content

Commit

Permalink
Merge branch 'main' into add_minimal_print
Browse files Browse the repository at this point in the history
  • Loading branch information
crecine authored May 1, 2024
2 parents 6e20906 + a988404 commit 5da7f9e
Show file tree
Hide file tree
Showing 50 changed files with 603 additions and 526 deletions.
10 changes: 5 additions & 5 deletions .github/environment.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
dependencies:
# build
- python >=3.8
- numpy >=1.16
- python >=3.9
- numpy >=1.21
- ipopt
- swig
- meson >=0.60
- meson >=1.3.2
- compilers
- pkg-config
- pip
Expand All @@ -13,6 +13,6 @@ dependencies:
# testing
- parameterized
- testflo
- scipy >1.2
- scipy >=1.7
- mdolab-baseclasses >=1.3.1
- sqlitedict >=1.6
- sqlitedict >=1.6
4 changes: 2 additions & 2 deletions .github/test_real.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ set -e

# all tests should pass on the private image
# except for the Intel image, where IPOPT is not available
if [[ $IMAGE == "private" ]] && [[ $COMPILERS != "intel" ]]; then
if [[ $IMAGE == "private" ]]; then
EXTRA_FLAGS='--disallow_skipped'
fi

cd tests
# we have to copy over the coveragerc file to make sure it's in the
# same directory where codecov is run
cp ../.coveragerc .
testflo --pre_announce -v --coverage --coverpkg pyoptsparse $EXTRA_FLAGS
testflo --pre_announce --disallow_deprecations -v --coverage --coverpkg pyoptsparse $EXTRA_FLAGS
4 changes: 2 additions & 2 deletions .github/workflows/windows-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jobs:
- uses: actions/checkout@v2
- uses: conda-incubator/setup-miniconda@v2
with:
python-version: 3.8
mamba-version: "*"
python-version: 3.9
miniforge-variant: Mambaforge
channels: conda-forge,defaults
channel-priority: strict
activate-environment: pyos-build
Expand Down
2 changes: 1 addition & 1 deletion .isort.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import_heading_stdlib=Standard Python modules
import_heading_thirdparty=External modules
import_heading_firstparty=First party modules
import_heading_localfolder=Local modules
skip_glob=**__init__.py,**setup.py
skip_glob=**__init__.py,setup.py
known_local_folder=testing_utils
17 changes: 17 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

build:
os: ubuntu-22.04
tools:
python: "3.11"

sphinx:
configuration: doc/conf.py

python:
install:
- requirements: doc/requirements.txt
7 changes: 7 additions & 0 deletions doc/advancedFeatures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Because the hot start process will store all the previous "restarted" iterations

Time limit (for SNOPT only)
---------------------------

.. note::

Since SNOPT 7.7, the user should rely on the ``Time Limit`` SNOPT option instead of the ``timeLimit`` argument of the ``Optimizer`` instance to set the maximum optimization time.


The :ref:`optimizer` class in pyOptSparse has an attribute used to set the maximum allowable wall time for optimizations using SNOPT.
The code will exit gracefully when such time limit is reached.
This feature is particularly useful when running a time-constrained job, as in the case of most HPC systems.
Expand All @@ -79,5 +85,6 @@ Note that the attribute takes the maximum wall time *in seconds* as an integer n
It will NOT interrupt an ongoing function or sensitivity evaluation.
If your function evaluations are expensive, you should be more conservative when setting the ``timeLimit`` option for it to be effective.


.. Clean Optimization Termination
.. ------------------------------
2 changes: 1 addition & 1 deletion doc/contribute.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ To install these dependencies, type

.. prompt:: bash

pip install sphinx numpydoc sphinx-rtd-theme
pip install sphinx numpydoc sphinx-rtd-theme sphinx_mdolab_theme

Testing
-------
Expand Down
17 changes: 11 additions & 6 deletions doc/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ Conda packages are available on ``conda-forge`` and can be installed via
conda install -c conda-forge pyoptsparse

This would install pyOptSparse with the built-in optimizers, as well as IPOPT.
If you wish to use optimizers not packaged by ``conda``, e.g. SNOPT, then you must build the package from source.
If you wish to use optimizers not packaged by ``conda``, e.g. SNOPT, then you must either build the package from source or use the installation script below.
If you have the SNOPT precompiled library available, it is possible to dynamically link it to pyOptSparse following the instructions on the :ref:`SNOPT installation page<snopt_by_conda>`.

Using an installation script
----------------------------
You can build and install pyOptsparse using a `Python script <https://github.com/OpenMDAO/build_pyoptsparse/>`_ developed by the OpenMDAO team.
For usage, see the instruction on the README of the repo.

This script is particularly useful for installing :ref:`IPOPT<ipopt>` and its dependencies.
It can also support SNOPT installation if you have access to the SNOPT source code.

Building from source
--------------------
Expand All @@ -26,17 +35,13 @@ pyOptSparse has the following dependencies:

Please make sure these are installed and available for use.
In order to use NSGA2, SWIG (v1.3+) is also required, which can be installed via the package manager.
If those optimizers are not needed, then you do not need to install SWIG.
Simply comment out the corresponding lines in ``pyoptsparse/pyoptsparse/setup.py`` so that they are not compiled.
The corresponding lines in ``pyoptsparse/pyoptsparse/__init__.py`` must be commented out as well.

Python dependencies are automatically handled by ``pip``, so they do not need to be installed separately.
The only exception is ``numpy``, which is required as part of the build process and therefore must be present before installing.

.. note::
* In Linux, the python header files (``python-dev``) are also required.
* **We do not support operating systems other than Linux.**
For macOS users, the conda package may work out of the box if you do not need any non-default optimizers.
Also, the installation script by OpenMDAO likely works on macOS.
For Windows users, a conda package is on the way, if it's not already in the repos.
This comes with the same disclaimer as the macOS conda package.
Alternatively, follow the :ref:`conda build instructions<conda build instruction>` below as this will work on any platform.
Expand Down
12 changes: 2 additions & 10 deletions doc/optimizers/IPOPT.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _ipopt:

IPOPT
=====
IPOPT (Interior Point OPTimizer) is an open source interior point optimizer, designed for large-scale nonlinear optimization.
Expand Down Expand Up @@ -68,16 +70,6 @@ Here we explain a basic setup using MUMPS as the linear solver, together with ME

#. Now clean build pyOptSparse. Verify that IPOPT works by running the relevant tests.

.. note::

To get IPOPT working with pyOptSparse when using another linear solver, several things must be changed.

#. The ``setup.py`` file located in ``pyoptsparse/pyIPOPT`` must be updated accordingly.
In particular, the ``libraries=`` line must be changed to reflect the alternate linear solver.
For example, for HSL you need to replace ``coinmumps`` and ``coinmetis`` with ``coinhsl``.
#. The option ``linear_solver`` in the options dictionary must be changed.
The default value can be changed in ``pyIPOPT.py`` so that this option does not need to be manually set in every run script.

Options
-------
Please refer to the `IPOPT website <https://coin-or.github.io/Ipopt/OPTIONS.html>`__ for complete listing of options.
Expand Down
4 changes: 2 additions & 2 deletions doc/optimizers/NLPQLP.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ solved. The line search can be performed with respect to two
alternative merit functions, and the Hessian approximation is updated
by a modified BFGS formula.

NLPQLP is a proprietary software, which can be obtained `here <http://www.ai7.uni-bayreuth.de/nlpqlp.htm>`_.
The latest version supported is v4.2.2.
NLPQLP is a proprietary software, which can be obtained `here <https://www.schittkowski.de/numericalsoftware.php>`_.
The supported versions are v4.2.2 and v5.0.3, but other versions may work.

Options
-------
Expand Down
22 changes: 22 additions & 0 deletions doc/optimizers/SNOPT.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,35 @@ BFGS quasi-Newton update.

Installation
------------

Building from source
********************
SNOPT is available for purchase `here
<http://www.sbsi-sol-optimize.com/asp/sol_snopt.htm>`_. Upon purchase, you should receive a zip file. Within the zip file, there is a folder called ``src``. To use SNOPT with pyoptsparse, paste all files from ``src`` except snopth.f into ``pyoptsparse/pySNOPT/source``.

From v2.0 onwards, only SNOPT v7.7.x is officially supported.
To use pyOptSparse with previous versions of SNOPT, please checkout release v1.2.
We currently test v7.7.7 and v7.7.1.

Installation by conda
*********************

.. _snopt_by_conda:

When installing via conda, all pyoptsparse binaries are pre-compiled and installed as part of the package.
However, the `snopt` binding module cannot be included as part of the package due to license restrictions.

If you are installing via conda and would like to use SNOPT, you will need to build the `snopt` binding module on your own, and inform `pyoptsparse` that it should use that library.

Suppose you have built the binding file, producing ``snopt.cpython-310.so``, living in the folder ``~/snopt-bind``.

To use this module, set the environment variable, ``PYOPTSPARSE_IMPORT_SNOPT_FROM``, e.g.:

.. code-block:: bash
PYOPTSPARSE_IMPORT_SNOPT_FROM=~/snopt-bind/
This will attempt to load the ``snopt`` binding module from ``~/snopt-bind``. If the module cannot be loaded from this path, a warning will be raised at import time, and an error will be raised if attempting to run the SNOPT optimizer.

Options
-------
Expand Down
26 changes: 22 additions & 4 deletions doc/optimizers/SNOPT_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,28 @@ Total real workspace:
User-specified values are not overwritten.
Save major iteration variables:
desc: >
This option is unique to the Python wrapper, and takes a list of values which can be saved at each iteration to the History file.
This specifies the list of major iteration variables to be stored in the history file.
``Hessian``, ``slack``, ``lambda`` and ``condZHZ`` are also supported.
desc: |
This option is unique to the Python wrapper, and takes a list of values which can be saved at each major iteration to the History file.
The possible values are
- ``Hessian``
- ``slack``
- ``lambda``
- ``nS``
- ``BSwap``
- ``maxVi``
- ``penalty_vector``
In addition, a set of default parameters are saved to the history file and cannot be changed. These are
- ``nMajor``
- ``nMinor``
- ``step``
- ``feasibility``
- ``optimality``
- ``merit``
- ``condZHZ``
- ``penalty``
Return work arrays:
desc: >
Expand Down
1 change: 0 additions & 1 deletion examples/hs071_zero_return.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def objfunc(xdict):


def sens(xdict, funcs):

x0 = xdict["x0"][0]
x1 = xdict["x1"][0]
x2 = xdict["x2"][0]
Expand Down
2 changes: 2 additions & 0 deletions examples/tp109.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Solves Schittkowski's TP109 constraint problem.
min 3.0*x1+1.*10**(-6)*x1**3+0.522074*10**(-6)*x2**3+2.0*x2
s.t. -(x4-x3+0.550) <= 0
-(x3-x4+0.550) <= 0
-(2.25*10**(+6)-x1**2-x8**2) <= 0
Expand All @@ -16,6 +17,7 @@
-0.55 <= xi <= 0.55, i = 3,4
196.0 <= xi <= 252.0, i = 5,6,7
-400.0 <= xi <= 800.0, i = 8,9
where a = 50.176
b = np.sin(0.25)
c = np.cos(0.25)
Expand Down
6 changes: 3 additions & 3 deletions pyoptsparse/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
__version__ = "2.9.0"
__version__ = "2.11.0"

from .pyOpt_history import History
from .pyOpt_variable import Variable
from .pyOpt_gradient import Gradient
from .pyOpt_constraint import Constraint
from .pyOpt_objective import Objective
from .pyOpt_optimization import Optimization
from .pyOpt_optimizer import Optimizer
from .pyOpt_optimizer import OPT
from .pyOpt_optimizer import Optimizer, OPT, Optimizers
from .pyOpt_solution import Solution

# Now import all the individual optimizers
from .pySNOPT.pySNOPT import SNOPT
Expand Down
8 changes: 1 addition & 7 deletions pyoptsparse/postprocessing/OptView.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class Display(OVBaseClass):
"""

def __init__(self, histList, outputDir, figsize):

# Initialize the Tkinter object, which will contain all graphical
# elements.
self.root = Tk.Tk()
Expand Down Expand Up @@ -214,7 +213,6 @@ def orig_plot(self, dat, val, values, a, i=0):
self.error_display("No bounds information")

def color_plot(self, dat, labels, a):

# If the user wants the non-constraint colormap, use viridis
if self.var_color.get():
cmap = plt.get_cmap("viridis")
Expand Down Expand Up @@ -254,7 +252,6 @@ def color_plot(self, dat, labels, a):

# Loop through the data sets selected by the user
for label in labels:

# Get the subarray for this particular data set and record its size
subarray = np.array(dat[label]).T
sub_size = subarray.shape[0]
Expand Down Expand Up @@ -438,7 +435,6 @@ def plot_selected(self, values, dat):

# Plot on individual vertical axes
elif self.var.get() == 1 and not fail:

# Set window sizing parameters for when additional axes are
# added
n = len(values)
Expand Down Expand Up @@ -553,7 +549,6 @@ def plot_selected(self, values, dat):
# Plot color plots of rectangular pixels showing values,
# especially useful for constraints
elif self.var.get() == 3 and not fail:

# Remove options that aren't relevant
self.c4.grid_forget()
self.c5.grid_forget()
Expand Down Expand Up @@ -666,7 +661,6 @@ def update_graph(self):
self.plot_selected(values, dat)

def set_mask(self):

if self.var_mask.get():
self.func_data = self.func_data_major
self.var_data = self.var_data_major
Expand Down Expand Up @@ -751,7 +745,7 @@ def save_tec(self):

num_vars = len(keys)
num_iters = len(dat[keys[0]])
full_data = np.arange(num_iters, dtype=np.float_).reshape(num_iters, 1)
full_data = np.arange(num_iters, dtype=np.float64).reshape(num_iters, 1)
var_names = ["Iteration"]
for key in keys:
small_data = np.asarray(dat[key])
Expand Down
Loading

0 comments on commit 5da7f9e

Please sign in to comment.