## Pyomo Basics

A typical Pyomo application involves the creation of at least two Pyomo objects from the following classes:

* **ConcreteModel()**  A python object representing the optimization problem to be solved.
* **SolverFactory()** A python object representing the mathematical progamming software to be used for calculating a solution.

There are a number of of open-source and commercial solvers that can be used with Pyomo. This simple structure allows one to test and find solvers suited to a particular application.  

A model, in turn, is composed of additional objects used to specify a problem. A minimal set of classes is needed to create useful models. These classes are:

* **Var()** Objects representing variables determined in the course of solving a particular problem.
* **Objective()** An object denoting the problem objective function that is to be either minimized or maximized.
* **Constraint()** Objects representing problem constraints.

The following cell presents a typical example.

## Example: Linear Production Model with Constraints

The mathematical formulation of a simple linear production model is given by

\begin{align}
\max_{x,y \geq 0} &\ 40\ x + 30\ y  & \mbox{objective}\\
\mbox{subject to:}\qquad \\
x & \leq 40  & \mbox{demand constraint} \\
x + y & \leq 80  & \mbox{labor A constraint} \\
2x + y & \leq 100 & \mbox{labor B constraint}
\end{align}

where $x$ and $y$ are the rates of production (in units per week) for two products.

#### Step 1. Import Pyomo.

The first step in any Pyomo project is to import relevant components of the Pyomo library. This can be done with the following python statement.

    from pyomo.environ import *
    
#### Step 2. Create the model object.

Pyomo provides two distinct methods to create models. Here we use `ConcreteModel()` to create a model instance which is appropriate when all of the data needed to complete the model is avaiable at the current time.

    model = ConcreteModel()
    
The Python variable `model` stores the model instance. This could be any valid Python variable name.
    
#### Step 3. Add the Decision Variables, Objective, and Constraints to the model object.

The first major component of a Pyomo model are decision variables which are added as fields to `model`. In the case we name the fields `model.x` and `model.y` corresponding to $x$ and $y$ in the process model. The Python class `Var()` is used to specify these as real numbers that must be greater than or equal to zero.

    model.x = Var(domain=NonNegativeReals)
    model.y = Var(domain=NonNegativeReals)
    
As we will see in other examples, the `domain` can specify other types of decision variables including reals, integers, and booleans.

The objective is specified as an algebraic expression involving the decision variables. Here we store the objective in `model.profit`, and use the optional keyword `sense` to specify a maximization problem.

    model.profit = Objective(expr = 40*model.x + 30*model.y, sense=maximize)

Constraints are added as fields to the model, each constraint created using the `Constraint()` class. The constraints are specified using the `expr` keywork in the form of linear algebraic expressions of the decision variables.

    model.demand = Constraint(expr = model.x <= 40)
    model.laborA = Constraint(expr = model.x + model.y <= 80)
    model.laborB = Constraint(expr = 2*model.x + model.y <= 100)


#### Step 4.  Create a solver object and solve.

The Pyomo libary includes a `SolverFactory()` class used to specify a solver. In this case, because the problem is a linear programming problem, we use the `glpk` solver. 

    results = SolverFactory('glpk').solve(model)
    results.write()
    if results.solver.status == 'ok':
        model.pprint()
    
The `solve()` method attempts to solve the model using the specified solver, and returns `results` which can be inspected to see if, in fact, a solution was found. If a solution is found, then `model` will have a pretty-print method `pprint()` that creates a summary of the problem solution.

#### Step 5. Display the solution.

Most applications will require access to specific components of the model. If a solution is found, the model will include methods with the same name as the fields created above, and which can be used to access solution values.

    print('Profit = ', model.profit())

    print('\nDecision Variables')
    print('x = ', model.x())
    print('y = ', model.y())

    print('\nConstraints')
    print('Demand  = ', model.demand())
    print('Labor A = ', model.laborA())
    print('Labor B = ', model.laborB())


```python
from pyomo.environ import *

# create a model
model = ConcreteModel()

# declare decision variables
model.x = Var(domain=NonNegativeReals)
model.y = Var(domain=NonNegativeReals)

# declare objective
model.profit = Objective(expr = 40*model.x + 30*model.y, sense=maximize)

# declare constraints
model.demand = Constraint(expr = model.x <= 40)
model.laborA = Constraint(expr = model.x + model.y <= 80)
model.laborB = Constraint(expr = 2*model.x + model.y <= 100)

# solve
results = SolverFactory('glpk').solve(model)
results.write()
if results.solver.status:
    model.pprint()

# display solution
print('\nProfit = ', model.profit())

print('\nDecision Variables')
print('x = ', model.x())
print('y = ', model.y())

print('\nConstraints')
print('Demand  = ', model.demand())
print('Labor A = ', model.laborA())
print('Labor B = ', model.laborB())
```

    # ==========================================================
    # = Solver Results                                         =
    # ==========================================================
    # ----------------------------------------------------------
    #   Problem Information
    # ----------------------------------------------------------
    Problem: 
    - Name: unknown
      Lower bound: 2600.0
      Upper bound: 2600.0
      Number of objectives: 1
      Number of constraints: 4
      Number of variables: 3
      Number of nonzeros: 6
      Sense: maximize
    # ----------------------------------------------------------
    #   Solver Information
    # ----------------------------------------------------------
    Solver: 
    - Status: ok
      Termination condition: optimal
      Statistics: 
        Branch and bound: 
          Number of bounded subproblems: 0
          Number of created subproblems: 0
      Error rc: 0
      Time: 0.013679981231689453
    # ----------------------------------------------------------
    #   Solution Information
    # ----------------------------------------------------------
    Solution: 
    - number of solutions: 0
      number of solutions displayed: 0
    2 Var Declarations
        x : Size=1, Index=None
            Key  : Lower : Value : Upper : Fixed : Stale : Domain
            None :     0 :  20.0 :  None : False : False : NonNegativeReals
        y : Size=1, Index=None
            Key  : Lower : Value : Upper : Fixed : Stale : Domain
            None :     0 :  60.0 :  None : False : False : NonNegativeReals
    
    1 Objective Declarations
        profit : Size=1, Index=None, Active=True
            Key  : Active : Sense    : Expression
            None :   True : maximize : 40*x + 30*y
    
    3 Constraint Declarations
        demand : Size=1, Index=None, Active=True
            Key  : Lower : Body : Upper : Active
            None :  -Inf :    x :  40.0 :   True
        laborA : Size=1, Index=None, Active=True
            Key  : Lower : Body  : Upper : Active
            None :  -Inf : x + y :  80.0 :   True
        laborB : Size=1, Index=None, Active=True
            Key  : Lower : Body    : Upper : Active
            None :  -Inf : 2*x + y : 100.0 :   True
    
    6 Declarations: x y profit demand laborA laborB
    
    Profit =  2600.0
    
    Decision Variables
    x =  20.0
    y =  60.0
    
    Constraints
    Demand  =  20.0
    Labor A =  80.0
    Labor B =  100.0


## Python Lists, Sets, Dictionaries, and Iterators

Pyomo is integrated with the Python language, and inherits significant functionality by leveraging the basic data structures of Python. To make the best use of Pyomo, it is important to understand the basics of Python lists, sets, and dictionaries.

### Data in Matrix/Vector Format

The example above used scalar modeling components, `model.x = Var()` and `model.y = Var()`, and each constraint was added as a separate line in the model.  This is fine for small problems with a just a few unknowns, but becomes impractical for larger problems.

Here we repeat the example above, this time using `numpy` arrays to enter the data. An indexed variable `model.x` represents the unknowns, and the constraints are indexed as well. The indices are represented by the Python `range()` statement.


```python
from pyomo.environ import *
import numpy as np

# enter data as numpy arrays
A = np.array([[3, 4], [2, -3]])
b = np.array([26, -11])

# set of row indices
I = range(len(A))

# set of column indices
J = range(len(A.T))

# create a model instance
model = ConcreteModel()

# create x and y variables in the model
model.x = Var(J)

# add model constraints
model.constraints = ConstraintList()
for i in I:
    model.constraints.add(sum(A[i,j]*model.x[j] for j in J) == b[i])

# add a model objective
model.objective = Objective(expr = sum(model.x[j] for j in J))

# create a solver
solver = SolverFactory('glpk')

# solve
solver.solve(model)

# print solutions
for j in J:
    print("x[", j, "] =", model.x[j].value)
```

    x[ 0 ] = 2.0
    x[ 1 ] = 5.0



```python

```

d4f4053152e13cc5526bd877eb3fb2d3dd3ada5f
ipynb
Jupyter Notebook
notebooks/intro/Pyomo_Basics.ipynb
gschivley/ND-Pyomo-Cookbook
7bddccd14eb3044e9d3e7c46999e1c9c29541e16
Apache-2.0
notebooks/intro/Pyomo_Basics.ipynb
gschivley/ND-Pyomo-Cookbook
7bddccd14eb3044e9d3e7c46999e1c9c29541e16
Apache-2.0
notebooks/intro/Pyomo_Basics.ipynb
gschivley/ND-Pyomo-Cookbook
7bddccd14eb3044e9d3e7c46999e1c9c29541e16
Apache-2.0
2018-10-14T16:40:40.000Z
2021-07-20T12:02:29.000Z
Qwen/Qwen-72B
1. YES
2. YES