Pyomo ModelFactory (модель нескольких подмоделей) Дизайн с ООП - PullRequest
1 голос
/ 07 июня 2019

Я написал модели на pyomo, которые могут корректно решать задачи при вводе с различными типами параметров.Теперь я хочу решить несколько из этих моделей одновременно в рамках задачи оптимизации.Я хотел бы сделать это в подходе ООП без переписывания большого количества кода.Возможно ли это?

Я пробовал многие методы блоков add_component () и del_component () блока, чтобы скопировать атрибуты, но у меня это не получилось.

После импорта инастройка моего решателя

import pyomo.environ as pyo
solver = pyo.SolverFactory('ipopt')

Я создаю класс модели ниже

class Model(pyo.ConcreteModel):
    """
    Model that solves the trivial equation $xy=z$,
        where $x$ is a variable and $y$ and $z$ are parameters.
    """
    def __init__(self, **kwargs):
        """

        :param kwargs: keyword arguments that become attributes of model
        """
        pyo.ConcreteModel.__init__(self)
        self.x = pyo.Var()
        self.y = pyo.Param(initialize=kwargs['y'])
        self.z = pyo.Param(initialize=kwargs['z'])
        self.constr = pyo.Constraint(expr=self.x*self.y==self.z)
        self.obj = pyo.Objective(expr=1.)

Класс модели здесь представляет собой чрезвычайно простую задачу для решения.

Теперь яЯ хочу решить несколько из этих моделей одновременно, используя класс ModelFactory, приведенный ниже.

class ModelFactory(pyo.ConcreteModel):
    """
    class that contains many Model classes and combines them into
        one single pyomo model that can be solved
    """
    def __init__(self, y_params, z_params):
        """

        :param y_params: values for parameters of y values for Model class
        :type y_params: list
        :param z_params: values for parameters of z values for Model class
        :type z_params: list
        """
        pyo.ConcreteModel.__init__(self)

        for i in range(len(y_params)):
            model_instance = Model(y=y_params[i], z=z_params[i])
            objects = list(
                model_instance.component_objects()
            )
            for obj in objects:
                if str(obj) in self.__dict__:
                    # common attributes in pyo.ConcreteModel
                    continue
                # copy and re-name all objects except the objective function
                if not isinstance(obj, pyo.Objective):
                    setattr(self, str(obj) + '_%i'%i , obj)
        self.obj = pyo.Objective(expr=1.)

Я тестирую код с помощью следующего

inst = ModelFactory([0, 4, 3, 2], [100, 22, 4, 2])  # initialize with arbitrary data
    solver.solve(inst, tee=True)

Я получаю ошибки с помощью команды setattr.Одна из ошибок:

This behavior is not supported by Pyomo; components must have a
single owning block (or model), and a component may not appear
multiple times in a block.  If you want to re-name or move this
component, use the block del_component() and add_component() methods.

Возможно ли это сделать, или это чрезвычайно сложно с del_component и add_component?

...