Special Constraints#

Integer Cuts#

Integer cuts can be of many types, these assign a bound to the number of a particular component by some logic.

See example below, where .x accesses the reporting variable (binary) related to the Aspect

The binary equals 1 if the Aspect is non-zero, and 0 otherwise

from energia import Model, Resource, Process

m = Model()
m.r1 = Resource(demand_min=100)
m.r2 = Resource(consume_max=2500)
m.r3 = Resource(consume_max=2000)

m.p1 = Process(m.r1 == -3 * m.r2 - 4 * m.r3)
m.p1.operate == True
m.p2 = Process(m.r1 == -5 * m.r2 - 2 * m.r3)
m.p2.operate == True
m.integer_cut1 = m.p1.capacity.x + m.p2.capacity.x <= 1
m.locate(m.p1,m.p2)
⚖   Initiated r1 balance in (l0, t0)                                        ⏱ 0.0001 s
🔗  Bound [≥] r1 release in (l0, t0)                                         ⏱ 0.0011 s
⚖   Initiated r2 balance in (l0, t0)                                        ⏱ 0.0001 s
🔗  Bound [≤] r2 consume in (l0, t0)                                         ⏱ 0.0006 s
⚖   Initiated r3 balance in (l0, t0)                                        ⏱ 0.0001 s
🔗  Bound [≤] r3 consume in (l0, t0)                                         ⏱ 0.0005 s
💡  Assumed p1 capacity unbounded in (l0, t0)                                ⏱ 0.0001 s
🔗  Bound [≤] p1 operate in (l0, t0)                                         ⏱ 0.0001 s
💡  Assumed p1 operate bounded by capacity in (l0, t0)                       ⏱ 0.0004 s
⚖   Updated r1 balance with produce(r1, l0, t0, operate, p1)                ⏱ 0.0001 s
🔗  Bound [=] r1 produce in (l0, t0)                                         ⏱ 0.0006 s
⚖   Updated r2 balance with expend(r2, l0, t0, operate, p1)                 ⏱ 0.0001 s
🔗  Bound [=] r2 expend in (l0, t0)                                          ⏱ 0.0005 s
⚖   Updated r3 balance with expend(r3, l0, t0, operate, p1)                 ⏱ 0.0001 s
🔗  Bound [=] r3 expend in (l0, t0)                                          ⏱ 0.0006 s
🏭  Operating streams introduced for p1 in l0                                ⏱ 0.0028 s
🏗   Construction streams introduced for p1 in l0                            ⏱ 0.0000 s
🌍  Located p1 in l0                                                         ⏱ 0.0044 s
💡  Assumed p2 capacity unbounded in (l0, t0)                                ⏱ 0.0001 s
🔗  Bound [≤] p2 operate in (l0, t0)                                         ⏱ 0.0001 s
💡  Assumed p2 operate bounded by capacity in (l0, t0)                       ⏱ 0.0005 s
⚖   Updated r1 balance with produce(r1, l0, t0, operate, p2)                ⏱ 0.0001 s
🔗  Bound [=] r1 produce in (l0, t0)                                         ⏱ 0.0008 s
⚖   Updated r2 balance with expend(r2, l0, t0, operate, p2)                 ⏱ 0.0001 s
🔗  Bound [=] r2 expend in (l0, t0)                                          ⏱ 0.0007 s
⚖   Updated r3 balance with expend(r3, l0, t0, operate, p2)                 ⏱ 0.0001 s
🔗  Bound [=] r3 expend in (l0, t0)                                          ⏱ 0.0007 s
🏭  Operating streams introduced for p2 in l0                                ⏱ 0.0034 s
🏗   Construction streams introduced for p2 in l0                            ⏱ 0.0000 s
🌍  Located p2 in l0                                                         ⏱ 0.0048 s
m.show(True, category='General')

Mathematical Program for Program(m)



Index Sets

\[\displaystyle {locations} = \{ {{l0}} \}\]
\[\displaystyle {t0} = \{ {{{{t0}_{0}}}} \}\]
\[\displaystyle {resources} = \{ {{r1}, {r2}, {r3}} \}\]
\[\displaystyle {processes} = \{ {{p1}, {p2}} \}\]



s.t.

General Constraints

\[\displaystyle [6]\text{ }{\mathbf{{\breve{{cap}}}}}_{{p1},{l0},{{{t0}_{0}}}} + {\mathbf{{\breve{{cap}}}}}_{{p2},{l0},{{{t0}_{0}}}} - 1.0 \leq 0\]
\[\displaystyle [7]\text{ }{\mathbf{{\breve{{cap}}}}}_{{p2},{l0},{{{t0}_{0}}}} + {\mathbf{{\breve{{cap}}}}}_{{p2},{l0},{{{t0}_{0}}}} - 1.0 \leq 0\]

Operations Involving Multiple Samples#

The come in handy if the user wants to deal with operations of Samples.

Take the example where the minimum consumption needs to be minimized across the board in the above example

m.total_consumption = sum(m.consume)

The function itself can also be optimized

m.total_consumption.opt()
📝  Generated Program(m).mps                                                 ⏱ 0.0012 s
Set parameter Username
Academic license - for non-commercial use only - expires 2026-08-01
Warning: duplicate nonzeros for column X6 and row C4.
Read MPS format model from file Program(m).mps
Reading time = 0.00 seconds
PROGRAM(M): 16 rows, 15 columns, 31 nonzeros
📝  Generated gurobipy model. See .formulation                               ⏱ 0.0066 s
Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (win64 - Windows 11.0 (26100.2))

CPU model: 13th Gen Intel(R) Core(TM) i7-13700, instruction set [SSE2|AVX|AVX2]
Thread count: 16 physical cores, 24 logical processors, using up to 24 threads

Optimize a model with 16 rows, 15 columns and 31 nonzeros
Model fingerprint: 0x0622c6ae
Variable types: 13 continuous, 2 integer (2 binary)
Coefficient statistics:
  Matrix range     [1e+00, 5e+00]
  Objective range  [1e+00, 1e+00]
  Bounds range     [1e+00, 1e+00]
  RHS range        [1e+00, 3e+03]
Presolve removed 16 rows and 15 columns
Presolve time: 0.00s
Presolve: All rows and columns removed

Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)
Thread count was 1 (of 24 available processors)

Solution count 1: 700 

Optimal solution found (tolerance 1.00e-04)
Best objective 7.000000000000e+02, best bound 7.000000000000e+02, gap 0.0000%
📝  Generated Solution object for Program(m). See .solution                  ⏱ 0.0001 s
✅  Program(m) optimized using gurobi. Display using .output()               ⏱ 0.0137 s