.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "tutorial/sellar.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_tutorial_sellar.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_tutorial_sellar.py:


======================
Introduction to Condor
======================

.. GENERATED FROM PYTHON SOURCE LINES 8-29

We wanted to have an API that looks as much like a mathematical description as
possible with as little distraction from programming cruft as possible. For example,
an arbitrary system of equations like from Sellar [sellar]_,

.. math::
   \begin{align}
   y_{1}&=x_{0}^{2}+x_{1}+x_{2}-0.2\,y_{2} \\
   y_{2}&=\sqrt{y_{1}}+x_{0}+x_{1}
   \end{align}

should be writable as

.. code-block:: python

     y1 == x[0] ** 2 + x[1] + x[2] - 0.2 * y2
     y2 == y1**0.5 + x[0] + x[1]

Of course, in both the mathematical and programmatic description, the source of each
symbol must be defined. In an engineering memo, we might say "where :math:`y_1,y_2`
are the variables to solve and :math:`x \in \mathbb{R}^3` parameterizes the system of
equations," which suggests the API for an algebraic system of equations as

.. GENERATED FROM PYTHON SOURCE LINES 29-40

.. code-block:: Python


    import condor

    class Coupling(condor.AlgebraicSystem):
        x = parameter(shape=3)
        y1 = variable(initializer=1.)
        y2 = variable(initializer=1.)

        residual(y1 == x[0] ** 2 + x[1] + x[2] - 0.2 * y2)
        residual(y2 == y1**0.5 + x[0] + x[1])








.. GENERATED FROM PYTHON SOURCE LINES 41-43

which can be evaluated by instantiating the model with numerical values for the
parameters:

.. GENERATED FROM PYTHON SOURCE LINES 43-46

.. code-block:: Python


    coupling = Coupling([5., 2., 1])








.. GENERATED FROM PYTHON SOURCE LINES 47-50

Once the model is finished running, the model *binds* the numerical results from the
iterative solver to the named *element* and *field* attributes on the instance. That
is, elements of fields accessible directly:

.. GENERATED FROM PYTHON SOURCE LINES 50-53

.. code-block:: Python


    print(coupling.y1, coupling.y2)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    [25.58830237] [12.05848815]




.. GENERATED FROM PYTHON SOURCE LINES 54-55

Fields are bound as dataclasses

.. GENERATED FROM PYTHON SOURCE LINES 55-59

.. code-block:: Python


    print(coupling.variable)






.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    CouplingVariable(y1=array([25.58830237]), y2=array([12.05848815]))




.. GENERATED FROM PYTHON SOURCE LINES 60-75

Models can be used recursively, building up more sophisticated models by *embedding*
models within another. However, system encapsulation is enforced so only elements from
input and output fields are accessible after the model has been defined. For example,
we may wish to optimize Sellar's algebraic system of equations. Mathematically, we can
define the optimization as

.. math::
   \begin{aligned}
   \operatorname*{minimize}_{x \in \mathbb{R}^3} &  &  & x_{2}^{2}+x_{1}+y_{1}+e^{-y_{2}} \\
   \text{subject to} &  &  & 3.16\le y_{1}\\
    &  &  & y_{2}\le24.0
   \end{aligned}

where :math:`y_1` and :math:`y_2` are the solution to the system of algebraic
equations described above. In condor, we can write this as

.. GENERATED FROM PYTHON SOURCE LINES 75-87

.. code-block:: Python


    from condor.backend import operators as ops

    class Sellar(condor.OptimizationProblem):
        x = variable(shape=3, lower_bound=0, upper_bound=10)
        coupling = Coupling(x)
        y1, y2 = coupling

        objective = x[2]**2 + x[1] + y1 + ops.exp(-y2)
        constraint(y1 >= 3.16)
        constraint(24. >= y2)








.. GENERATED FROM PYTHON SOURCE LINES 88-90

As with the system of algebraic equations, we can numerically solve this optimization
problem by providing an initial value for the variables and instantiating the model.

.. GENERATED FROM PYTHON SOURCE LINES 90-94

.. code-block:: Python


    Sellar.set_initial(x=[5,2,1])
    sellar = Sellar()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    This is Ipopt version 3.14.11, running with linear solver MUMPS 5.4.1.

    Number of nonzeros in equality constraint Jacobian...:        0
    Number of nonzeros in inequality constraint Jacobian.:        6
    Number of nonzeros in Lagrangian Hessian.............:        6

    Total number of variables............................:        3
                         variables with only lower bounds:        0
                    variables with lower and upper bounds:        3
                         variables with only upper bounds:        0
    Total number of equality constraints.................:        0
    Total number of inequality constraints...............:        2
            inequality constraints with only lower bounds:        1
       inequality constraints with lower and upper bounds:        0
            inequality constraints with only upper bounds:        1

    iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
       0  2.8588308e+01 0.00e+00 9.61e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
       1  2.5032242e+01 0.00e+00 9.60e+00  -1.0 1.90e+03    -  4.74e-03 1.12e-03f  1
       2  1.6557725e+01 0.00e+00 4.45e+00  -1.0 3.81e+01    -  1.00e+00 5.42e-01f  1
       3  1.5031940e+01 0.00e+00 3.92e+00  -1.0 6.87e+00    -  1.00e+00 1.15e-01f  1
       4  4.5491414e+00 0.00e+00 6.34e-01  -1.0 6.04e+00    -  1.00e+00 1.00e+00f  1
       5  3.4782092e+00 0.00e+00 5.17e-02  -1.7 9.99e-01    -  1.00e+00 8.87e-01f  1
       6  3.2369916e+00 0.00e+00 2.15e-03  -1.7 2.29e-01    -  1.00e+00 1.00e+00f  1
       7  3.1867988e+00 0.00e+00 3.56e-05  -3.8 5.09e-02    -  1.00e+00 1.00e+00h  1
       8  3.1845411e+00 0.00e+00 8.40e-07  -3.8 2.55e-02    -  1.00e+00 1.00e+00h  1
       9  3.1836276e+00 0.00e+00 3.86e-07  -5.7 1.34e-02    -  1.00e+00 1.00e+00h  1
    iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
      10  3.1834622e+00 0.00e+00 8.19e-08  -5.7 6.64e-03    -  1.00e+00 1.00e+00h  1
      11  3.1834161e+00 0.00e+00 1.91e-08  -5.7 3.20e-03    -  1.00e+00 1.00e+00h  1
      12  3.1834029e+00 0.00e+00 3.60e-09  -5.7 1.39e-03    -  1.00e+00 1.00e+00h  1
      13  3.1833947e+00 0.00e+00 7.48e-10  -8.6 6.21e-04    -  1.00e+00 1.00e+00h  1
      14  3.1833939e+00 0.00e+00 2.48e-11  -8.6 1.15e-04    -  1.00e+00 1.00e+00h  1
      15  3.1833939e+00 0.00e+00 3.38e-14  -8.6 4.25e-06    -  1.00e+00 1.00e+00h  1

    Number of Iterations....: 15

                                       (scaled)                 (unscaled)
    Objective...............:   3.1833939181332549e+00    3.1833939181332549e+00
    Dual infeasibility......:   3.3805821765621465e-14    3.3805821765621465e-14
    Constraint violation....:   0.0000000000000000e+00    0.0000000000000000e+00
    Variable bound violation:   7.4470968355807926e-09    7.4470968355807926e-09
    Complementarity.........:   2.5421361853922688e-09    2.5421361853922688e-09
    Overall NLP error.......:   2.5421361853922688e-09    2.5421361853922688e-09


    Number of objective function evaluations             = 16
    Number of objective gradient evaluations             = 16
    Number of equality constraint evaluations            = 0
    Number of inequality constraint evaluations          = 16
    Number of equality constraint Jacobian evaluations   = 0
    Number of inequality constraint Jacobian evaluations = 16
    Number of Lagrangian Hessian evaluations             = 15
    Total seconds in IPOPT                               = 0.062

    EXIT: Optimal Solution Found.




.. GENERATED FROM PYTHON SOURCE LINES 95-97

The resulting object will have a dot-able data structure with the bound results,
including the embedded ``Coupling`` model:

.. GENERATED FROM PYTHON SOURCE LINES 97-102

.. code-block:: Python


    print("objective value:", sellar.objective) # scalar value
    print(sellar.constraint) # field
    print(sellar.coupling.y1) # embedded-model element





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    objective value: 3.183393918133255
    SellarConstraint(Sellar_constraint_0=array([3.16]), Sellar_constraint_1=array([3.75527764]))
    [3.15999998]




.. GENERATED FROM PYTHON SOURCE LINES 103-105

.. rubric:: References
.. [sellar] Sellar, R., Batill, S., and Renaud, J., "Response Surface Based, Concurrent Subspace Optimization for Multidisciplinary System Design," 1996. https://doi.org/10.2514/6.1996-714


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 0.154 seconds)


.. _sphx_glr_download_tutorial_sellar.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: sellar.ipynb <sellar.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: sellar.py <sellar.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: sellar.zip <sellar.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_