molfoundry.FlowModel#

class molfoundry.FlowModel(dg)#

Bases: object

A Gurobi integer-flow model over a derivation graph.

On construction it creates one integer firing-count variable per hyperedge (reaction) and records the per-vertex stoichiometry. The caller then declares inflow / outflow on individual vertices, optionally sets a custom objective (the default minimizes the total number of reactions), and solves.

The mass-balance constraints – produced - consumed + inflow - outflow = 0 for every vertex – are added automatically the first time the model is solved, so inflow / outflow must be declared before solving.

The underlying gurobipy.Model is exposed via model, and the gurobipy module via gp, so the objective and any extra constraints can be built directly.

Example:

from molfoundry import FlowModel

fm = FlowModel(dg)
fm.add_in_flow(dg.findVertex(a), 6, 6)
fm.add_in_flow(dg.findVertex(water), 1, 1)
for v in dg.vertices:
        fm.add_out_flow(v, 0, None)
sink = dg.findVertex(product)
fm.add_out_flow(sink, 1, None)
# Minimize reactions while maximizing the sink outflow.
fm.set_objective(
        fm.gp.quicksum(fm.reaction_var(e) for e in dg.edges)
        - 1000 * fm.out_flow_var(sink)
)
for solution in fm.enumerate_solutions(100):
        if solution.is_realizable():
                ...
Parameters:

dg (DG)

property model#

The underlying gurobipy.Model, for arbitrary customization.

reaction_var(edge)#

The integer firing-count variable for edge.

Parameters:

edge (HyperEdge)

Return type:

Any

in_flow_var(vertex)#

The inflow variable for vertex, or None if none was added.

Parameters:

vertex (Vertex)

Return type:

Any | None

out_flow_var(vertex)#

The outflow variable for vertex, or None if none was added.

Parameters:

vertex (Vertex)

Return type:

Any | None

add_in_flow(vertex, lo=0, hi=None)#

Declare an inflow (source) on vertex bounded to [lo, hi].

hi=None leaves the inflow unbounded above. Returns the created variable (also reachable later via in_flow_var()).

Parameters:
Return type:

Any

add_out_flow(vertex, lo=0, hi=None)#

Declare an outflow (sink) on vertex bounded to [lo, hi].

hi=None leaves the outflow unbounded above. Returns the created variable (also reachable later via out_flow_var()).

Parameters:
Return type:

Any

set_objective(expr, sense=ObjectiveSense.MINIMIZE)#

Set the model objective; sense is ObjectiveSense.MINIMIZE (the default) or ObjectiveSense.MAXIMIZE.

Parameters:
Return type:

None

optimum(time_limit=None)#

Solve for a single optimal flow, or None if the model is infeasible.

Parameters:

time_limit (float | None)

Return type:

FlowSolution | None

enumerate_solutions(max_num_solutions, time_limit=None)#

Enumerate up to max_num_solutions best flows, best objective first.

With max_num_solutions == 1 this is a plain optimize (PoolSearchMode 0); otherwise it uses PoolSearchMode 2 (systematic n-best) so the pool is a guaranteed set of the best solutions. The pool is sorted by objective and de-duplicated before yielding.

Yields:

FlowSolution objects, best (lowest) objective first.

Parameters:
  • max_num_solutions (int)

  • time_limit (float | None)

Return type:

Iterator[FlowSolution]

dispose()#

Release the underlying Gurobi model and environment.

Return type:

None