Source code for omlt.block
"""OmltBlock.
The omlt.block module contains the implementation of the OmltBlock class. This
class is used in combination with a formulation object to construct the
necessary constraints and variables to represent ML models.
Example:
.. code-block:: python
import tensorflow.keras as keras
from omlt import OmltBlock
from omlt.neuralnet import FullSpaceNNFormulation
from omlt.io import load_keras_sequential
nn = keras.models.load_model(keras_fname)
net = load_keras_sequential(nn)
m = pyo.ConcreteModel()
m.neural_net_block = OmltBlock()
m.neural_net_block.build_formulation(FullSpaceNNFormulation(net))
m.obj = pyo.Objective(expr=(m.neural_net_block.outputs[2]-4.0)**2)
status = pyo.SolverFactory('ipopt').solve(m, tee=True)
pyo.assert_optimal_termination(status)
"""
import pyomo.environ as pyo
from pyomo.core.base.block import BlockData, declare_custom_block
[docs]
@declare_custom_block(name="OmltBlock")
class OmltBlockData(BlockData):
def __init__(self, component):
super().__init__(component)
self.__formulation = None
self.__input_indexes = None
self.__output_indexes = None
[docs]
def _setup_inputs_outputs(self, *, input_indexes, output_indexes):
"""Setup inputs and outputs.
This function should be called by the derived class to create the
inputs and outputs on the block
Args:
input_indexes : list
list of indexes (can be tuples) defining the set to be used for
the input variables
output_indexes : list
list of indexes (can be tuples) defining the set to be used for
the input variables
"""
self.__input_indexes = input_indexes
self.__output_indexes = output_indexes
self.inputs_set = pyo.Set(initialize=input_indexes)
self.inputs = pyo.Var(self.inputs_set, initialize=0)
self.outputs_set = pyo.Set(initialize=output_indexes)
self.outputs = pyo.Var(self.outputs_set, initialize=0)
[docs]
def build_formulation(self, formulation):
"""Build formulation.
Call this method to construct the constraints (and possibly
intermediate variables) necessary for the particular neural network
formulation. The formulation object can be accessed later through the
"formulation" attribute.
Parameters
----------
formulation : instance of _PyomoFormulation
see, for example, FullSpaceNNFormulation
"""
if not formulation.input_indexes:
msg = (
"OmltBlock must have at least one input to build a formulation. "
f"{formulation} has no inputs."
)
raise ValueError(msg)
if not formulation.output_indexes:
msg = (
"OmltBlock must have at least one output to build a formulation. "
f"{formulation} has no outputs."
)
raise ValueError(msg)
self._setup_inputs_outputs(
input_indexes=list(formulation.input_indexes),
output_indexes=list(formulation.output_indexes),
)
self.__formulation = formulation
# tell the formulation that it is working on this block (self)
self.__formulation._set_block(self)
# tell the formulation object to construct the necessary models
self.__formulation._build_formulation()