(************************************************************ * IMITATOR MODEL * * Coffee vending machine with drinker * * Description : Coffee vending machine; a single button is used to wake the machine up, and to add sugar. Then a cup, and coffee are delivered after a (parametric) time. Drinker: Work for some parametric time [p_work_min, p_work_max], then needs coffee. Asks for a coffee with a non-deterministic number of sugars in [0, MAX_SUGAR]. If does not get its coffee within p_patience_max, then gets mad. Variant of coffeeDrinker.imi, but chosing an arbitrary and unbounded number of sugars. * Correctness : The scientist never gets mad * Source : Own work * Author : Étienne André * Input by : Étienne André * * Created : 2011/01/21 * Fork from : coffeeDrinker.imi * Fork date : 2018/08/13 * Last modified : 2020/08/13 * * IMITATOR version: 3 ************************************************************) var (* Clocks *) x1, x2, y1, y2 : clock; (* Parameters *) (* time during which the button cannot be pressed after a pressure *) (* p_block_button, *) (* time during which one can add sugar *) p_add_sugar, (* time needed to prepare the coffee from the first button pressure *) p_coffee, (* interval of work without need for coffee *) p_work_min, p_work_max, (* Minimal interval of time between 2 consecutive pressures by the user *) p_press_min, (* time after which the drinker gets mad *) p_patience_max, : parameter; (* Discrete variables *) nb_sugar : discrete; (* Constants *) (* MAX_SUGAR = 2 : parameter; *) (************************************************************) automaton machine (************************************************************) synclabs: press, cup, coffee, sleep; loc idle: invariant True when True sync press do {x1 := 0, x2 := 0} goto add_sugar; loc add_sugar: invariant x2 <= p_add_sugar & x2 <= p_coffee when (*x1 >= p_block_button*)True sync press do {x1 := 0} goto add_sugar; when x2 = p_add_sugar sync cup do {} goto preparing_coffee; loc preparing_coffee: invariant x2 <= p_coffee (* when x2 = p_coffee sync coffee goto idle; *) when True sync press goto preparing_coffee; when x2 = p_coffee sync coffee do {x1 := 0} goto cdone; loc cdone: invariant x1 <= 10 when True sync press do {x1 := 0, x2 := 0} goto add_sugar; when x1 = 10 sync sleep goto idle; end (* machine *) (************************************************************) automaton researcher (************************************************************) synclabs: press, coffee; loc researching: invariant y1 <= p_work_max when y1 >= p_work_min sync press do {y1 := 0, y2 := 0, nb_sugar := 0} goto add_sugar; (*** TODO: an improvement would be to first nonderministically chose the number of sugars to add, and then to indeed add it (and get mad if it is impossible to get a coffee with this number); otherwise, the scientist may not get the desired number of sugards depending on the relationship between p_press_min and p_add_sugar ***) loc add_sugar: invariant y2 <= p_patience_max (* Can always add more sugar *) when y1 >= p_press_min sync press do {y1 := 0, nb_sugar := nb_sugar + 1} goto add_sugar; (* Can also non-deterministically stop adding sugar and wait for coffee *) when True goto wait_coffee; when y2 = p_patience_max goto mad; loc wait_coffee: invariant y2 <= p_patience_max when y2 < p_patience_max sync coffee do {y1 := 0, y2 := 0} goto researching; when y2 = p_patience_max goto mad; loc mad: invariant True end (* researcher *) (************************************************************) (* Initial state *) (************************************************************) init := (*------------------------------------------------------------ INITIAL LOCATION ------------------------------------------------------------*) & loc[machine] = idle & loc[researcher] = researching (*------------------------------------------------------------ INITIAL CLOCKS ------------------------------------------------------------*) & x1 = 0 & x2 = 0 & y1 >= 0 & y1 <= p_work_max (*------------------------------------------------------------ INITIAL DISCRETE ------------------------------------------------------------*) & nb_sugar = 0 (*------------------------------------------------------------ PARAMETER CONSTRAINTS ------------------------------------------------------------*) (* & p_block_button >= 0 *) & p_add_sugar >= 0 & p_coffee >= 0 & p_press_min >= 0 & p_work_min >= 0 & p_work_min <= p_work_max & p_patience_max >= 0 ; (************************************************************) (* Property specification *) (************************************************************) property := unreachable loc[researcher] = mad; projectresult(p_patience_max, p_press_min, p_coffee); (************************************************************) (* The end *) (************************************************************) end