Software Correctness Indexed Processes SWEN224 2017-T2. David Streader Engineering & Computer Science Victoria University of Wellington
Review We have: Built sequential processes. Composed processes in parallel Synchronized events running in different processes Made events private by Hiding events Removing hidden events Simplifying processes Labeled processes
Learning Objectives Understand how to: Index Process states Index Process events How to build and model check small finite state approximations of infinite state systems. Small world assumption: most real world errors can be detected in a small world This assumption does not hold universally.
Revision Example: We are going to build a two place buffer from two one place buffers. To be able to validate that the construction is correct requires you to decide what the behavior of a one and two place buffer is. One place buffer Two place buffer Are the above acceptable arbiters of correctness
Labeling events Given two simple one place Buffers that continually perform events in then out build a two place buffer. We cannot use Buff||Buff as both events would synchronise First add label one to a Buffer with command one:Buff. This prepends one. to the start of each event name. Second rename the one.out to move with one:Buff/{move/one.out} giving:
Labeling events Build a two place buffer Btwo by composing and hiding the move event in two renamed buffers . (one:Buff/{move/one.out})||(two:Buff/{move/two.in})\{move}. Abstracting and simplifying simp(abs(Btwo)) gives: Is this a two place buffer?
Indexing Process State To consider a class of processes. For example an N place buffer. const N = 4 automata { Buff = B[0], B[i:0..N] = (when i< N in -> B[i+1] | when 0< i out ->B[i-1]). } const N = 4 sets the value of variable N – hence automata size B[i:0..N] = defines states 0 .. N when <guard> event -> Process is a conditional event
Indexed Processes (state) First we declare the index variable and bound its size Our example consists of a loop of coin events. The number of states and events in the loop is controlled by the index. C[i:1..N] are N processes where i has value 1,2,... N Recurring style <name> = Pin[1], Pin[i:<rng>] = … const N = 4 automata { Money = C[1], C[i:1..N] = (when(i<N) coin->C[i+1] | when(i==N) coin->C[1]). } 2 lines N states C[1] C[2]
Indexing events as well as state So far we have indexed the state space of processes. Indexes are like java variables they can be: Initialised Read written In addition we can pass values into events, but the input value can only be decided at run time. in[v:0..N] allows the value v to be input on the in event. out[v] outputs the value v when the out event is taken Show example:
Indexed processes and events We model a one place buffer that can hold values 2,3,4 The indexed in event are implicitly composed by choice. Buffer = (in[i:2..N] ->State[i]), // scope of i end at “,“ The indexed process State uses indexed out events State[x:2..N] = (out[x] -> Buffer). const N = 4 Buffer = (in[i:2..N] ->State[i]), State[x:2..N] = (out[x] -> Buffer).
Indexing for the lazy modeler Indexing is just a shorthand way of specifying a model that could be specified with out indexing The ability to see an automata greatly increases our confidence that we have defined the model we want We might want to build a large model e.g. a model where const N = 20 But large models can be very hard to understand. Hence view the model where const N = 3 and then change just this line and build.
Counter example Here none of the events are indexed but the number of states is controlled by the local index X Count = Cnt[0], Cnt[i:0..X] = ( when (i<X) inc->Cnt[i+1] | when (i>0) dec->Cnt[i-1] ).
The natural language problem Natural languages are: Very expressive Open to interpretation People do not read (elaborate) instructions Basic recipe for building indexed processes from a natural language specification. Step 1 find indexes and indexed states Step 2 find indexed events Step 3 find all events Step 4 build automata Step 5 inspect the automata and validate it against specification
From English to automata Closed doors are always locked. The door starts closed. The lock can hold any one of N codes. To open you need to input the correct code and after opening the door must close when the wrong code is input the door returns the start. Before using the door the code must be set. Step 1 find indexes and indexed states Step 2 find indexed events: Step 3 find all events Step 4 build automata Step 5 inspect the automata and validate it against specification
From English to automata Closed doors are always locked. The door starts closed. The lock can hold any one of N codes. To open you need to input the correct code and after opening the door must close when the wrong code is input the door returns the start. Before using the door the code must be set. Step 1 code is an index Lock in one of N states (codes) Lock[code:1..N ] = …… Lock[code]. code := ? output := code Information flow Output Input
From English to automata Closed doors are always locked. The door starts closed. The lock can hold any one of N codes. To open you need to input the correct code and after opening the door must close when the wrong code is input the door returns the start. Before using the door the code must be set. Step 2 find indexed events input[ ] setCode[ ] input[cd:1..N] …….. show[cd] cd := ? output := cd Information flow Output Input
From English to automata Closed doors are always locked. The door starts closed. The lock can hold any one of N codes. To open you need to input the correct code and after opening the door must close when the wrong code is input the door returns the start. Before using the door the code must be set. Step 3 find all events open[] close return setCode[ ]
From English to automata Closed doors are always locked. The door starts closed. The lock can hold any one of N codes. To open you need to input the correct code and after opening the door must close when the wrong code is input the door returns the start. Before using the door the code must be set. Step 4 build automata Lock = setCode [j:1..N] -> L[j], L[i:1..N] = open [k:1..N] -> ( when i==k close->L[i] | when i != k return ->Lock).
From English to automata Step 3 build automata when N = 2 Understand the information flow. Do you know the value of the code held by the lock when it is the state represented one of the nodes?
English to Cooker model Build a cooker that requires the time to first be set by a setTime event. The setTime event accepts integer t. The cooker then executes the cook event t times. Step 1 find indexed states and events: Cooker[time:1..N] setTime[t:1..N] Step 2 find all events cook setTime Step 3 build automata
English to Cooker model Specify Cook = setTime[t:1..N] -> C[t], Information flow C[n:0:N] = when n>0 -> C[n-1]. You can specify the automata then visually check the result. OR sketch the automata and then write the specification.
From English to automata Modeling a petrol pump. After the nozzle has been lifted the customer starts by inputting the required liters of petrol, from 1 to N. Each pump event delivers a liter. After delivering the required liters of petrol the nozzle is returned and the petrol paid for. The pump is now ready for the next customer. Step 1 index is liters Pump state is liter delivered P[l:1..N] Step 2 event start[s:1.N] is input Step 3 all events: lift, start[], pump, return, pay
Pay value not modeled Add return after lift Index acts like a variable What would it look like with indexed pay[s] (s is output)?
Pay value modeled Second variable
From English to automata The previous petrol pump design can be thought of as prepay but an alternative design is pump until you choose to stop or the tank is full and finally pay the amount owing hence pump must still be indexed by liters delivered Events: lift, starts, pump, return, pay[]
Pump and Pay With this model you can pump as much as you want and then pay for the petrol you took.
Pump and Pay Defining this pump is simpler in two respects the start event does not need to accept a parameter we do not need two parameters With indexed processes it my be easier to think about the syntax rather than the automata.
Indexed number of Processes NOT USED 2017
Indexed number of processes We have seen the ability to define N states and to define N events. In addition we can define N processes. These N processes are independent of each other and run in parallel. This independence is exemplified by a much simplified producer consumer design pattern. With N Producers of tasks each with it own consumers of the task. Producer 1 Producer 2 Producer N Consumer 1 Consumer 2 Consumer N
Indexed Processes Producer N Producer each synchronise on [i].task event
Messy Details 3 Producers and Consumers is very messy
Less Messy With just 2 Producers and Consumers there is still too much detail for easy understanding
A Simplified view Hiding all but the tasks Gives a very easy to understand view: