Skip to content

model

Model(name=None, solver=None, solver_env=None, use_var_names=False, sense=None)

The object that holds all the variables, constraints, and the objective.

Parameters:

Name Type Description Default
name Optional[str]

The name of the model. Currently it is not used for much.

None
solver Optional[SUPPORTED_SOLVER_TYPES]

The solver to use. If None, Config.default_solver will be used. If Config.default_solver has not been set (None), Pyoframe will try to detect whichever solver is already installed.

None
solver_env Optional[Dict[str, str]]

Gurobi only: a dictionary of parameters to set when creating the Gurobi environment.

None
use_var_names bool

Whether to pass variable names to the solver. Set to True if you'd like outputs from e.g. Model.write() to be legible. Does not work with HiGHS (see here).

False
sense Union[ObjSense, ObjSenseValue, None]

Either "min" or "max". Indicates whether it's a minmization or maximization problem. Typically, this parameter can be omitted (None) as it will automatically be set when the objective is set using .minimize or .maximize.

None

Examples:

>>> m = pf.Model()
>>> m.X = pf.Variable()
>>> m.my_constraint = m.X <= 10
>>> m
<Model vars=1 constrs=1 objective=False>

Try setting the Gurobi license:

>>> m = pf.Model(solver="gurobi", solver_env=dict(ComputeServer="myserver", ServerPassword="mypassword"))
Traceback (most recent call last):
...
RuntimeError: Could not resolve host: myserver (code 6, command POST http://myserver/api/v1/cluster/jobs)
Source code in src\pyoframe\model.py
def __init__(
    self,
    name: Optional[str] = None,
    solver: Optional[SUPPORTED_SOLVER_TYPES] = None,
    solver_env: Optional[Dict[str, str]] = None,
    use_var_names: bool = False,
    sense: Union[ObjSense, ObjSenseValue, None] = None,
):
    self.poi, self.solver_name = Model.create_poi_model(solver, solver_env)
    self._variables: List[Variable] = []
    self._constraints: List[Constraint] = []
    self.sense = ObjSense(sense) if sense is not None else None
    self._objective: Optional[Objective] = None
    self.var_map = (
        NamedVariableMapper(Variable) if Config.print_uses_variable_names else None
    )
    self.name = name

    self.params = Container(self._set_param, self._get_param)
    self.attr = Container(self._set_attr, self._get_attr)
    self._use_var_names = use_var_names

binary_variables property

Examples:

>>> m = pf.Model()
>>> m.X = pf.Variable(vtype=pf.VType.BINARY)
>>> m.Y = pf.Variable()
>>> len(list(m.binary_variables))
1

integer_variables property

Examples:

>>> m = pf.Model()
>>> m.X = pf.Variable(vtype=pf.VType.INTEGER)
>>> m.Y = pf.Variable()
>>> len(list(m.integer_variables))
1

compute_IIS()

Computes the Irreducible Infeasible Set (IIS) of the model.

Gurobi only

This method only works with the Gurobi solver. Open an issue if you'd like to see support for other solvers.

Examples:

>>> m = pf.Model(solver="gurobi")
>>> m.X = pf.Variable(lb=0, ub=2)
>>> m.Y = pf.Variable(lb=0, ub=2)
>>> m.bad_constraint = m.X >= 3
>>> m.minimize = m.X + m.Y
>>> m.optimize()
>>> m.attr.TerminationStatus
<TerminationStatusCode.INFEASIBLE: 3>
>>> m.bad_constraint.attr.IIS
Traceback (most recent call last):
...
RuntimeError: Unable to retrieve attribute 'IISConstr'
>>> m.compute_IIS()
>>> m.bad_constraint.attr.IIS
True
Source code in src\pyoframe\model.py
@for_solvers("gurobi", "copt")
def compute_IIS(self):
    """
    Computes the Irreducible Infeasible Set (IIS) of the model.

    !!! warning "Gurobi only"
        This method only works with the Gurobi solver. Open an issue if you'd like to see support for other solvers.

    Examples:
        >>> m = pf.Model(solver="gurobi")
        >>> m.X = pf.Variable(lb=0, ub=2)
        >>> m.Y = pf.Variable(lb=0, ub=2)
        >>> m.bad_constraint = m.X >= 3
        >>> m.minimize = m.X + m.Y
        >>> m.optimize()
        >>> m.attr.TerminationStatus
        <TerminationStatusCode.INFEASIBLE: 3>
        >>> m.bad_constraint.attr.IIS
        Traceback (most recent call last):
        ...
        RuntimeError: Unable to retrieve attribute 'IISConstr'
        >>> m.compute_IIS()
        >>> m.bad_constraint.attr.IIS
        True
    """
    self.poi.computeIIS()

convert_to_fixed()

Turns a mixed integer program into a continuous one by fixing all the integer and binary variables to their solution values.

Gurobi only

This method only works with the Gurobi solver. Open an issue if you'd like to see support for other solvers.

Examples:

>>> m = pf.Model(solver="gurobi")
>>> m.X = pf.Variable(vtype=pf.VType.BINARY, lb=0)
>>> m.Y = pf.Variable(vtype=pf.VType.INTEGER, lb=0)
>>> m.Z = pf.Variable(lb=0)
>>> m.my_constraint = m.X + m.Y + m.Z <= 10
>>> m.maximize = 3 * m.X + 2 * m.Y + m.Z
>>> m.optimize()
>>> m.X.solution, m.Y.solution, m.Z.solution
(1, 9, 0.0)
>>> m.my_constraint.dual
Traceback (most recent call last):
...
RuntimeError: Unable to retrieve attribute 'Pi'
>>> m.convert_to_fixed()
>>> m.optimize()
>>> m.my_constraint.dual
1.0

Only works for Gurobi:

>>> m = pf.Model("max", solver="highs")
>>> m.convert_to_fixed()
Traceback (most recent call last):
...
NotImplementedError: Method 'convert_to_fixed' is not implemented for solver 'highs'.
Source code in src\pyoframe\model.py
@for_solvers("gurobi")
def convert_to_fixed(self) -> None:
    """
    Turns a mixed integer program into a continuous one by fixing
    all the integer and binary variables to their solution values.

    !!! warning "Gurobi only"
        This method only works with the Gurobi solver. Open an issue if you'd like to see support for other solvers.

    Examples:
        >>> m = pf.Model(solver="gurobi")
        >>> m.X = pf.Variable(vtype=pf.VType.BINARY, lb=0)
        >>> m.Y = pf.Variable(vtype=pf.VType.INTEGER, lb=0)
        >>> m.Z = pf.Variable(lb=0)
        >>> m.my_constraint = m.X + m.Y + m.Z <= 10
        >>> m.maximize = 3 * m.X + 2 * m.Y + m.Z
        >>> m.optimize()
        >>> m.X.solution, m.Y.solution, m.Z.solution
        (1, 9, 0.0)
        >>> m.my_constraint.dual
        Traceback (most recent call last):
        ...
        RuntimeError: Unable to retrieve attribute 'Pi'
        >>> m.convert_to_fixed()
        >>> m.optimize()
        >>> m.my_constraint.dual
        1.0

        Only works for Gurobi:

        >>> m = pf.Model("max", solver="highs")
        >>> m.convert_to_fixed()
        Traceback (most recent call last):
        ...
        NotImplementedError: Method 'convert_to_fixed' is not implemented for solver 'highs'.
    """
    self.poi._converttofixed()

dispose()

Disposes of the model and cleans up the solver environment.

When using Gurobi compute server, this cleanup will ensure your run is not marked as 'ABORTED'.

Note that once the model is disposed, it cannot be used anymore.

Examples:

>>> m = pf.Model()
>>> m.X = pf.Variable(ub=1)
>>> m.maximize = m.X
>>> m.optimize()
>>> m.X.solution
1.0
>>> m.dispose()
Source code in src\pyoframe\model.py
def dispose(self):
    """
    Disposes of the model and cleans up the solver environment.

    When using Gurobi compute server, this cleanup will
    ensure your run is not marked as 'ABORTED'.

    Note that once the model is disposed, it cannot be used anymore.

    Examples:
        >>> m = pf.Model()
        >>> m.X = pf.Variable(ub=1)
        >>> m.maximize = m.X
        >>> m.optimize()
        >>> m.X.solution
        1.0
        >>> m.dispose()
    """
    env = None
    if hasattr(self.poi, "_env"):
        env = self.poi._env
    self.poi.close()
    if env is not None:
        env.close()

optimize()

Optimize the model using your selected solver (e.g. Gurobi, HiGHS).

Source code in src\pyoframe\model.py
def optimize(self):
    """
    Optimize the model using your selected solver (e.g. Gurobi, HiGHS).
    """
    self.poi.optimize()

write(file_path, pretty=False)

Output the model to a file.

Typical usage includes writing the solution to a .sol file as well as writing the problem to a .lp or .mps file. Set use_var_names in your model constructor to True if you'd like the output to contain human-readable names (useful for debugging).

Parameters:

Name Type Description Default
file_path Union[Path, str]

The path to the file to write to.

required
pretty bool

Only used when writing .sol files in HiGHS. If True, will use HiGH's pretty print columnar style which contains more information.

False
Source code in src\pyoframe\model.py
def write(self, file_path: Union[Path, str], pretty: bool = False):
    """
    Output the model to a file.

    Typical usage includes writing the solution to a `.sol` file as well as writing the problem to a `.lp` or `.mps` file.
    Set `use_var_names` in your model constructor to `True` if you'd like the output to contain human-readable names (useful for debugging).

    Parameters:
        file_path:
            The path to the file to write to.
        pretty:
            Only used when writing .sol files in HiGHS. If `True`, will use HiGH's pretty print columnar style which contains more information.
    """
    file_path = Path(file_path)
    file_path.parent.mkdir(parents=True, exist_ok=True)
    kwargs = {}
    if self.solver_name == "highs":
        if self.use_var_names:
            self.params.write_solution_style = 1
        kwargs["pretty"] = pretty
    self.poi.write(str(file_path), **kwargs)