Creating Constraints

Note

You can download this example as a Jupyter notebook or start it in interactive mode.

Creating Constraints#

Constraints are created and at the same time assigned to the model using the function

model.add_constraints

where model is a linopy.Model instance. Again, we want to understand this function and its argument. So, let’s create a model first.

[1]:
from linopy import Model
import numpy as np
import pandas as pd
import xarray as xr
m = Model()

Given a variable x which has to by lower than 10/3, the constraint would be formulated as

\[x \le \frac{10}{3}\]

or

\[3 x \le 10\]

or

\[x - \frac{3}{10} \le 0\]

of which all formulations can be written out with linopy just like that.

[2]:
x = m.add_variables(name='x')

When applying one of the operators <=, >=, == to the expression, an unassigned constraint is built:

[3]:
con = 3 * x <= 10
con
[3]:
Constraint (unassigned)
-----------------------
+3 x ≤ 10.0

Unasssigned means, it is not yet added to the model. We can inspect the elements of the anonymous constraint:

[4]:
con.lhs
[4]:
LinearExpression
----------------
+3 x
[5]:
con.rhs
[5]:
<xarray.DataArray 'rhs' ()> Size: 8B
array(10.)

We can now add the constraint to the model by passing the unassigned Constraint to the .add_constraint function.

[6]:
c = m.add_constraints(con, name='my-constraint')
c
[6]:
Constraint `my-constraint`
--------------------------
+3 x ≤ 10.0

The same output would be generated if passing lhs, sign and rhs as separate arguments to the function:

[7]:
m.add_constraints(3 * x <= 10, name='the-same-constraint')
[7]:
Constraint `the-same-constraint`
--------------------------------
+3 x ≤ 10.0

Note that the return value of the operation is a Constraint which contains the reference labels to the constraints in the optimization model. Also is redirects to its lhs, sign and rhs, for example we can call

[8]:
c.lhs
[8]:
LinearExpression
----------------
+3 x

to inspect the lhs of a defined constraint.

When moving the constant value to the left hand side in the initialization, it will be pulled to the right hand side as soon as the constraint is defined

[9]:
3 * x - 10
[9]:
LinearExpression
----------------
+3 x - 10
[10]:
3 * x - 10 <= 0
[10]:
Constraint (unassigned)
-----------------------
+3 x ≤ 10.0

Like this, the all defined constraints have a clear separation between variable on the left, and constants on the right.

All constraints are added to the .constraints container from where all assigned constraints can be accessed.

[11]:
m.constraints
[11]:
linopy.model.Constraints
------------------------
 * my-constraint
 * the-same-constraint
[12]:
m.constraints['my-constraint']
[12]:
Constraint `my-constraint`
--------------------------
+3 x ≤ 10.0