14. Import and Export of Optimization Problems

This notebook demonstrates how an optimization problem setup in MASSpy can be exported for use with other optimization solvers. This notebook is based on the Optlang API documentation and the COBRApy FAQ How do I generate an LP file from a COBRA model?

Variables, constraints, objectives, and a name (if provided) are imported/exported through this method; however, solver configuration options are not.

[1]:
try:
    import simplejson as json
except ImportError:
    import json

import cobra
from optlang import Model as OptModel

import mass.example_data
# Print list of available solvers
print(list(cobra.util.solver.solvers))
['glpk_exact', 'glpk', 'gurobi', 'scipy']

14.1. Using Optlang

To facilitate the formation of the mathematical optimization problem, MASSpy utilizes the Optlang python package [JCS17]. As stated in the documentation:

  1. Optlang provides a common interface to a series of optimization tools, so different solver backends can be changed in a transparent way.

  2. Optlang takes advantage of the symbolic math library SymPy to allow objective functions and constraints to be easily formulated from symbolic expressions of variables.

  3. Optlang interfaces with all solvers through importable python modules (read more here).

The following optimization solvers are supported:

However, there are times where it would be preferrable to utilize other solvers and/or change programming environments in the process of setting up and performing optimizations. Fortunately, Optlang provides class methods for importing and exporting the optimization problem in both LP and JSON-compatible formats. The examples below demonstrate how the JSON format is utilized with MASSpy objects to facilitate the transference of optimization problems.

It is generally NOT recommended to import optimization problems directly into the solvers, as the corresponding MASSpy objects are bypassed and therefore do not have any values updated to match the new state of the solver.

14.1.1. Importing and Exporting with LP files

LP formulations of models can be used in conjunction with Optlang facilitate the exchange of optimization problems. Note the following:

  1. Importing and exporting using LP formulations can change variable and constraint identifiers

  2. LP formulations do not work with the scipy solver interface.

[2]:
# Start with a fresh model
model = mass.example_data.create_example_model("textbook")
# Change the bounds for demonstration purposes
model.variables.HEX1.lb, model.variables.HEX1.ub = (-123, 456)
print(model.variables["HEX1"])
Set parameter Username
-123 <= HEX1 <= 456

14.1.2. Exporting an LP file

For all solver interfaces in Optlang, the str representation of an optlang.interface.Model is the LP formulation of the problem.

To export the optimization problem into a file:

[3]:
with open("problem.lp", "w") as file:
    file.write(str(model.solver))

Alternatively, the optlang.interface.Model.to_lp() method can be used, but note that variable and constraint identifiers may be changed.

14.1.3. Importing an LP file

The optlang.interface.Model.from_lp() method can be used to import an LP formulation of an optimization problem.

[4]:
# Use new model to demonstrate how bounds change
model = mass.example_data.create_example_model("textbook")
print("Before: " + str(model.variables["HEX1"]))

# Load problem from JSON file
with open("problem.lp") as file:
    model._solver = OptModel.from_lp(file.read())
print("After: " + str(model.variables["HEX1"]))
Before: 0 <= HEX1 <= 1000.0
After: -123.0 <= HEX1 <= 456.0

14.1.4. Importing and Exporting with JSON files

[5]:
# Start with a fresh model
model = mass.example_data.create_example_model("textbook")
# Change the bounds for demonstration purposes
model.variables.HEX1.lb, model.variables.HEX1.ub = (-654, 321)
print(model.variables.HEX1)
-654 <= HEX1 <= 321

14.1.4.1. Exporting using JSON

Problems formulated in Optlang can be exported using the optlang.interface.Model.to_json class method. First, the to_json class method exports a JSON compatible dict containing the variables, constraints, objectives, and an optional name from the optlang.interface.Model. The dict is then passed to json.dump to save the optimization problem as a JSON file.

To export the optimization problem into a file:

[6]:
with open("problem.json", "w") as file:
    json.dump(model.solver.to_json(), file)

14.1.4.2. Importing using JSON

Problems can be imported into Optlang using the optlang.interface.Model.from_json class method. First, a JSON compatible dict is loaded from a file using the json.load. The dict is then passed to the from_json class method to load the variables, constraints, objectives, and an optional name into the optlang.interface.Model (imported as “OptModel” in this example”).

To import the optimization problem from a file:

[7]:
# Use new model to demonstrate how bounds change
model = mass.example_data.create_example_model("textbook")
print("Before: " + str(model.variables.HEX1))

# Load problem from JSON file
with open("problem.json") as file:
    model._solver = OptModel.from_json(json.load(file))
print("After: " + str(model.variables.HEX1))
Before: 0 <= HEX1 <= 1000.0
After: -654 <= HEX1 <= 321

14.1.5. Adding a solver interface

For an optimization solver that does not currently have an interface, consider adding a solver interface.