Formal Methods

1 / 30

# Formal Methods - PowerPoint PPT Presentation

Formal Methods. Isn’t this really getting old?. Inheritance in Object Z. Before we discuss deferred refinement, we will look at the specification of a small system containing inheritance and some other system specification aspects we have not yet seen.

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Formal Methods' - yardley-rosario

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Formal Methods

Isn’t this really getting old?

Inheritance in Object Z

Before we discuss deferred refinement, we will look at the specification of a small system containing inheritance and some other system specification aspects we have not yet seen.

We will develop a small set of object structures culminating in the specification of an abstract generic stack.

Inheritance in Object Z

Stack [T]

|max : N

Take a simple object structure such as a stack. We should, by now, be able to specify one using Object Z fairly easily.

items: seq T

# items ≤ max

Note: the operation “Top” and the history invariant have been omitted.

INIT

items =< >

Push

• (items)
• item?: T

#items < max

items’ = <item?>^items

Pop

• (items)
• item!: T

items ≠ < >

items = <item!>^items’

Inheritance in Object Z

IndexedStack [T]

|max : N

Now let us define an “IndexedStack”.

This is a stack with a curser.

items: seq T  index : N1

# items ≤ max  items≠ < >index  dom items

INIT

items =< >

could be written with a “;” instead of “”, or on two different lines

SetIndex

• (index)
• n?: N1

“pop” and “top” can also be similarly written and are omitted as is the history invariant.

n?  dom items

index’ = n?

Push

• (items,index)
• item?: T

#items < max

items =<item!>^items’items≠ < >index’=index+1

Inheritance in Object Z

IndexedStack [T]

Or, we could do the following:

Stack[T]

index : N1

items≠ < >index  dom items

INIT

items =< >

SetIndex

• (index)
• n?: N1

n?  dom items

index’ = n?

Push

• (index)

items ≠ < >index’=index+1

Inheritance in Object Z

Here is an example of a “DoublePushStack”.

This is possible but inadvisable from a software engineering principles of good design perspective, as this is an example of “Specification” inheritance (not “generalization”

DoublePushStack[T]

Stack[T] redef Push

Push

• (items)
• item? :T

#items < max-1

items’ = <item?,item?>^items

Deferred Refinement

Deferred refinement was the second approach to refinement that we had set out to examine.

You will recall that in direct refinement the specification is refined into their corresponding program design in a single step; as we saw with the library example so far.

In deferred refinement, the first refinement cycle will result in a new – more explicit – specification, which is then further refined and so on, resulting in a related and provably consequent sequence of documents finally yielding an implementable design.

Deferred Refinement

A database check-pointing system

A database, in the most generic, is defined as a function from addresses to pages of data. We shall use this definition to commence our work.

We introduce ADDR and PAGE as types. They may be classes developed or to be developed elsewhere or basic types (probably the former). [ADDR, PAGE]

We define DATABASE as the abbreviation for all the functions from ADDR to PAGE.

Deferred Refinement

Let us compose a system that, from the user’s viewpoint, has two versions of the database. The state space will be something like:

CheckSys

working: DATABASE

backup : DATABASE

This says that the two observations working and backup may be any databases at all and need not be related in any way. Of course we will build some relationship between them later.

Most operations affect only the working database. For example:

Deferred Refinement

Access

ΞCheckSys

p! : PAGE

p! = working(a?)

This operation takes an address a? as input and produces as its output p! the page stored at that address. Neither version of the database changes.

Deferred Refinement

It is also possible to update the working database with a new page:

Update

 CheckSys

p? : PAGE

working’= working {a? p?}

backup’ = backup

Note:

Now the two versions are no longer identical – if they were at all

Deferred Refinement

We can “Synch” the two database copies. This is a Check Point

CheckPoint

 CheckSys

working’= working

backup’ = working

We can also restore the working database to its state at the last check point.

Restore

 CheckSys

working’= backup

backup’ = backup

Deferred Refinement

This completes the specification! Now we commence the refinement process.

At first we might want to keep two copies of the database, so implementing the specification directly.

Experience however tells us that copying the entire database is a very expensive operation particularly if check points are taken frequently.

A better idea might be to keep one complete copy and a “delta”, a record of changes since the creation of this master copy.

Deferred Refinement

The master copy is thus only a single database now:

Master

master: DATABASE

The record changes made since last checkpoint is a partial function from addresses to pages: it is partial because not every page will have been updated since last checkpoint.

Changes

The concrete state space is described by putting these two parts together:

Deferred Refinement

CheckSys1

Master

Changes

How does this concrete state space mirror our original work?

Basically, the master database is what we described as the backup and the working database is master changes, the result of updating the master copy with the recorded changes. Let us record this in a schema:

Deferred Refinement

CheckSys

Checksys1

backup = master

working= master changes

To remind you, the notation:

means that a function (in this case working) agrees with master everywhere except in the domain of changes, where it agrees with changes.

master changes

Deferred Refinement

Now let us attempt to implement some operations:

Accessing a page at address a? should return a page from the working copy according to:

working (a?)= (master changes)(a?)

working = master changes

So from here to a valid specification is a small step.

Deferred Refinement

Access1

ΞCheckSys1

p! : PAGE

p!= (master changes)(a?)

But we can do a little better: if a? dom changes, then:

And if a?  dom changes, then

(master changes)(a?) = changes(a?)

(master changes)(a?) = master(a?)

Deferred Refinement

So we now know that we have a conditional:

If there are no changes, we return the master, if there are changes, we update the master and then return it.

Access2

ΞCheckSys1

p! : PAGE

r! : REPORT

(a?  dom changes  p!= changes(a?)  r! = ok) 

(a?  dom changes  p!= master(a?)  r! = not_present)

Deferred Refinement

We could of course write the specification slightly differently as:

Access2

ΞCheckSys1

p! : PAGE

r!: REPORT

((a?  dom changes)((p!= changes(a?)  r! = ok)) 

((a?  dom changes) ((p!= master(a?)  r! = not_present))

The second specification is closer to an implementation, the first closer to the logic we need to prove the correctness of our derivations later in the process. Either one would be fine.

Deferred Refinement

Observing the symmetry, we could write:

Access2

ΞCheckSys1

p! : PAGE

r :== REPORT 

GetChanges == ((((a?  dom changes))  ((p!= changes)(a?)) (r! = ok )) 

(r! = not_present)) 

ReadMaster == ((r! = not_present) ( p!=master(a?)))

Deferred Refinement

Now we can implement:

var r:REPORT

begin

GetChange(a,p,r);

if r != ok then

end;

Of course we now need to write GetChanges and ReadMaster, but we basically have them.

Deferred Refinement

Directly from slide 18;

GetChanges

ΞChanges

p! : PAGE

r!: REPORT

(((a?  dom changes)) ( ((p!= changes)(a?)) (r! = ok )) 

(r! = not_present))

Deferred Refinement

ΞMaster

p! : PAGE

p!= master(a?)

begin

p := master(a);

end;

Deferred Refinement

For Update, we need backup’ = backup, so

master’ = backup’ = backup = master, and

working’= working {a? p?}; so we want:

Luckily, (f g) h =f (g h)

So, if we let changes’ = changes {a? p?}, then:

(master changes){a? p?}

master’ changes’ =

working’= working {a? p?} [from Update]

=

= master (changes {a? p?}) [associativity]

= master changes’ [from Update1]

Deferred Refinement

So, update1 must be:

Update1

 CheckSys1

p! : PAGE

changes’= changes {a? p!}

master’ = master

Implementation left as exercise

Deferred Refinement

Similarly and without proof (left as an exercise);

CheckPoint1

 CheckSys1

master’ = master changes

changes’=

We can of course implement this in two functions, one perhaps called WritetoMaster(changes) and one as ResettoNull(changes)

Deferred Refinement

What about the Restore function? Let us recall its specification:

Restore

 CheckSys

working’= backup

backup’ = backup

We want backup’=backup; so we need master’ = master; so as in Update1, again we want:

This time, because working’ = backup and changes’ must be null,

master’ changes’ =master’

Deferred Refinement

The condition is as before:

Restore1

 CheckSys1

master’ = master

changes’=

We can establish this by a simple call to ResettoNull(changes)

The next phase of the development (next refinement iteration) would commence in order to decide on the concrete implementation of WritetoMaster(changes); ResettoNull(changes); GetChanges(a,p,r); etc.

One set of these operate on the master part, another on changes

Deferred Refinement

These could form two independent modules developed independently, perhaps even by different teams.

The next iteration would require selection of data and object structures to represent the various operations, perhaps for instance for master, we choose an array, or maybe a linked list of pages stored on secondary storage, and changes may be a hash table held in main memory. Of course these accesses need to be written.

They are not as hard as they seem.