用Pyomo和类解决DAE问题

时间:2017-07-20 15:22:30

标签: class pyomo

我正在努力解决汽车问题。 首先,我有一个汽车问题的原始代码:

# Ampl Car Example
#
# Shows how to convert a minimize final time optimal control problem
# to a format pyomo.dae can handle by removing the time scaling from
# the ContinuousSet.
#
# min tf
# dxdt = 0
# dvdt = a-R*v^2
# x(0)=0; x(tf)=L
# v(0)=0; v(tf)=0
# -3<=a<=1

from pyomo.environ import *
from pyomo.dae import *

m = ConcreteModel()

m.R = Param(initialize=0.001) #  Friction factor
m.L = Param(initialize=100.0) #  Final position

m.tau = ContinuousSet(initialize=[0.0, 0.80, 1.0])  # Unscaled time
m.time = Var(m.tau)  # Scaled time
m.tf = Var()
m.x = Var(m.tau,bounds=(0,None))
m.v = Var(m.tau,bounds=(0,None))
m.a = Var(m.tau, bounds=(-3.0,1.0),initialize=0)

m.dtime = DerivativeVar(m.time)
m.dx = DerivativeVar(m.x)
m.dv = DerivativeVar(m.v)

m.obj = Objective(expr=m.tf)

def _ode1(m,i):
    if i == 0 :
        return Constraint.Skip
    return m.dx[i] == m.tf * m.v[i]
m.ode1 = Constraint(m.tau, rule=_ode1)

def _ode2(m,i):
    if i == 0 :
        return Constraint.Skip
    return m.dv[i] == m.tf*(m.a[i] - m.R*m.v[i]**2)
m.ode2 = Constraint(m.tau, rule=_ode2)

def _ode3(m,i):
    if i == 0:
        return Constraint.Skip
    return m.dtime[i] == m.tf
m.ode3 = Constraint(m.tau, rule=_ode3)

def _init(m):
    yield m.x[0] == 0
    yield m.x[1] == m.L
    yield m.v[0] == 0
    yield m.v[1] == 0
    yield m.time[0] == 0
m.initcon = ConstraintList(rule=_init)

discretizer = TransformationFactory('dae.collocation')
discretizer.apply_to(m,ncp=1, scheme='LAGRANGE-RADAU')

solver = SolverFactory('ipopt')
solver.solve(m, tee=True)

print("final time = %6.2f" %(value(m.tf)))

现在,我想用班级来表达汽车,然后我可以实例化两辆汽车。 所以我这样写:

from pyomo.environ import *
from pyomo.dae import *

m = ConcreteModel()

class Car():
    def __init__(self,friction):

        self.friction = friction

        self.R = Param(initialize = self.friction)  # Friction factor

        self.tau = ContinuousSet(bounds=(0, 1))  # Unscaled time
        self.time = Var(self.tau)  # Scaled time
        self.tf = Var()
        self.x = Var(self.tau, bounds=(0, None), initialize=0)
        self.v = Var(self.tau, bounds=(0, None))
        self.a = Var(self.tau, bounds=(-3.0, 1.0), initialize=0)

        self.dtime = DerivativeVar(self.time)
        self.dx = DerivativeVar(self.x)
        self.dv = DerivativeVar(self.v)

        def _ode1(m, i):
            if i == 0:
                return Constraint.Skip
            return self.dx[i] == m.tf * self.v[i]
        self.ode1 = Constraint(self.tau, rule=_ode1)

        def _ode2(m, i):
            if i == 0:
                return Constraint.Skip
           return self.dv[i] == m.tf * (self.a[i] - self.R * self.v[i] ** 2)

        self.ode2 = Constraint(self.tau, rule=_ode2)

        def _ode3(m, i):
            if i == 0:
                return Constraint.Skip
            return self.dtime[i] == m.tf

        self.ode3 = Constraint(self.tau, rule=_ode3)

m.car1 = Car(0.001)

m.obj = Objective(expr=m.car1.tf)

def _init(m):
    yield m.car1.x[0] == 0
    yield m.car1.x[1] == 100
    yield m.car1.v[0] == 0
    yield m.car1.v[1] == 0
    yield m.car1.time[0] == 0
m.car1.initcon = ConstraintList(rule=_init)

discretizer = TransformationFactory('dae.finite_difference')
discretizer.apply_to(m, nfe=10, scheme='BACKWARD')

solver = SolverFactory('ipopt')
solver.solve(m, tee=True)

print("final time = %6.2f" % (value(m.car1.tf)))

然而,我明白了:

Traceback (most recent call last):
File "D:/pyo/pyomoceshi/ceshi3/car/classcar3.py", line 79, in <module>
solver.solve(m, tee=True)
File "D:\python\m\lib\site-packages\pyomo\opt\base\solvers.py", line 582, in solve
self._presolve(*args, **kwds)
File "D:\python\m\lib\site-packages\pyomo\opt\solver\shellcmd.py", line 196, in _presolve
OptSolver._presolve(self, *args, **kwds)
File "D:\python\m\lib\site-packages\pyomo\opt\base\solvers.py", line 661, in _presolve
**kwds)
File "D:\python\m\lib\site-packages\pyomo\opt\base\solvers.py", line 729, in _convert_problem
**kwds)
File "D:\python\m\lib\site-packages\pyomo\opt\base\convert.py", line 110, in convert_problem
problem_files, symbol_map = converter.apply(*tmp, **tmpkw)
File "D:\python\m\lib\site-packages\pyomo\solvers\plugins\converter\model.py", line 164, in apply
io_options=io_options)
File "D:\python\m\lib\site-packages\pyomo\core\base\block.py", line 1646, in write
io_options)
File "D:\python\m\lib\site-packages\pyomo\repn\plugins\ampl\ampl_.py", line 357, in __call__
include_all_variable_bounds=include_all_variable_bounds)
File "D:\python\m\lib\site-packages\pyomo\repn\plugins\ampl\ampl_.py", line 783, in _print_model_NL
list(self_varID_map[id(var)] for var in ampl_repn._linear_vars),
File "D:\python\m\lib\site-packages\pyomo\repn\plugins\ampl\ampl_.py", line 783, in <genexpr>
list(self_varID_map[id(var)] for var in ampl_repn._linear_vars),
KeyError: 68767416L

我想知道如何解决它或使用其他方式。

1 个答案:

答案 0 :(得分:1)

以下是您的脚本的工作版本。我改变了一些东西,以便有一个Car函数返回代表汽车的Pyomo Block而不是Car类。通过拥有一个Car类,你实际上是在尝试创建一个Block的子类并遇到一些与之相关的微妙挑战。您可以查看博文here以获取更多信息。我做的第二个更改是在初始条件的声明中,我将ConstraintList的名称从m.car1.initcon更改为m.car1_initcon。区别在于您是希望ConstraintList存在于car1块还是模型上。在您的代码中,&#39; dot&#39;在名称中意味着你试图将它放在car1 Block上,但规则中产生的约束与模型相关。我更改了名称以解决这种不一致。

from pyomo.environ import *
from pyomo.dae import *

m = ConcreteModel()

def Car(model, friction):

    def construct_car_block(b):

        b.R = Param(initialize = friction)  # Friction factor
        b.tau = ContinuousSet(bounds=(0, 1))  # Unscaled time
        b.time = Var(b.tau)  # Scaled time
        b.tf = Var()
        b.x = Var(b.tau, bounds=(0, None), initialize=0)
        b.v = Var(b.tau, bounds=(0, None))
        b.a = Var(b.tau, bounds=(-3.0, 1.0), initialize=0)

        b.dtime = DerivativeVar(b.time)
        b.dx = DerivativeVar(b.x)
        b.dv = DerivativeVar(b.v)

        def _ode1(b, i):
            if i == 0:
                return Constraint.Skip
            return b.dx[i] == b.tf * b.v[i]
        b.ode1 = Constraint(b.tau, rule=_ode1)

        def _ode2(b, i):
            if i == 0:
                return Constraint.Skip
            return b.dv[i] == b.tf * (b.a[i] - b.R * b.v[i] ** 2)
        b.ode2 = Constraint(b.tau, rule=_ode2)

        def _ode3(m, i):
            if i == 0:
                return Constraint.Skip
            return b.dtime[i] == b.tf
        b.ode3 = Constraint(b.tau, rule=_ode3)

    return Block(rule=construct_car_block)

m.car1 = Car(m, friction=0.001)

m.obj = Objective(expr=m.car1.tf)

def _init(m):
    yield m.car1.x[0] == 0
    yield m.car1.x[1] == 100
    yield m.car1.v[0] == 0
    yield m.car1.v[1] == 0
    yield m.car1.time[0] == 0
m.car1_initcon = ConstraintList(rule=_init)

discretizer = TransformationFactory('dae.finite_difference')
discretizer.apply_to(m, nfe=15, scheme='BACKWARD')

solver = SolverFactory('ipopt')
solver.solve(m, tee=True)

print("final time = %6.2f" % (value(m.car1.tf)))