Opened 10 years ago

Closed 10 years ago

Last modified 7 years ago

#2965 closed discussion (fixed)

Information about "outer output" declarations needed in backend for variable merging in state machines

Reported by: Bernhard Thiele Owned by: Bernhard Thiele
Priority: high Milestone: 1.9.4
Component: Frontend Version: trunk
Keywords: state machines Cc: Per Östlund, Adrian Pop

Description

MLS 3.3, "17.3.5 Merging Variable Definitions" requires to merge variables in states that have been declared as outer output. However, in the backend that information is lost, thus it can't be implemented.
Quoting from the spec:

In each state, the outer output variables are solved for and for each such variable a single definition is formed:
v := if activeState(state1) then expre1 elseif activeState(state2 ) then expre2 elseif ... else last(v)

I tried to recover the needed pieces from what is available in the backend, but didn't succeed so far. Consider example:

model ConferenceTut1Modified
  inner Integer i(start=0);
  Integer j(start=0), y;
  model State1
    outer output Integer i;
    input Integer j;
    Integer k;
  equation 
    i = previous(i) + 2 - k;
    j = k;
  end State1;
  State1 state1(j=j);
  model State2
    outer output Integer i;
    input Integer j;
    Integer k;
  equation 
    i = previous(i) - 1- k;
    j = k;
  end State2;
  State2 state2(j=j);
equation 
  2 = j;
  y = i;
  initialState(state1);
  transition(state1, state2, i > 10, immediate=false);
  transition(state2,state1, i < 1, immediate=false);
end ConferenceTut1Modified;

The model flattens to:

class ConferenceTut1Modified
  Integer i(start = 0);
  Integer j(start = 0);
  Integer y;
  Integer state1.i = i;
  Integer state1.j = j;
  Integer state1.k;
  Integer state2.i = i;
  Integer state2.j = j;
  Integer state2.k;
equation
  state1.i = 2 + previous(state1.i) - state1.k;
  state1.j = state1.k;
  state2.i = -1 + previous(state2.i) - state2.k;
  state2.j = state2.k;
  2 = j;
  y = i;
  initialState(state1);
  transition(state1, state2, i > 10, false, true, false, 1);
  transition(state2, state1, i < 1, false, true, false, 1);
end ConferenceTut1Modified;

Variable i needs to be merged, but variable j not. So i should get merged like

i = if activeState(state1) then 2 + previous(i) - state1.k 
    else -1 + previous(i) - state2.k;

If we could assume that all models are "correct", one might be able to figure out that the only way that the model could be correct is that i is a "shared" variable, but j is not. However, one can not safely make that assumption. Hence, additional information about i needs to be passed from the frontend to the backend. Or do I miss s.th.?

(Note that #2806 is vaguely related to this ticket, but had the opposite intention of dropping certain information...)

Attachments (1)

2015_OM Workshop_State Machines_Bernhard Thiele.pdf (480.0 KB ) - added by Bernhard Thiele 10 years ago.

Download all attachments as: .zip

Change History (8)

comment:1 by Adrian Pop, 10 years ago

Can't you just add this information to the DAE.Var in InstDAE.daeDeclare?

comment:2 by Bernhard Thiele, 10 years ago

Hm. The inner outer attributes are lost in the backend (BackendDAECreate.lower), they are available in the frontend DAE. The direction is available in frontend until it is stripped away for all non-toplevel instances in InstVar.instScalar

attr = stripVarAttrDirection(cr, attr, inState);

which I suppose is due to #2806.

It seems however, that I need both information, because in state machines "outer output Real x" needs merging "outer input Real x" is only reading. And we have "inner outer output Real x" which, in state machines also has a different semantics than the usual "inner outer". In state machines that means that lower level outer may write directly to the highest level inner (so inner outer output is used in intermediate levels for "shared" variables.

Actually, I don't understand why the spec requires this intermediate level construct "inner outer output". For me it seems that reusing "outer output" at the intermediate levels should be sufficient to declare s.th. as a "shared" variable. But may be I start understanding the reason during the implementation ;-).

comment:3 by Bernhard Thiele, 10 years ago

I have now a prototype implementation for state machines in source:/branches/StateMachines@24335 .
Compared to the trunk version there are two important differences.

Change 1: Include information about "inner outer" in BackendDAE.Var
BackEnd/BackendDAE.mo - add .DAE.VarInnerOuter innerOuter to VAR:

public
uniontype Var "variables"
  record VAR
    // ...
    .DAE.VarDirection varDirection "input, output or bidirectional";
    // ...
    .DAE.VarInnerOuter innerOuter "inner, outer,  inner outer or unspecified";
  end VAR;
end Var;

FrontEnd/DAE.mo - Add new uniontype:

public uniontype VarInnerOuter
  record INNER           "an inner prefix"       end INNER;
  record OUTER           "an outer prefix"       end OUTER;
  record INNER_OUTER     "an inner outer prefix" end INNER_OUTER;
  record NOT_INNER_OUTER "no inner outer prefix" end NOT_INNER_OUTER;
end VarInnerOuter;

Change 2: Pass information about variable causality from the front-end to the back-end
I commented out line

attr = stripVarAttrDirection(cr, attr, inState);

from InstVar.instScalar (see previous comment).

Change 3: Special rules for instantiation of variables appearing in state machines
I changed function InstVar.instVar and added special rules for instantiating variables that are part of a state machine, so that I can identify them later in the back-end and treat them special.

Problem: How to get "Change 2" into development trunk without breaking #2806

It is possible to merge Change 1 and Change 3 back into the trunk, however merging Change 2 will break #2806.

Note that as background information I will attach my presentation that gives an overview about the current state machine implementation approach. Moving parts of the state machine implementation from the back-end to the front-end could also be an alternative (for more reasons than just the problem at hand, but it might introduce other difficulties...).

Any ideas?

comment:4 by Bernhard Thiele, 10 years ago

I think I partially fixed the issue in source:/branches/StateMachines@24659

I changed the function call

attr = stripVarAttrDirection(cr, attr, inState);

to

attr = stripVarAttrDirection(cr, ih, inState, inPrefix, attr);

and implemented an additional check in the function whether a component with inner/outer prefix is part of a state machine component. If this is the case I don't strip that information, otherwise it is stripped.

comment:5 by Bernhard Thiele, 10 years ago

Resolution: fixed
Status: newclosed

Merged branch into source:/trunk@24709.

comment:6 by Dietmar Winkler, 9 years ago

Milestone: Futurepre1.9.4

It doesn't make sense to keep closed ticket in the "Future" milestone that were simply forgotten to assign to the correct milestone in the past.

comment:7 by Martin Sjölund, 7 years ago

Milestone: pre1.9.41.9.4

Removing the pre1.9.4 milestone in favor of 1.9.4.

Note: See TracTickets for help on using tickets.