aseba-community / thymio-vpl2

Next generation VPL for Thymio using Qt Quick from Qt 5.x
GNU Lesser General Public License v3.0
2 stars 5 forks source link

VPL is not declarative #116

Open stephanemagnenat opened 7 years ago

stephanemagnenat commented 7 years ago

As pointed out by @davidjsherman, VPL is close to being declarative, but is not because when events conflicts (for instance with multiple configurations of distance sensors), the order of lines of appearance matters.

This problem has also been reported by teachers, and is actually one cause of the difficulty of using VPL to write non-trivial problems: the notional machine becomes difficult to create when the order matters.

It is interesting to think how this could be improved: currently, VPL forbids similar events or event configurations on two different lines. This could maybe be extended to forbid non-disjoint event conditions.

davidjsherman commented 7 years ago

So, as long as you have don't-care positions, you can trigger two rules with the same conditions: r1(0,x), r2(x,0) both match (0,0). If I understand the goal, teaching autonomous robotics is a noisy world, a realistic semantics would be a random choice between the two. It might be fun to think of an exercise for the children that demonstrates this. For example, a line follower with the above rules, would tend to go straight only if there is no bias.

Whatever the choice of semantics, the important thing is feedback to the programmer.

My memory is rusty but I think checking for ambiguous rules is the same as constructing an Aho-Corasick automaton.

davidjsherman commented 7 years ago

The sensors are random number generators. Another reasonable semantics would be to give the priority to the sensor that has changed the most since the last clock tick

stephanemagnenat commented 7 years ago

Another reasonable semantics would be to give the priority to the sensor that has changed the most since the last clock tick

That is interesting indeed. There are many possible semantics indeed, depending on whether we only consider the close/far thresholds (and hence the conditions), which works only when these thresholds cannot be changed, or whether we consider general conditions.

Actually, when I think about it, I think that in VPL2, all true transition within the reactive mode are taken. @marvelous, is it correct?

marvelous commented 7 years ago

No, the implementation is single-threaded, only one row is triggered simultaneously. We could have one thread per row to support multiple concurrent row triggers, but the problem would resurface anyway when we add a mutable state variable: last write wins would be an obvious implementation choice.

stephanemagnenat commented 7 years ago

I think that, without multi-threading, one could improve the current situation, even assuming we do not want to detect and forbid conflicts.

Indeed, even with a single state and no action conflict, the current behaviour is unexpected. Let us consider the following program, with only one state, with the robot lying on a white surface:

screen shot 2017-08-07 at 18 17 45

Currently, the second line is never executed, because it has been evaluated to true at the first evaluation step, even though it was never actually executed (because the first line was instead). We could change this behaviour such that the transition bit of a line is only set when it is actually executed.

I agree that it will not solve cases with action conflicts, but at least it will behave as naturally expected in a reactive setting with no action conflict.

So there are two questions:

marvelous commented 7 years ago

That sounds like an ugly hack. I much prefer to do an exhaustive check and raise a compilation error if not too runtime-intensive. An other option that seems simple to me is to do a runtime check, raise an aesl event and stop the robot when multiple transitions are possible, prompting the programmer to remove the ambiguity.

marvelous commented 7 years ago

BTW, do you have a realistic VPL1 program for this issue?

davidjsherman commented 7 years ago

For simplicity, let's invent a text syntax: ...||... for motor speed, [...] for bottom sensors, /...\ for front sensors, top(...) for top LEDs.

Example 1

[ 1 1 ]  ->  100||100
[ _ 0 ]  ->  150||50
[ 0 _ ]  ->   50||150
[ 0 0 ]  ->  top(31,0,0)

This is an attempt at a black line follower. The student's idea is to turn away from white, and to shine red if the robot gets lost on white. Question: if the robot gets lost, does it turn? Deterministically or stochastically?

Example 2

/ 1 1 _ _ _ \  ->  150||50
/ _ 1 1 _ _ \  ->  300||0
/ _ _ 1 1 _ \  ->    0||300
/ _ _ _ 1 1 \  ->   50||150
/ _ _ 0 _ _ \  ->  200||200 ; top(0,31,0)
/ _ _ 1 _ _ \  ->  top(31,0,0)
/ _ 1 _ _ _ \  ->  top(15,15,0)
/ _ _ _ 1 _ \  ->  top(15,15,0)

This is an attempt at a wall avoider, where the student requires a consensus between proximity sensors to make a decision. If the threat of hitting the wall is high the robot swerves in place, otherwise it turns while advancing. If nothing is directly in front, then go forward at speed. Independently, shine red or yellow if a wall is detected. Questions: what color is shown when rule 2 is triggered? What speed is used when / 1 1 0 _ _ \ is true? When / _ 1 1 1 _ \ is true?

Possible answers: (red, yellow, or orange); (150||50, 200||200, or 175||125); (300||0, 0||300, 300||300, or 0||0)

Comments

These programs are syntactically correct and have a clear intention. They don't have to be the programs we would have written, or even correct; they are plausible programs that a student might try, and hope to learn from the observed behavior of the robot. We can't forbid these programs because of an arcane rule, that can't be explained to a 10-year-old.

I can think of four semantics for these programs: deterministic using rule order, stochastic transition system, constraint solving over finite domains, analog (average between requested values). But really the question is, which semantics is best for helping students learn to program autonomous robots in a noisy world?

marvelous commented 7 years ago

Great examples! Let's ping @motib and @FrancescoMondada for input.

motib commented 7 years ago

David's examples use "don't care"s which are very much like variables in Prolog. I am in favor of choosing the Prolog semantics: execute the first clause that unifies, here, the first event-action pair whose event evaluates to true. It is easy to explain and deterministic, hence, repeatable, so you can debug the program. Any non-deterministic semantics would just confuse kids. There is lots of "noise" in the sensors and the environment, so I don't see the need for noise in the program semantics!

FrancescoMondada commented 7 years ago

It is hard that in the case of / 1 1 1 \ all sensors become true at the same time. Therefore I expect several lines to activate during the steps between / 000 \ and / 1 1 1 . This should better fit to what the programmer expects. If all three become 1 at the same moment, I agree with Moti that it should be deterministic: even the last or the first line satisfying the conditions should be executed. But the transition bit should be per line, and not per sensor.

marvelous commented 7 years ago

In example 2, the intent of the user seems to run 2 things concurrently: motor control and light control (the 5th line should even be split in two!). If the sensors go from / 1 0 0 0 0 \ to / 1 1 0 0 0 \, should 150||50 or top(15,15,0) be executed? @davidjsherman says that both should be executed, @motib and @FrancescoMondada say that only 150||50 should be executed. Do I get this right?

davidjsherman commented 7 years ago

I agree with @FrancescoMondada that the noisiness of the environment means that many rules get their chance. But what is unfortunate is that a non-declarative semantics leads to a bias, which is what I tried to show in the examples. There isn't any way for the young programmer to define a fair strategy. In example 1, the lost robot always spins clockwise. In example 2, there is a bias towards turning right.

And I fear that the programmer will have a hard time understanding why the lost robot never turns red. Actually, as a teacher I fear the trouble I will have explaining why to the programmer!

davidjsherman commented 7 years ago

@marvelous well spotted. I suppose we could say that each set of actuators (motors, LEDs, sound, IR comm) run in separate threads?

FrancescoMondada commented 7 years ago

@davidjsherman why the robot will never turn red? Because we have transition bits per sensor and not per line, and this a problem. @marvelous If the sensors go from / 1 0 0 0 0 \ to / 1 1 0 0 0 , both 150||50 and top(15,15,0) should be executed, both detect the transition of this sensor. But if the sensors go from / 0 0 0 0 0 \ to / 1 1 1 0 0 \ only the last motor command (or the first) will be executed.

marvelous commented 7 years ago

@FrancescoMondada so you are arguing for having the conflict resolution between actions, not between lines? Both lines should run, but if they have conflicting actions only one of these actions is executed? Sorry if I misunderstood first.

FrancescoMondada commented 7 years ago

@marvelous yes, only conflict resolution between conflicting actions (and executing all of them will result in having the last only applied), it does not make sense to have conflicts between actions of different type

marvelous commented 7 years ago

The implementation will be simpler if we do the conflict resolution at the aesl variable level. The motor action block always sets both motor.left.target and motor.right.target, so if two motor action blocks are executed sequentially by the runtime, the effect will be only the last action.

Using this last writer wins conflict resolution [insert distributed systems paper reference here], we can execute the action blocks in program order (last action block wins) or in reverse program order (first action block wins).

davidjsherman commented 7 years ago

Hello everyone, you keep talking about "program order" as if that is a thing, but the issue is named "VPL is not declarative". An implicit priority between rules is a cognitive bias that comes from sequential programming! Has a decision been made that you want to teach that to young programmers?

davidjsherman commented 7 years ago

@FrancescoMondada, I guess I don't understand which problem you mean in your comment? I understand that you want to trigger rules on the rising edge of sensor changes. Is the problem this strategy, or my example? Sorry to be so slow. Thanks for explaining.

marvelous commented 7 years ago

You are right, @davidjsherman! Going back to

[ 1 1 ]  ->  100||100
[ _ 0 ]  ->  150||50
[ 0 _ ]  ->   50||150
[ 0 0 ]  ->  top(31,0,0)

The issue is that [ 0 0 ] would effect both 150||50 and 50||150. But it's not an issue that it would also effect top(31,0,0). Should the program detect this situation (before or during execution) and explain it to the user? So he would arrive to this solution:

[ 1 1 ]  ->  100||100
[ 1 0 ]  ->  150||50
[ 0 1 ]  ->   50||150
[ 0 0 ]  ->   xx||xx ; top(31,0,0)

(we won't tell him that the lights never turn back off)

motib commented 7 years ago

I am now confused as to the semantics of VPL. My intuition is that - while all event-action pairs are notionally parallel - in practice there is an endless loop that checks the events sequentially in textual order, jumping back to the first pair at the end of the program. Or are separate threads initiated for each pair? With interrupts to schedule them? Do multicore computers execute the threads in true parallelism?!

If my intuition is correct, you teach that the pairs are executed in parallel, but if that leads to weird behavior, then the sequential model needs to be explained. Even in languages like Prolog that are designed to be declarative, the implementation is sequential. There were parallel logic programming languages, but they never made it outside the research labs.

motib commented 7 years ago

Let me add a clarification: I am using the (for me very important) concept of a "notional machine" proposed by Ben du Boulay in 1986. (For a modern survey see: Juha Sorva. Notional machines and introductory programming education. ACM Transactions on Computing Education (TOCE) 13(2), 2013.) This is the architecture that defines the semantics, even if it doesn't precisely reflect the implementation. Beginning students, in particular, should be presented with a very simple notional machine. That is why I am comfortable with a VPL notional machine that is fully parallel, even if the underlying implementation is different, and even if the notional machine has to modified in some situations.

davidjsherman commented 7 years ago

@motib and purely declarative logic languages that didn't even get that far!

davidjsherman commented 7 years ago

@motib I agreed that the semantics of the notional machine is paramount, we shouldn't define the meaning of the language in terms of what it easy to implement. When you say "fully parallel" do you mean that the sensor surveillance threads are running in parallel, or that every rule is notionally running in parallel (and thus will fire independently whenever its conditions are met)?

davidjsherman commented 7 years ago

@marvelous Yes, it would be nice to give advice for completing rules as you suggested. But I worry that it will lead to a combinatorial explosion. In Example 2, I made a cascade of all the front sensors. Wouldn't a complete solution require you to add 25 rules for all of the combinations?

marvelous commented 7 years ago

Yes, an unambiguous solution for example 2 seems impractical to say the least. So where do we go from here? Last/first action block wins doesn't seem bad to me, but you seem to want an other behaviour. Averaging or metastable?

I remember @stephanemagnenat saying that a big part of this issue from his point of view is that the real-time execution makes it very hard for the user to understand and address the issue. Maybe some kind of replay functionality that highlights where conflicting action blocks were executed at the "same" time?

ddoak commented 7 years ago

I just knew this thread was going to be good. /gets popcorn :-)

FrancescoMondada commented 7 years ago

@davidjsherman sorry, for me discussing in such a chat is complex a not very productive. Perhaps I am wrong in my assumptions. Let start from beginning: why do you say that the lost robot never turns red . Is this in example 1 or 2?

mbonani commented 7 years ago

To go forward let's explain some actual thing and why there is misunderstanding. There is a difference between VPL1 and VPL2 generated code. First taking simple example 1, I will then make test of example 2. As I am less familiar with terms like "declarative" , single tread etc, I make the example 1 on the 2 platform and tested it on real Thymio.
With VPL1: image

When the robot go on white the generated code make that all the three event are fired and finally the robot turns right and it is red. It is what Francesco is used to and here the order matters. If we invert line 2 and line 3 the behavior is changed, robot turns left and is red. As all event are fired all action are executed and finally last win when two actions are on the same element.

In VPL2, as it is single thread, the Thymio only turns left and never become red. It execute the first one and then it is finished. So it is why David was saying it never go red and it will be hard to explain to student.

For me in this simple example 1, it is logic for me that it's behave like in VPL1. I think it is the position of Francesco. Orders matter but finally it can be explain to student specially if we show the generated code.

I will now test example 2. Lets see the difference with actual implementation and if we can agree if implementation of VPL1 it is ok or if we have to improve to be declarative (logique?).

mbonani commented 7 years ago

In VPL1: image The behavior is more complex and it is not working well in both case, often the robot go straight if central sensor became /x x 0x x\ even if it see still /1 1 0 x x \ . The problem come basically because we used "when" instead of "if". The logic of the behavior depends not of order of the line but more in which order happens the events. This example will normally bring the student to make the correction go forward only if / 0 0 0 0 0 \ . And then the behavior is working. image

Perhaps the "not care" state is less compatible with "when" and less intuitive for proximity sensor then for buttons. I have no clue, but perhaps do not allow "not care" state will help, a least in simple mode.

stephanemagnenat commented 7 years ago

Thank you all for these interesting elements. As @davidjsherman reminded us, the issue is that VPL (both 1 and 2) is currently not declarative, while it pretends to be in theory. So as noted by @motib, VPL is notionally parallel while in the implementation we have nasty side-effects such as breakage of symmetry as pointed out by David. This breakage of contract between the notional machine and the implementation is, from my observations, the main reason why it is difficult to write somewhat complex programs in VPL while it is very efficient to write simple ones.

I see the value of the semantic stochastic decision making suggested by David, or the averaging of actuator outputs, as these are two theoretically sound and non-biased interpretations of how to combine multiple matching rules (sampling and averaging). However, this presents two practical difficulties: 1. the implementation is clearly not trivial, 2. I am sure that it would be very difficult to teach teachers the proposed semantic.

@marvelous mentioned the idea of a replay function. It is very interesting and we tried this in our ITiCSE 2015 paper through augmented reality (video). One key observation from this work is that a replay feature is an added complexity in user interaction and, hence, it is challenging to make it seamless enough so that its added benefits offsets the cost of the increased cognitive load. I believe that with more modern AR techniques, such as Hololens, it might work well, but it is a matter of research outside the scope of VPL2 at that point.

Going back to the examples of David. In the various Thymio workshop I conducted, containing a line following and a labyrinth navigation task, children did write similar programs, ambiguities did arise, children were quite confused, and with the aid of the assistants they finally put black dots instead of ignore to avoid the ambiguities.

For all these reasons, and knowing that if we want to teach some serious programming concepts with Thymio we need the students to build a proper notional machine, I think that we should detect the possible ambiguities at compile teach and prevent the user to load a possibly-ambiguous program to the robot. This would correspond to the idea of @mbonani of not allowing "not care", but only when it leads to ambiguities.

@FrancescoMondada raised the interesting idea that if two lines have no action that affect the same actuators, they should be allowed even though they have conflicting events. I would be interested in the opinion of others on this point, especially from @marvelous.

Finally, I want to point out that we are talking about the core semantics of VPL that will affect thousands of teachers and even more children, so it is worth thinking in detail and coming with an implementation that really matches the notional machine. So, again, thanks for your contributions!

motib commented 7 years ago

the main reason why it is difficult to write somewhat complex programs in VPL while it is very efficient to write simple ones.

Isn't that the reason VPL exists?! Who would even want to write VPL programs with more than 5-10 pairs? When I worked extensively with Scratch, I found the same phenomenon: it is really fun for "small" programs, but once you have to scroll the screen to see the program, it stops being fun. That is a sign you need to find a more advanced software environment.

The only problem that I think needs solving is that of "don't cares" with the semantics of "when". As I noted before, a lot of my programs broke when the semantics was changed. So I am in favor of @mbonani's suggestion to forbid or at least discourage "don't cares".

stephanemagnenat commented 7 years ago

Isn't that the reason VPL exists?!

Yes but there is a gap, moderately-complex programs such as navigating a labyrinth are too complex to design because of the mismatch between the notional machine and the implementation.

So I am in favor of @mbonani's suggestion to forbid or at least discourage "don't cares".

Don't care make sense to only select some sensors, but they create a lot of confusion in case of potentially-ambiguous events. That is why I think we should detect these at compile time and force the user to select a non-ambiguous configuration (typically by setting the "don't care" to "not seeing"), which is what users end up doing anyway most of the time for their program to work, as otherwise they run into the problem of asymmetry of behaviour already mentioned above.

marvelous commented 7 years ago

For all these reasons, and knowing that if we want to teach some serious programming concepts with Thymio we need the students to build a proper notional machine, I think that we should detect the possible ambiguities at compile teach and prevent the user to load a possibly-ambiguous program to the robot. This would correspond to the idea of @mbonani of not allowing "not care", but only when it leads to ambiguities.

So what do you think about @davidjsherman's example 2? What could be an allowed solution that meets the user's expectations and how would you explain it to her?

@FrancescoMondada raised the interesting idea that if two lines have no action that affect the same actuators, they should be allowed even though they have conflicting events. I would be interested in the opinion of others on this point, especially from @marvelous.

From an implementation's point of vue, it doesn't seem complicated. To take the argument further, should we allow lines that have exactly the same events? In example 2, it does make sense to split line 5 in two lines with the same event.

stephanemagnenat commented 7 years ago

What could be an allowed solution that meets the user's expectations and how would you explain it to her?

Assuming we allow to have twice the same event, as long as there is no action conflict, this would be a solution:

/ 1 1 0 0 0 \  ->  150||50
/ 0 1 1 0 0  \  ->  300||0
/ 0 0 1 1 0 \  ->    0||300
/ 0 0 0 1 1 \  ->   50||150
/ 0 0 0 0 0 \  ->  200||200
/ _ 0 0 0 _ \  ->  top(0,31,0)
/ _ 0 1 0 _ \  ->  top(31,0,0)
/ _ 1 0 0 _ \  ->  top(15,15,0)
/ _ 0 0 1 _ \  ->  top(15,15,0)

Formally, we would define a program to be ambiguous, if there exists at least two lines in which the events unify (in the Prolog sense as pointed out by @motib) and that share at least a similar action (in the sense of action types as currently defined in VPL2: top_color, bottom_color, motor, sound). Similarly, a program is said to be valid if it is non-ambiguous.

If we do not allow twice the same event, a valid solution is more complicated and fails to capture as precisely the meaning of the user, as one needs to prevent unification of the colour clauses compared to the motor ones:

/ 1 1 0 0 0 \  ->  150||50
/ 0 1 1 0 0  \  ->  300||0
/ 0 0 1 1 0 \  ->    0||300
/ 0 0 0 1 1 \  ->   50||150
/ 0 0 0 0 0 \  ->  200||200 ; top(0,31,0)
/ _ 0 1 0 _ \  ->  top(31,0,0)
/ 0 1 0 0 0 \  ->  top(15,15,0)
/ 0 0 0 1 0 \  ->  top(15,15,0)

This example indeed shows the value of allowing twice the same event in the case of non-conflicting action. In that sense, the compiler would not verify event duplication, but directly ambiguity. It is better because it relates to the notional machine – and thus semantics – rather than syntax.

marvelous commented 7 years ago
/ 1 1 0 0 0 \  ->  150||50
/ 0 1 1 0 0 \  ->  300||0
/ 0 0 1 1 0 \  ->    0||300
/ 0 0 0 1 1 \  ->   50||150
/ 0 0 0 0 0 \  ->  200||200

The big issue I see with this solution is that the following sequence will not behave as the user intends:

/ 1 1 0 0 0 \  ->  150||50
/ 1 1 1 0 0 \  ->  no change of direction
/ 1 1 1 1 0 \  ->  no change of direction
/ 1 1 1 1 1 \  ->  no change of direction
/ 0 1 1 1 1 \  ->  no change of direction
/ 0 0 1 1 1 \  ->  still no change of direction!!!

an unambiguous solution for example 2 seems impractical to say the least.

stephanemagnenat commented 7 years ago

That is true. And indeed for this example, the solutions proposed by David, either averaging or sampling, are better.

So let us think a bit whether one of these could be feasible. I think that averaging is more predictable than sampling, because the effect of the action will take place at the same time the events trigger. We could collect all rules that match, combine all their actions, and use the result to write the actuators. Note that this is well defined for colors and motors, but not so much for sound (we could average the generated melody, it would be fun, but I am not sure that this is what we want). Moreover, there is a problem because of the when semantics: if one rule becomes true after the others, this rule will dominate. If we average, the if semantics would be more correct, that is, apply all rules that are currently true, and combine their results.

What we see is that the good solution seems to depend on the type of action. For continuous actions such as the wheels and the colors, an if semantics with some form of averaging or sampling seems the best. For sporadic actions such as sound, the when semantics with forbidden ambiguity at compile time seems the best. Note that we could also change the sound action to make it work well with if semantics, for instance if we just make it generate one note, whose pitch and intensity could be chosen by the programmer.

The averaging of commands leads to an interesting, although a bit spooky, thinking about states. Do we want to have a probability distribution over states? That, allied with if semantics would lead to a closed-form and consistent semantics for the whole VPL, but I am afraid that the corresponding notional machine would be non-trivial to build. However, it might be very interesting from a scientific point of view, and actually we might want to make a study on this (before deploying it in the real world). But of course, we do not need to have a fully probabilistic state machine. We can consider that all lines that do not specify a state change vote for staying in the current state, and then the next state is the one for which there is more vote.

@marvelous and @davidjsherman, what do you think about this analysis?

mbonani commented 7 years ago

All this make me think also that to understand what is going on the generated code is useful. Feedback from teacher also pointed often that VPL is good because you see the code. This is probably another issue but without the code it will be difficult to explain to pupils why it is working or not, this is more the case with the different propose solution. Perhaps VPL 1 is not declarative but the generated code is simple enough to understand and explain it.

stephanemagnenat commented 7 years ago

Feedback from teacher also pointed often that VPL is good because you see the code.

One elements that is bad for educational purposes with Thymio is that the API of the robot was designed to match the implementation, and not a clean interface for educational needs. For instance, there is no good educational reason why motors can be set with a variable while LEDs must be set through native functions. These are pure implementation details.

Perhaps VPL 1 is not declarative but the generated code is simple enough to understand and explain it.

It is a point indeed. However, I am not sure how much looking at the code does really help the student, or whether it mostly help the teachers. In any case, it would be interesting to understand more in which context users look at the generated code. As said before, the code is not of optimal educational value because the API is too low level.

stephanemagnenat commented 7 years ago

Also, I think that teachers resort to looking at the generated at least partially because the VPL1 implementation has side effects and biases, compared to the notional machine. It would be interesting to see how users would react without such implementation issues.

stephanemagnenat commented 7 years ago

So, let us think how actions would react to multiple matching rules, assuming an if semantics for the events:

action mixing rule
motor averaging
colors averaging
single note averaging
music score voting && start if not running
state change voting
IR comm voting

By voting, I mean that all active lines vote for the given action, and the result that has the majority wins, considering that "not executing the action" is also one option voted for.

Note that the average semantics would correct the problem seen in VPL1, that lead to the use of when (see this explanation):

[ 0 0 ]         ->   100 || 100
[ 1 _ ]         ->   100 || -100
[ _ 1 ]         ->  -100 || 100
/ _ _ 1 _ _ \   ->  -100 || -100

The following program will follow a track and stop when there is an obstacle in front.

The mismatch problem between tap/clap (which happen only once) and the other events still remains. Btw, these two should probably be unified, as I do not remember a case when they were used together to denote different things.

mbonani commented 7 years ago

considering that "not executing the action" is also one option voted for.

Is that meaning that if I have several event without this actions card set it is a "not executing the action" ? Most time with an if semantics it wil be the case.

The mismatch problem between tap/clap (which happen only once) and the other events still remains. Btw, these two should probably be unified, as I do not remember a case when they were used together to denote different things.

Clap -> my robot start Tap -> my robot stop

stephanemagnenat commented 7 years ago

Is that meaning that if I have several event without this actions card set it is a "not executing the action" ? Most time with an if semantics it will be the case.

It is an interesting point. I was considering this for voting actions. Whether we should consider it for averaging actions is a question. I tend to say no, because for such an action (motors, color), the non-appearance of the block means "don't care" for that action, while for voting actions (music score, state change), the non-appearance of the block means "do not do it".

marvelous commented 7 years ago
[ 0 0 ]         ->   100 || 100
[ 1 _ ]         ->   100 || -100
[ _ 1 ]         ->  -100 || 100
/ _ _ 1 _ _ \   ->  -100 || -100

The following program will follow a track and stop when there is an obstacle in front.

This ugly hack is a compelling argument for not trying to second-guess the user intent!

If the user first expresses a wrong solution:

[ 0 0 ]       ->   100 ||  100
[ 1 _ ]       ->   100 || -100
[ _ 1 ]       ->  -100 ||  100
/ _ _ 1 _ _ \ ->     0 ||    0

This solution seems way more simple to explain than averaging tricks:

/ _ _ 0 _ _ \ [ 0 0 ] ->   100 ||  100
/ _ _ 0 _ _ \ [ 1 _ ] ->   100 || -100
/ _ _ 0 _ _ \ [ _ 1 ] ->  -100 ||  100
/ _ _ 1 _ _ \         ->     0 ||    0

In this case, the proper solution is for the user to remove the ambiguity, like in example 1.

Your points about the if semantics are interesting. From the code point of view, setting the motor speed is instantaneous, but from the user point of view, it is a continuous action. #69 I also think that state changes should trigger an event, which would break many VPL1.4 programs. But all these are discussions for other issues.

stephanemagnenat commented 7 years ago

In this case, the proper solution is for the user to remove the ambiguity, like in example 1.

I agree, and resolving the problem this way is totally compatible with averaging, if we want to also deal with example 2.

Your points about the if semantics are interesting.

@motib, you implemented your tutorial both with if (for 1.3) and when (for 1.4) semantics. Which one would you say was more natural and led to the simplest notional machine?

I also think that state changes should trigger an event, which would break many VPL1.4 programs.

I think that anyway we'll implement states differently than in VPL 1.4, so I'm not worried for that.

marvelous commented 7 years ago

resolving the problem this way is totally compatible with averaging, if we want to also deal with example 2.

The solution is compatible with averaging, but the averaging method will probably confuse the user when she hits the ambiguous cases before reaching the solution.

stephanemagnenat commented 7 years ago

Note that the problem expressed above that led to the choice of when semantics, can be solved now easily with if semantics because we allow conjuctions of events, as pointed out by @marvelous, regardless of the question of averaging or ambiguity removal.

Regarding averaging, I think that there is an interesting and unique educational value of discussing the situation of multiple matching rules as pointed out by @davidjsherman. @miracet (Didier Roy), what do you think?

motib commented 7 years ago

First, I must admit that I haven't been following the details of this discussion for a while, but since @stephanemagnenat asked a question....

The programs in the tutorial were implemented before the change to "when". I'm not 100% sure, but I may have changed some of them to work with "when". It was quite unintuitive for simple programs, because "don't cares" (which is the default for prox sensors) had to be replaced with "not detected", requiring quite a few clicks.

stephanemagnenat commented 7 years ago

The solution is compatible with averaging, but the averaging method will probably confuse the user when she hits the ambiguous cases before reaching the solution.

This is true, I agree.

@motib in the case of your tutorial, would the example programs behave more naturally if there would be an averaging semantics in case of multiple line matches? I am thinking about the Braitenberg creatures for example. Please consider that conjunctions of multiple event blocks are available.