# Tutorial¶

## Overview¶

Pyomo includes a diverse set of optimization capabilities for formulating and analyzing optimization models. Pyomo supports the formulation and analysis of mathematical models for complex optimization applications. This capability is commonly associated with algebraic modeling languages (AMLs), which support the description and analysis of mathematical models with a high-level language. Although most AMLs are implemented in custom modeling languages, Pyomo’s modeling objects are embedded within Python, a full-featured high-level programming language that contains a rich set of supporting libraries.

Pyomo has also proven an effective framework for developing high-level optimization and analysis tools. It is easy to develop Python scripts that use Pyomo as a part of a complex analysis workflow. Additionally, Pyomo includes a variety of optimization solvers for stochastic programming, dynamic optimization with differential algebraic equations, mathematical programming with equilibrium conditions, and more! Increasingly, Pyomo is integrating functionality that is normally associated with an optimization solver library.

## Modeling Components¶

The primary modeling components defined by Pyomo are Param, Var, Constraint, Objective, Set, and Block. Each of these may be indexed.

>>> import pyomo.environ as pe
>>> m = pe.ConcreteModel()
>>> m.a = pe.Set(initialize=[1, 2, 3])
>>> m.x = pe.Var(m.a, initialize=0, bounds=(-10,10))
>>> m.y = pe.Var(m.a)
>>> def c_rule(m, i):
...     return m.x[i] >= m.y[i]
>>> m.c = pe.Constraint(m.a, rule=c_rule)
>>> m.c.pprint()
c : Size=3, Index=a, Active=True
Key : Lower : Body        : Upper : Active
1 :  -Inf : y[1] - x[1] :   0.0 :   True
2 :  -Inf : y[2] - x[2] :   0.0 :   True
3 :  -Inf : y[3] - x[3] :   0.0 :   True


The index specifies the set of allowable members of the component. In the case of Var, the constructor will automatically create variables for each member of the index. Other components (like Constraint<pyomo.core.base.constraint.Constraint>) leverage a rule, which is called by the constructor for every member of the index, the return value of which dictates whether or not to create the corresponding modeling object. Beyond facilitating the construction of large structured models, discrete indexing sets provide error checking, ensuring that requested modeling objects are allowed by the index:

>>> m.z = pe.Var()
>>> m.c[4] = m.x[1] == 5 * m.z
Traceback (most recent call last):
...
KeyError: "Index '4' is not valid for indexed component 'c'"


This helps prevent many common mistakes. To add new objects to a component, the new index must first be added to the underlying index set:

>>> m.a.add(4)
>>> m.c[4] = m.x[1] == 5 * m.z


However, it is sometimes useful to allow a more flexible form of indexing using non-iterable sets. For example, an indexed component may be made to behave like a dictionary by indexing it using the Any set. This set admits any hashable object as a member.

>>> m.c2 = pe.Constraint(pe.Any)
>>> m.c2[1] = m.x[1] == 5 * m.z
>>> m.c2[8] = m.x[2] == m.z * m.y[2]
>>> m.c2.pprint()
c2 : Size=2, Index=Any, Active=True
Key : Lower : Body            : Upper : Active
1 :   0.0 :      x[1] - 5*z :   0.0 :   True
8 :   0.0 : x[2] - z * y[2] :   0.0 :   True


Note

It it important that the component construction not iterate over the non-iterable set. For most components, simply omitting the rule= argument is sufficient. Var requires the dense=False argument so that the constructor does not iterate over the non-iterable set.

>>> m.v = pe.Var(pe.Any, dense=False)
>>> m.c2[2] = m.v[1] + m.v[2] == 0
>>> m.v.pprint()
v : Size=2, Index=Any
Key : Lower : Value : Upper : Fixed : Stale : Domain
1 :  None :  None :  None : False :  True :  Reals
2 :  None :  None :  None : False :  True :  Reals
>>> m.c2.pprint()
c2 : Size=3, Index=Any, Active=True
Key : Lower : Body            : Upper : Active
1 :   0.0 :      x[1] - 5*z :   0.0 :   True
2 :   0.0 :     v[1] + v[2] :   0.0 :   True
8 :   0.0 : x[2] - z * y[2] :   0.0 :   True


The following illustrates how to use Any with Blocks.

>>> m.b = pe.Block(pe.Any)
>>> m.b['foo1'].x = pe.Var()
>>> m.b['foo1'].y = pe.Var()
>>> m.b['foo1'].c = pe.Constraint(expr=m.b['foo1'].x >= 5*m.b['foo1'].y)
>>> m.b[1].x = pe.Var()


## Pyomo Command¶

>>> print('Hello World')
Hello World