Commit 9dbb0241 authored by Jorn Baayen's avatar Jorn Baayen

transcribe() working again

parent 3837bc50
from casadi import MX, Function, jacobian, vertcat, reshape, mtimes, substitute, interpolant
from casadi import MX, Function, jacobian, vertcat, reshape, mtimes, substitute, interpolant, transpose, repmat
import numpy as np
import logging
......@@ -10,7 +10,7 @@ def is_affine(e, v):
return (f.sparsity_jac(0, 0).nnz() == 0)
def nullvertcat(L):
def nullvertcat(*L):
"""
Like vertcat, but creates an MX with consistent dimensions even if L is empty.
"""
......@@ -26,8 +26,8 @@ def reduce_matvec(e, v):
This reduces the number of nodes required to represent the linear operations.
"""
Af = Function("Af", [], [jacobian(e, v)])
A = Af()[0]
Af = Function("Af", [MX()], [jacobian(e, v)])
A = Af(MX())
return reshape(mtimes(A, v), e.shape)
......@@ -43,8 +43,10 @@ def reduce_matvec_plus_b(e, v):
def interpolate(ts, xs, t, equidistant, mode=0):
if mode == 0:
return interpolant(ts, xs, t, equidistant)
if False: # TODO mode == 0:
print(ts)
print(xs)
return interpolant('interpolant', 'linear', [ts], xs, {'lookup_mode': 'exact'})(t)
else:
if mode == 1:
xs = xs[:-1] # block-forward
......@@ -54,8 +56,8 @@ def interpolate(ts, xs, t, equidistant, mode=0):
if t.size1() > 1:
t_ = MX.sym('t')
xs_ = MX.sym('xs', xs.size1())
f = Function('interpolant', [t_, xs_], [mul(transpose((t_ >= ts[:-1]) * (t_ < ts[1:])), xs_)])
f = f.map('interpolant_map', t.size1())
return transpose(f([transpose(t), repmat(xs, 1, t.size1())])[0])
f = Function('interpolant', [t_, xs_], [mtimes(transpose((t_ >= ts[:-1]) * (t_ < ts[1:])), xs_)])
f = f.map(t.size1(), 'serial')
return transpose(f(transpose(t), repmat(xs, 1, t.size1())))
else:
return mul(transpose((t >= ts[:-1]) * (t < ts[1:])), xs)
\ No newline at end of file
return mtimes(transpose((t >= ts[:-1]) * (t < ts[1:])), xs)
\ No newline at end of file
# cython: embedsignature=True
from casadi import MX, substitute, repmat, vertcat, depends_on
from casadi import MX, substitute, repmat, vertcat, depends_on, veccat
from pymola.backends.casadi.api import transfer_model
from collections import OrderedDict
import numpy as np
......@@ -72,7 +72,7 @@ class ModelicaMixin(OptimizationProblem):
else:
if v.symbol.name() in kwargs.get('lookup_tables', []):
self._mx['lookup_tables'].append(v.symbol)
elif v.fixed == False:
elif v.fixed == True:
self._mx['constant_inputs'].append(v.symbol)
else:
self._mx['control_inputs'].append(v.symbol)
......@@ -106,12 +106,13 @@ class ModelicaMixin(OptimizationProblem):
v.symbol.name(), alias))
# Initialize nominals and types
# TODO needs initialized metadata
self._nominals = {}
self._discrete = {}
for v in itertools.chain(self._pymola_model.states, self._pymola_model.alg_states, self._pymola_model.inputs):
sym_name = v.symbol.name()
if v.nominal != 0 and v.nominal != 1:
self._nominals[sym_name] = abs(float(nominal))
self._nominals[sym_name] = abs(float(v.nominal))
if logger.getEffectiveLevel() == logging.DEBUG:
logger.debug("ModelicaMixin: Set nominal value for variable {} to {}".format(
......@@ -119,6 +120,19 @@ class ModelicaMixin(OptimizationProblem):
self._discrete[sym_name] = v.python_type != float
# Initialize dae and initial residuals
inputs = [v.symbol for v in self._pymola_model.inputs]
self._dae_residual = self._pymola_model.dae_residual_function(self._mx['time'][0],
veccat(*self._mx['states']), veccat(*self._mx['derivatives']), veccat(*self._mx['algebraics']), veccat(*inputs), MX(), veccat(*self._mx['parameters']))
if self._dae_residual is None:
self._dae_residual = MX()
self._initial_residual = self._pymola_model.initial_residual_function(self._mx['time'][0],
veccat(*self._mx['states']), veccat(*self._mx['derivatives']), veccat(*self._mx['algebraics']), veccat(*inputs), MX(), veccat(*self._mx['parameters']))
if self._initial_residual is None:
self._initial_residual = MX()
# Call parent class first for default behaviour.
super(ModelicaMixin, self).__init__(**kwargs)
......@@ -138,10 +152,10 @@ class ModelicaMixin(OptimizationProblem):
# Eliminate constant symbols from model, replacing them with the values
# specified in the model.
compiler_options['replace_constants'] = True
compiler_options['replace_constant_values'] = True
# Replace any parameter expressions into the model.
compiler_options['replace_parameter_expressions'] = 'True'
compiler_options['replace_parameter_expressions'] = True
# Eliminate variables starting with underscores.
compiler_options['eliminable_variable_expression'] = r'_\w+'
......@@ -150,8 +164,7 @@ class ModelicaMixin(OptimizationProblem):
compiler_options['detect_aliases'] = True
# Cache the model on disk
# TODO set to False to runt into unset attributes
compiler_options['cache'] = False
compiler_options['cache'] = True
# Done
return compiler_options
......@@ -211,7 +224,7 @@ class ModelicaMixin(OptimizationProblem):
# Initial conditions obtained from start attributes.
for v in self._pymola_model.states:
# TODO nan values
initial_state[sym.name()] = sym.start
initial_state[v.symbol.name()] = v.start
return initial_state
......@@ -238,7 +251,7 @@ class ModelicaMixin(OptimizationProblem):
if M is None:
M = 1
m_ = v.min
m_ = MX(v.min)
if not m_.is_constant():
[m] = substitute([m_], self._mx['parameters'], parameter_values)
if m.is_constant():
......@@ -248,7 +261,7 @@ class ModelicaMixin(OptimizationProblem):
if np.isfinite(m_): # TODO vector values
m = m_
M_ = v.max
M_ = MX(v.max)
if not M_.is_constant():
[M] = substitute([M_], self._mx['parameters'], parameter_values)
if M.is_constant():
......
......@@ -72,6 +72,9 @@ class OptimizationProblem(metaclass = ABCMeta):
Base class for all optimization problems.
"""
def __init__(self, **kwargs):
self._mixed_integer = False
def optimize(self, preprocessing=True, postprocessing=True, log_solver_failure_as_error=True):
"""
Perform one initialize-transcribe-solve-finalize cycle.
......@@ -111,14 +114,10 @@ class OptimizationProblem(metaclass = ABCMeta):
my_solver = options['solver']
del options['solver']
# Expand option
expand = options['expand']
del options['expand']
# Already consumed
del options['optimized_num_dir']
nlpsol_options = {'expand': expand, my_solver: options}
nlpsol_options = {my_solver: options}
if self._mixed_integer:
nlpsol_options['discrete'] = discrete
......
......@@ -11,7 +11,7 @@ model TestModel
output Real z;
input Real x_delayed(fixed=true);
input Real x_delayed(fixed=false);
output Real switched;
......
......@@ -12,7 +12,7 @@ model TestModelWithInitial
output Real z;
input Real x_delayed(fixed=true);
input Real x_delayed(fixed=false);
output Real switched;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment