diff --git a/doc/_data/contents.yml b/doc/_data/contents.yml index dc90e5b..2fc0896 100644 --- a/doc/_data/contents.yml +++ b/doc/_data/contents.yml @@ -2,4 +2,6 @@ docs: - install - language - +- title: IVy by example + docs: + - examples/client_server_example \ No newline at end of file diff --git a/doc/examples/client_server_example.md b/doc/examples/client_server_example.md new file mode 100644 index 0000000..5c7d74e --- /dev/null +++ b/doc/examples/client_server_example.md @@ -0,0 +1,188 @@ +--- +layout: page +title: Invariants +--- + +The most basic technique for proving correctness in IVy is to +construct an inductive invariant. IVy makes this easier by providing +tools to visualize the failures of inductive proofs and suggest +possible refinements to the proof. + +An *safety invariant* is a formula or a set of formulas that has the +following properties: + +- *initiation*: It is true in all initial states of the program. + +- *safety*: If it is true in a program state, then no exported action +can cause an assertion failure starting in that state. + +- *consecution*: If it is true in a state, then after executing any +exported action, the formula remains true. + +In this example, we will use IVy's CTI method. CTI stands for +"counter-example to induction". If one of the above conditions fails, +IVy tries to construct a *simple* example of the failure. We can +attempt to correct the proof by *generalizing* from this +counter-example. + +# An abstract protocol model + +The following is a very abstract model of a protocol that establishes +connections between clients and servers. Each server has a semaphore +that is used to guarantee that at any time at most one client can be +connected to the server. + + #lang ivy1.5 + + type client + type server + + relation link(X:client, Y:server) + relation semaphore(X:server) + + init semaphore(W) & ~link(X,Y) + + action connect(x:client,y:server) = { + assume semaphore(y); + link(x,y) := true; + semaphore(y) := false + } + + action disconnect(x:client,y:server) = { + assume link(x,y); + link(x,y) := false; + semaphore(y) := true + } + + export connect + export disconnect + +This program declares two types `client` and `server`. The state of +the protocol model consists of two relations. The relation `link` +tells us which clients are connected to which servers, while +`semaphore` tells us which servers have their semaphore "up". + +The program exports two actions to the environment: `connect` and +`disconnect`. The `connect` actions creates a link from client `x` to +server `y`, putting the server's semaphore down. Notice that `connect` +assumes the server's semaphore is initially up. The `disconnect` +action removes a link and puts the semaphore up. The two `export` +declarations at the end tell us that the environment may call +`connect` and `disconnect` in arbitrary sequence, though it must obey +the stated assumptions. + +## Safety and invariant conjectures + +A program is *safe* if the environment cannot call it in any way that +causes an assertion to be false. There are various way to use +assertions to specify desired safety properties of a program. A simple +one is to add a test action that asserts some property of the program +state. In the client/server example above, we might specify that no +two distinct clients can be connected to a single server using the +following test action: + + action test = { + assert ~(X ~= Z & link(X,Y) & link(Z,Y)) + } + + export test + +The assertion is implicitly universally quantified over (distinct) +clients `X` and `Z` and server `Y`. + +# Discovering a safety invariant + +To try to construct a safety invariant for this program, we run IVy in +its CTI mode. Here is the command line: + + $ ivy ui=cti client_server_example.ivy + +This produces the following rather uninformative display: + +![IVy screenshot](images/client_server1.png) + +Since we didn't specify any conjectured invariant formulas in the +input file, IVy starts with the empty set of conjectures. This +trivially satisfies the initiation and consecution conditions, but +probably won't satisfy the saftey condition. We'll try anyway and see +what goes wrong. We select the "check inductiveness" operation, like this: + +![IVy screenshot](images/client_server2.png) + +Here's what IVY says: + +![IVy screenshot](images/client_server3.png) + +When we click OK, we see the following display: + +![IVy screenshot](images/client_server4.png) + +On the left-hand side of the display, we see a transition of the +program from a state labeled `0` to a state labeled `1`. The action +labeling the transition arrow can tell us seomthing about hwo we get +from state `0` to state `1` (an in particular, how the assertion in +our program fails). For the moment, though, let's concentrate on the +right-hand side. Here, we see a representation of state `0`, the one just +before the asertion failure. It shows one server (arbitrarily numbered `0`) +and two clients (numbered `0` and `1`). The checkboxes on the right allow us to +display further information about the state. For example, let's check the box +next to `link(X,Y)` under the label `+`. Here's what we get: + +![IVy screenshot](images/client_server5.png) + +The red arrows show the link relationships between the clients and the +server (notice that on the right, the relation `link(X,Y)` is in red). +This is condition that causes our assertion to fail when the `test` +action is executed. + +This situation is unrealistic. That is, a cluster of two clients and a +server as shown should never occur. We will conjecture that in fact +thsi 'bad pattern' never occurs. To do this we select the `Gather` option +from the `Conjecture` menu. When then see the following: + +![IVy screenshot](images/client_server6.png) + +IVy has collect three facts about the displayed state, shown under the +heading 'Constraints'. These facts are a logical representation of the +bad pattern we observed graphically. Two of them are obvious: the facts +`link(0,0)` and `link(1,0)` say that both clients are linked to the server. +Implicit in the grpahic, though, is a third fact: `0:client ~= 1:client`. +This says that `0` and `1` name distinct clients. + +Also notice that the nodes and the arcs in the graph have been highlighted +to indicate that they are all used in the listed facts. + +Since think that this particular pattern should never occur, we will generalize +it to produce a *conjecture* about the program state. Choosing the `Strengthen` option +from the `Conjecture` menu, we see: + +![IVy screenshot](images/client_server7.png) + +IVy is suggesting to add this fact to the list of conjectured invariants: + + ForAll CL0:client, CL1:client, SE0:server. ~(link(CL0,SE0) & link(CL1,SE0) & CL0 ~= CL1 + +This says that there is are no clients `CL0` and `CL1` and server +`SE0` matching our bad pattern. In other words, the bad pattern +occurrs nowhere in our program state, no matter how many clients and +servers there are. This is a simple generalization from our +counterexample. + +We click OK, adding this formula to our (thus far empty) list of +conjectures. Of course this conjecture is a trivial one. It just says +that the formula in our assertion is always true. + +We can now try checking inductiveness again with our new conjecture. +Here is what IVy says: + +![IVy screenshot](images/client_server8.png) + +It is telling us that our new conjecture fails the consecution test. +When we click OK, we see the counter-example to induction: + +![IVy screenshot](images/client_server9.png) + +IVy has already displayed the `link` relation, since it occurs in the +conjecture. + + diff --git a/doc/examples/images/client_server1.png b/doc/examples/images/client_server1.png new file mode 100644 index 0000000..a85bdae Binary files /dev/null and b/doc/examples/images/client_server1.png differ diff --git a/doc/examples/images/client_server2.png b/doc/examples/images/client_server2.png new file mode 100644 index 0000000..c88961c Binary files /dev/null and b/doc/examples/images/client_server2.png differ diff --git a/doc/examples/images/client_server3.png b/doc/examples/images/client_server3.png new file mode 100644 index 0000000..ab917e5 Binary files /dev/null and b/doc/examples/images/client_server3.png differ diff --git a/doc/examples/images/client_server4.png b/doc/examples/images/client_server4.png new file mode 100644 index 0000000..aeec0eb Binary files /dev/null and b/doc/examples/images/client_server4.png differ diff --git a/doc/examples/images/client_server5.png b/doc/examples/images/client_server5.png new file mode 100644 index 0000000..1da3a6f Binary files /dev/null and b/doc/examples/images/client_server5.png differ diff --git a/doc/examples/images/client_server6.png b/doc/examples/images/client_server6.png new file mode 100644 index 0000000..d57480b Binary files /dev/null and b/doc/examples/images/client_server6.png differ diff --git a/doc/examples/images/client_server7.png b/doc/examples/images/client_server7.png new file mode 100644 index 0000000..2218799 Binary files /dev/null and b/doc/examples/images/client_server7.png differ diff --git a/doc/examples/images/client_server8.png b/doc/examples/images/client_server8.png new file mode 100644 index 0000000..d1e9f84 Binary files /dev/null and b/doc/examples/images/client_server8.png differ diff --git a/doc/examples/images/client_server9.png b/doc/examples/images/client_server9.png new file mode 100644 index 0000000..3aac9a6 Binary files /dev/null and b/doc/examples/images/client_server9.png differ