If and switch expressions

In some models one wants to produce different values under different circumstances. Or one needs to convert from one type to another type. if and switch expressions provide means to do this in a concise manner. This lesson provides an introduction to both these expressions. For more practical examples, see the simulation model of the synthesis-based engineering example elsewhere in the documentation.

If expression

Consider the following expression:

if x > 0: 1 elif x < 0: -1 else 0 end

This expression takes a real number x and produces its sign. The if expression is used to detect the different situations, and to produce the correct result in each of those situations.

An if expression always consist of the if and the else parts. In between can optionally be any number of elif parts:

if x > 0: 1 elif x < 0: -1 else 0 end
if x > 0: 1 else 0 end
if x > 0: 1 elif x < -10: -2 elif x < 0: -1 else 0 end

If the 'guard predicate' of an if or elif (the expression before the :) holds, that alternative is chosen. In the following example, if x has a value of 2 and y a value of 3, then value -2.8 is produced:

if x > 0 and y = 2: 1.5 elif x > 0 and y != 2 or x < 0: -2.8 else 0.1 end

The if and elif alternatives are considered in order. The first alternative that has a guard that holds determines what value is produced by the if expression. Consider the following if expression:

if x > 0: 1.5 elif x > 0: -2.8 else 0.1 end

For any value x > 0, this if expression produces 1.5. It will never produce -2.8, as the if part is considered before the elif part.

Switch expression

Similar to an if expression, a switch expression can be used to produce different values under different circumstances. Consider the following partial CIF model:

enum mode = OFF, ON1, ON2, ON3, DISCONNECTED;
automaton rotary_switch:
  disc mode m = OFF;
  ...
end

alg int speed = switch rotary_switch.m:
                  case ON1: 5
                  case ON2: 10
                  case ON3: 15
                  else      0
                end;
end

This switch expression takes the operation mode rotary_switch.m and provides the speed corresponding to that mode. If the value of m matches one of the cases, the switch expression will produce the corresponding value. For example, if m has value ON2, this switch expression produces 10. If none of the cases match, the value of the else case is taken. For example, if m has value DISCONNECTED, this switch expression produces 0. Note that multiple values can be captured by the else case, i.e., you do not have to cover each possible value with a separate case.

One can use different kinds of types as long as the types of the cases match the type of the switch expression. In the example above, m is of type mode, which is an enumeration. Hence all cases should be of type mode as well. Below is an example using a ranged integer in the switch expression:

alg int[0,2] num_products;

alg string display_text = switch num_products:
                            case 0: "There are no products in the buffer."
                            case 1: "There is one product in the buffer."
                            case 2: "There are two products in the buffer."
                          end;

One can also use an automaton as a variable of the switch expression, where the cases have to be locations of that automaton:

automaton controller:
  location accelerate: ...
  location decelerate: ...
  location steady: ...
end

alg int acceleration = switch controller:
                         case accelerate:  5
                         case decelerate: -3
                         case steady:      0
                       end;

Note that in this switch expression we omitted the else case, as the three cases together already cover all possible locations of automaton controller.

It is possible to rewrite a switch expression into an if expression (the other way around is not always possible). This rewrite can be automated using a CIF to CIF transformation.