Consider allowing CIF/SVG inputs mappings that map to a disabled event
Origin
This came up for the wolf/goat/cabbage CIF example (#465 (closed) and !427 (merged)).
From !427 (comment 1048975):
I like the example, nice visualization as well :).
Only thing I do not like (which is outside this issue):
svgin id "wolf1" event if boat.atBank = 1: c_wolfIn else no_action end;
Why do we need to explicitly define
no_action
events? We should be able to omit theelse
. Do you know the rational why we always require theelse
?
From !427 (comment 1048980):
The grammar on the documentation website states
[... parts omitted ...]
[...] I am not sure what would happen if a user modeled for example
svgin id "wolf1" event if boat.atBank = 1: c_wolfIn elif false: no_action end;
From !427 (comment 1048981):
. So I am not sure what would happen if a user modeled for example
svgin id "wolf1" event if boat.atBank = 1: c_wolfIn elif false: no_action end;
ERROR: Simulation resulted in a runtime error, for state: time=2.9666666666666655, bank1=alive, bank1.hasCabbage=true, bank1.hasGoat=false, bank1.hasWolf=true, bank2=alive, bank2.hasCabbage=false, bank2.hasGoat=false, bank2.hasWolf=false, boat=*, boat.atBank=2, boat.hasCabbage=false, boat.hasGoat=true, boat.hasWolf=false, disabled_actions=*. CAUSE: Evaluation of the SVG input mapping ("../wolf_goat_cabbage.svg") for the SVG element with id "wolf1" failed. CAUSE: Incomplete SVG input mapping: none of the guards are satisfied (evaluate to value "true").
From !427 (comment 1048983):
For completeness, my suggestion is to default to "Do nothing" instead of "crash" when none of the guards are satisfied.
Possible solutions
There are multiple approaches to solve this, as discussed in the various comments of this issue. We need to decide on the best approach.
-
Keep it as is
The current approach is to use
no_action
events, like done for the wolf/goat/cabbage, and for infrastructural systems. -
Allow SVG inputs to map to not map to an event
Allow CIF/SVG input mappings to map to no event. Only if you click it, and it maps to an event, is the event taken. If it doesn't map to an event, the CIF/SVG mapping indicates the click should have no effect, and is thus ignored.
- Pro: This allows to keep much of the current implementation. We can just evaluate the mapping, and ignore the click if it doesn't map to any event.
- Con: This approach requires to use
if
expressions that are incomplete. You must thus be able to indicate the condition under which the click maps to an event, and when it doesn't. If the condition is actually determined by synthesis, this is not really feasible, as the whole goal of synthesis is often to find conditions you don't know yet. A practical example for this, is the FIFO example that was mentioned. - Con: There are concerns about the conceptual aspects of this choice.
- Con: It seems Solution 3 is really needed, and makes this choice (mostly?) superfluous.
- Note: We need to allow
if
expressions that are incomplete, as discussed here. We should allow not having anyelif
orelse
parts then. This can be changed locally for CIF/SVG input mappings, but does require a language change. Should be a very localized and self-contained change though. - Decision: Not chosen. We go for Solution 3. If we need Solution 2 in the future, we can revisit. Let's try Solution 3 first.
-
Allow SVG inputs to map to disabled events
CIF/SVG input mappings would still always map to an event, but the event need not be enabled. If it is disabled, it will simply not be chosen.
- Pro: This approach does not require
if
expressions with conditions that are difficult/impossible to specify (as for option 2). - Pro: We can simplify many CIF/SVG input mappings, as they don't have to map to enabled events.
- Pro: This approach is considered conceptually cleaner than Solution 2.
- Con: This approach is a bit more difficult to implement.
- Con: This approach may degrade performance (see here).
- Con: Sometimes mapping to a disabled event may be intended, other times it may be a mistake.
- Decision: Chosen. Addresses valid use cases that can't be solved with Solution 2, is conceptually clean, and improves the current situation.
- Implementation: We decided not to go for a simulator option to revert to the old behavior (for error checking). Instead, we'll print a normal output message in case the click does not amount to any behavior, similar to the warning that we get now and that results in deadlock immediately thereafter.
- Pro: This approach does not require
Implementation of Solution 3
From #469 (comment 1053757) and #469 (comment 1053771):
This still needs a decision when the event stops being fine to perform.
This should remain simple, I think. The click has an 'immediate' effect, or no effect. If it is not possible now, and we allow to ignore it in such cases, it should immediately be ignored. ...
I was thinking to keep it until the next time step. That avoids priority or sequence problems in choosing events.
It would require considering the entire queue, rather than only the head of the queue. It is not what we currently do, but I think it is possible.
This still needs to be figured out.