Implicit dv := pre(dv) in initial algorithm?
Consider:
model DiscreteInit2
Integer i;
initial algorithm
if time < 1 then
i := 1;
end if;
equation
when false then
i = pre(i);
end when;
end DiscreteInit2;
From what I read here about algorithms:
A discrete-time variable v is initialized with pre(v).
and here about when equations:
If a when-clause equation v = expr; is not active during the initialization phase, the equation v = pre(v) is added for initialization.
my interpretation is that the initialization problem to be solved for this model is:
initial algorithm
i := pre(i);
if time < 1 then
i := 1;
end if;
equation
i = pre(i);
which, swapping pre(i) => prei for readability, conceptually is similar to (pseudo code):
function f
input Integer prei;
input Integer i;
output Integer i_out;
algorithm
i_out := prei;
if time < 1 then
i_out := 1;
end if;
end f;
i = f(prei, i);
i = prei;
which reveals that we have a cycle/mutually dependent equations in the variables {i, prei}, turning this into an illegal model.
Is this interpretation correct?
Note relation to #2639. I'm trying to get clarity on the initialization-specific aspects in this new issue.
Clearly discrete variables that are not unconditionally assigned should have deterministic value at the start of the initial algorithm to get deterministic results.
However, using pre(dv) will mostly cause loops that cannot be solved (uniquely), unless the variable is assigned a value (independent of its initial value) and in that case the initial value didn't matter. That just seems bad.
For parameters we instead have the special rule that they are initialized to their start-value in initial algorithms, and that seems like a solution that could be generalized to all variables in initial algorithms giving the following benefits:
- It is deterministic
- It does not cause loop
- It unifies the handling in initial algorithms (so the same for parameters, discrete and continuous-time variables)
- Does anyone have a preference for pre(dv) over the start-value for initial algorithms?
- Are there any cases where pre(dv) actually works for initial algorithms?
If not I would propose the change above.
dv = pre(dv) looks to me like a steady-state condition, which of course can be hard to solve for in some cases. I think using the start attribute makes a lot more sense.
I like the idea of unifying the handling and breaking loops, but it's a non-trivial change of semantics that should be evaluated using test-implementations rather than by listening to gut feelings.
I played around with the MWE by @maltelenz and I came to the conclusion that OMC already implements the proposed new semantics 😅:
- OMC does not complain about the initial algebraic loop, so it is not adding the
dv = pre(dv)equation as actually required by the MLS - if I set the start attribute for
i(e.g.,Integer i(start = 3)), I get an initial value of 1 ifStartTime = 0, but I get 3 ifStartTime = 2, when the equation in the initial algorithm is skipped
This means, the OMC generated code first initializes those discrete variables with their start attributes, and then possibly overwrites their value when executing the initial algorithm. So, we already have a working test implementation, and it's been around for a while 😃
Is there any further tests cases you'd like to analyze with it?
keeping @phannebohm and @kabdelhak in the loop, maybe they can further comment about this specific issue.