1. 19 Mar, 2019 1 commit
    • Tjerk Vreeken's avatar
      Revert "CollInt: Fix missing parameter check to include NaN" · 542c5216
      Tjerk Vreeken authored
      This reverts commit 038975e7.
      
      There are many models that have parameters that are not used. For
      example, species transport in RTC-Tools Channel Flow might use a
      "V_nominal" for linearization, but if there are no species this
      parameter is never used.
      
      We would rather like to check on parameters that are actually used, but
      that would be an expensive check to always perform for every run. It is
      probably better to put a check like that behind an optional flag for
      performing such checks.
      542c5216
  2. 15 Mar, 2019 13 commits
    • Tjerk Vreeken's avatar
      pi.py: Fix duplicating read units for all ensembles · c7985d80
      Tjerk Vreeken authored
      When we duplicate variables over all ensemble members, we should not
      only copy the values but also the unit.
      c7985d80
    • Tjerk Vreeken's avatar
      pi.py: Fix duplicating read values for all ensembles · 4280c608
      Tjerk Vreeken authored
      When an ensemble member is not specified for a certain variable in the
      input, we want to add the same variable-values pair to all ensembles.
      The loop that was supposed to do this was a no-op, as it used
      `ensemble_member` (which is zero in this case), instead of the loop
      index.
      
      Note that we remove the underscore prefix that indicated that the loop
      index was unused.
      4280c608
    • Tjerk Vreeken's avatar
      pi.py: Fix set variable for more than ensemble member · 698720a6
      Tjerk Vreeken authored
      We would encounter an IndexError when trying to set a variable for an
      ensemble member other than zero, because self.__units was not properly
      (re)initialized for all ensemble members.
      698720a6
    • Tjerk Vreeken's avatar
      Annotate AliasDict element types in API · 1fb30470
      Tjerk Vreeken authored
      For dictionaries and lists we typically indicate what the type of the
      elements are, but this was not yet possible for the commonly used
      AliasDict class.
      
      This commit adds type annotation support to the AliasDict class, and
      also clarifies the API with the correct element types in all places that
      an AliasDict is expected or returned.
      1fb30470
    • Tjerk Vreeken's avatar
      CollInt: Remove unnecessary resolving of initial values · 55faee67
      Tjerk Vreeken authored
      The methods history() and initial_state() do not return symbolic values,
      and resolving of these values is therefore not needed in
      CollocatedIntegratedOptimizationProblem. For symbolic initial state
      values from the model, we make sure to resolve them right away in
      ModelicaMixin.
      
      The code that we remove/change in this commit was a remainder of the
      JModelica era, where resolving with parameter values was not done in
      ModelicaMixin.
      
      Note that, depending on the completeness of the history data, initial
      derivatives can be a function of the (symbolic) initial state. They are
      however not not a function of e.g. symbolic parameters.
      55faee67
    • Tjerk Vreeken's avatar
      CollInt: Remove unnecessary resolving of constant inputs · 988042a4
      Tjerk Vreeken authored
      The method constant_inputs() returns Timeseries, which cannot be
      symbolic. Resolving of these values is therefore not needed in this
      class. For symbolic constant inputs from a Modelica model we make sure
      to resolve them in ModelicaMixin.
      
      The code that we remove/change in this commit was a remainder of the
      JModelica era, where resolving of symbolic expressions with parameter
      values was not done in ModelicaMixin.
      988042a4
    • Tjerk Vreeken's avatar
      CollInt: Remove unnecessary resolving of bounds · 63bf9cb2
      Tjerk Vreeken authored
      The method bounds() does not return symbolic values, and resolving of
      these values is therefore not needed in this class. For symbolic bounds
      from a Modelica model we make sure to resolve them in ModelicaMixin.
      
      The code that we remove/change in this commit was a remainder of the
      JModelica era, where resolving of symbolic expressions with parameter
      values was not done in ModelicaMixin.
      63bf9cb2
    • Tjerk Vreeken's avatar
      CollInt: Fix missing parameter check to include NaN · 038975e7
      Tjerk Vreeken authored
      Instead of only checking for missing parameters, we check for NaN as
      well. This is because ModelicaMixin sets all parameters to their
      respective values, even if they have no value set (=NaN).
      038975e7
    • Tjerk Vreeken's avatar
      ModelicaMixin: Fix symbolic parameter substitution checks · 133e8be2
      Tjerk Vreeken authored
      If not all parameters that occur in a symbolic expression are specified,
      it can either result in a (still) symbolic expression, or NaN. We
      checked the former, but did not yet check the latter.
      
      Note that the reason that expressions result in NaN is because some of
      the parameters are NaN. This in turn is caused by ModelicaMixin not
      skipping parameters in the model for which a value is not set (NaN).
      133e8be2
    • Tjerk Vreeken's avatar
      ModelicaMixin: Remove useless constant_inputs() implementation · 9f52be89
      Tjerk Vreeken authored
      If a constant input is given a default value in the Modelica model,
      Pymoca will turn this assignment into an equation. All constant inputs
      (and control inputs), whether they have been given a default value or
      not in the Modelica model, will therefore have a value attribute equal
      to NaN.
      
      Note that this means we also cannot (easily) detect if a value has been
      given to a constant input in the Modelica file. If a user gives the same
      constant input another value in RTC-Tools, the system of equations could
      become infeasible.
      9f52be89
    • Tjerk Vreeken's avatar
      ModelicaMixin: Fix reading of symbolic initial states · 3213fc10
      Tjerk Vreeken authored
      The initial_state() method has to return a numeric value. For symbolic
      initial state that means that we need to substitute the parameters, just
      like e.g. bounds() and seed() already did.
      
      Note that, unlike e.g. the seed() method in ModelicaMixin, we raise an
      exception if the symbolic expression cannot be resolved. This is because
      a wrong/missing initial state is worse than a wrong seed value.
      3213fc10
    • Tjerk Vreeken's avatar
    • Tjerk Vreeken's avatar
      ModelicaMixin: Fix reading of symbolic start attributes · 3e4fbba1
      Tjerk Vreeken authored
      Regression in 10da03cb. Only for SX symbols does a symbolic expression
      turn into a NaN. For symbolic MX expressions a RuntimeError is raised.
      
      We also have to do the Python type conversion on the _substituted_
      value, not the original MX value (which will result in a RuntimeError).
      
      Lastly, if we cannot resolve the seed value, we should continue to the
      next symbol instead of still setting the seed.
      3e4fbba1
  3. 27 Feb, 2019 1 commit
    • Tjerk Vreeken's avatar
      Timeseries: Fix constructor for ca.DM and support float arguments · 2199c96f
      Tjerk Vreeken authored
      According to the typing hints, a ca.DM should have been supported, but
      it would fail with an Exception because it does not support len().
      
      Furthermore, the code in the constructor seemed to suggest support for
      floats (and integers), due to the "np.full_like" branch. The typing
      hints did however not cover this, and neither did it work in practice
      because of the len() call.
      2199c96f
  4. 25 Feb, 2019 1 commit
    • Tjerk Vreeken's avatar
      GPMixin: Fix Exception when target min or max empty Timeseries · 053baa9a
      Tjerk Vreeken authored
      If target_min and target_max are both empty Timeseries (full of NaNs),
      the "is_empty" attribute is True and the Goal is skipped in its
      entirety. However, in case only one of the two targets is empty, we
      would get an Exception in CollInt due to setting an empty constraint of
      size MX(1x0).
      
      This bug was introduced in commit a788207e when support for vector goals
      was added. To make sure that results for a vector goal are exactly equal
      to its non-vector counterpart, the slicing of a (vector) soft constraint
      was added in the relevant section of code. This slicing did not account
      for the possibility of no element of the constraint expression being
      active.
      053baa9a
  5. 21 Feb, 2019 1 commit
  6. 18 Feb, 2019 2 commits
    • Tjerk Vreeken's avatar
      Simulation: Fix wrong scaling of nominals for inputs · a5cedd8c
      Tjerk Vreeken authored
      When setting up the rootfinder, we did not replace control/constant inputs
      with their scaled equivalents in the DAE. We did however assume they were
      scaled these when using set_var() to set the control inputs. This led to
      horribly wrongly and inconsistently formulated problems.
      
      Note that the initialize() method has its own optimization problem, and
      there the constant and control inputs were replaced with their scaled
      equivalents in the respective DAE.
      
      To solve this issue for the rootfinder without breaking initialize(), we
      now ignore nominals for constant inputs and control inputs. Note that
      these variables are not part of the state vector, but are instead
      parameters. Using unscaled variants in the DAE is therefore unlikely to
      lead to issues.
      a5cedd8c
    • Tjerk Vreeken's avatar
      af32d81c
  7. 16 Feb, 2019 2 commits
    • Tjerk Vreeken's avatar
      GPMixin: Fix scale_by_problem_size with keep_soft_constraints · 6116b456
      Tjerk Vreeken authored
      The combination of these two options would lead to infeasible objective
      constraints, because the size of vector symbols in the objective were
      not taken into account when building the constraint.
      
      For example, when using `scale_by_problem_size` an objective `e` with
      `e` being a symbol of size 3 would lead to an (expanded) objective of
      `(e[0] + e[1] + e[2]) / 3`. If this minimized to a value of 0.1, we
      would end up with an objective constraint `e[0] + e[1] + e[2] <= 0.1`,
      which is infeasible.
      6116b456
    • Tjerk Vreeken's avatar
      Rename test class and method of vector goals · 86bc4975
      Tjerk Vreeken authored
      The "constraints" name was an unintended remainder of using the vector
      constraints test class and its methods as a starting point.
      86bc4975
  8. 15 Feb, 2019 4 commits
    • Tjerk Vreeken's avatar
      ControlTreeMixin: Improve branch allocation · 4d789d2b
      Tjerk Vreeken authored
      Instead of picking the first ensemble member in a branch as our first
      reference, we should pick the most extreme one. That way, the ordering
      of the ensemble members does not have an influence on what branch they
      end up on (barring cases where distance of an ensemble member to the
      reference branches is equal).
      
      Closes #1095
      4d789d2b
    • Tjerk Vreeken's avatar
      CollInt: Fix constraints on initial derivative · b3e07c0e
      Tjerk Vreeken authored
      When history data is available at t-1 but not at t0, we would end up
      using the unscaled symbol of the state, resulting in the wrong value for
      the initial derivative. This was not caught in the relevant test,
      because the nominal on 'w' was 1.0.
      
      This commit fixes the bug by properly using the scaled version of the
      symbol, and also changes the test such that it would have caught this
      bug.
      
      Note that the behavior was/is correct when when history data is
      available at both t0 and t-1, as there is no reference to the initial
      state entry in the state vector in this case (only to numeric values).
      b3e07c0e
    • Jorn Baayen's avatar
      OptimizationProblem.interpolate: Guard against out-of-bounds array access · ae029bfb
      Jorn Baayen authored
      In particular cases, divmod can return close-to-zero residuals.  We
      needed to add an additional check to correctly handle this happening at the
      final data point.
      ae029bfb
    • Tjerk Vreeken's avatar
      ControlTreeMixin: Avoid allocating free variables for emtpy branches · 555d37a5
      Tjerk Vreeken authored
      Although allocating decision variables that are free is not wrong, it is
      wasteful and may sometimes even lead to solver warnings.
      
      Closes #1084
      555d37a5
  9. 12 Feb, 2019 1 commit
  10. 05 Feb, 2019 1 commit
    • Tjerk Vreeken's avatar
      GPMixin: Disallow non-positive weight for goals with target bounds · 091104e6
      Tjerk Vreeken authored
      If a goal has target bounds, a negative weight would mean maximization
      of the violation variable. This makes no sense from the perspective of
      goal programming, which is why it is now explicitly disallowed with a
      check.
      
      If a goal has target bounds and a weight of zero, we would basically
      just be adding useless constraints. This therefore also makes no sense,
      and is now explicitly disallowed.
      
      If the goal does not have target bounds, a negative goal weight is
      possible if e.g. the user wants to maximize, or flip the sign of the
      goal function.
      091104e6
  11. 01 Feb, 2019 1 commit
    • Tjerk Vreeken's avatar
      GPMixin: Fix keep_soft_constraints with ensembles · 20b2f164
      Tjerk Vreeken authored
      We rely on the map_path_expression() call working for all ensemble
      members. For performance reasons, map_path_expression() reuses variables
      from transcribe(), see f94499ca. Therefore, we cannot call
      map_path_expression() in the constraints() call of any ensemble member
      later than currently being processed. So instead of adding our overall
      constraint to the first ensemble member, we have to add it to the last.
      20b2f164
  12. 31 Jan, 2019 4 commits
  13. 14 Jan, 2019 1 commit
  14. 09 Jan, 2019 1 commit
    • Tjerk Vreeken's avatar
      Disallow goal violation timeseries when keeping soft constraints · 20833f90
      Tjerk Vreeken authored
      The violation timeseries was only ever set in the call to
      __soft_to_hard_constraints, which is never called when
      keep_soft_constraints is set.
      
      As the goal violation is no longer guaranteed to be constant over
      priorities, there is no easy way to support goal violation timeseries id
      when keeping soft constraints. That is why we explicitly disallow it in
      this commit.
      
      Closes #1088
      20833f90
  15. 08 Jan, 2019 5 commits
    • Tjerk Vreeken's avatar
      Fix DeprecationWarning of MutableSet · 745dacab
      Tjerk Vreeken authored
      Importing ABCs directly from collections instead of collections.abc is
      deprecated in Python 3.7, and will be removed in Python 3.8.
      745dacab
    • Tjerk Vreeken's avatar
      SimulationProblem: Disallow setting parameters after initialization · 6c8b59f3
      Tjerk Vreeken authored
      Setting parameters only works correctly if done before initialize() is
      called. Because set_var() is also allowed (for backwards compatibility
      reasons) for setting parameter values, we want to be clear about this by
      raising an Exception if the user tries to set a parameter _after_
      initialization.
      6c8b59f3
    • Tjerk Vreeken's avatar
      SimulationProblem: Fix when nominal is symbolic MX · 7def7922
      Tjerk Vreeken authored
      Due to backwards compatibility with allowing set_var() for parameters,
      it is possible for get_variable_nominal() to return a symbolic MX
      expression instead of a numeric value. This was not handled properly
      inside SimulationProblem.
      
      Note that we want to disallow setting parameters like this in the
      future, instead forcing users to override/extend the parameters()
      method. That way, we will be able to guarantee that
      get_variable_nominal() always returns a numeric value.
      
      Closes #1085
      7def7922
    • Tjerk Vreeken's avatar
      SimulationProblem: Fix scaling of bounds with nominals · 7449e8fd
      Tjerk Vreeken authored
      The bounds were not scaled at all with the nominals. With the equations
      being scaled, this would lead to many infeasible problems.
      7449e8fd
    • Tjerk Vreeken's avatar
      SimulationProblem: Fix scaling of equations with nominals · 7e8bfd75
      Tjerk Vreeken authored
      SimulationProblem was only ever using the nominals defined in the Modelica
      file, even if e.g. the user was overriding get_variable_nominal().
      
      Also note that variable nominals can be symbolic, but that we would like
      to handle numeric values/floats as much as possible. We therefore
      evaluate the nominals to their numeric values as soon as we know all
      parameter values.
      7e8bfd75
  16. 07 Jan, 2019 1 commit