Keywords

These keywords were added by machine and not by the authors. This process is experimental and the keywords may be updated as the learning algorithm improves.

1 Whence the Cause?

Mathematical reasoning may be regarded rather schematically as the exercise of a combination of two facilities, which we may call intuition and ingenuity.

– Alan M. Turing

The Purpose of Ordinal Logics (1938)

1.1 History

The computing pioneer Alan Turing (1912–1954) [13, 22] and the physicist Albert Einstein (1879–1955), who died only a year after Turing although after a considerably longer lifespan, are two of the western scientists who are celebrated with busts on the campus of Southwestern University in Chongqing, China (see Fig. 1). Einstein is of course extremely well-known internationally, but Turing has been less well-known until more recently when his achievements have become increasingly visible to the public. He is considered by many to be the founding father of modern computer science with his 1936/7 paper on the Entscheidungsproblem (“decision problem” in German), establishing what is computable through the theoretical computing device that has become known as a Turing Machine [42]. This is an abstract model of a computing machine that is useful for demonstrating what is and what is not computable. This astoundingly novel approach has had a profound effect on the theory of computation subsequently, effectively founding the field of theoretical computer science.

Fig. 1.
figure 1

Busts of Alan Turing and Albert Einstein on the campus of Southwest University, Chongqing, China. (Photographs by Jonathan Bowen.)

Turing produced what is considered by many as the first paper on proving a program correct [43]. However, sadly this short paper had little impact on the development of formality in computing until it was rediscovered and evaluated in its historical context much later [34]. Instead, Tony Hoare’s much later 1969 paper on an axiomatic basis for computer programming, introducing Hoare logic and assertions, was a turning point in providing a formal approach to program proving [29].

Formal methods [18] emerged during the 1970s as a mathematically-based approach to software development. Jean-Raymond Abrial’s 1974 paper on data semantics [1] was in hindsight a seminar paper leading to the development of the Z notation for the formal specification of computer-based systems. In the early 1980s, Abrial visited the Programming Research Group (PRG) in the Oxford University Computing Laboratory (OUCL) and sowed the seeds for thedevelopment of the Z notation there. A Z course was established for bothacademics and industry. Projects such as the Distributed Computing Software Project used Z to specify network services at OUCL [15, 24]. A series of Z User Meetings was established, first in Oxford from 1986, with written proceedings from 1987 [5], then around the UK from 1992 [36], and finally internationally from 1998 [14].

A “Z Reference Manual” (ZRM) was published as a book originally in 1989, with a second edition in 1992, and further revisions online in 2001 [39]. This was and even remains a de facto standard, with an associated type-checker, [40]. However, an ISO/IEC standard with a formal semantics written in the Z notation itself was issued in 2002 [32]. The development of a formal semantics revealed some issues in Z that were clarified in the final semantics in the ISO/IEC standard [27].

Turing is associated with Cambridge University and later Manchester University. There is no known record of him ever having even visited Oxford University. However, Turing did liaise with Christopher Strachey (1916–1975), at one time a teacher at Harrow School, but also an expert early programmer. His program for the game of draughts impressed Turing. Strachey went on to found the Programming Research Group at Oxford in the 1960s, where he developed denotational semantics with colleagues there. Strachey’s untimely death in 1975 led to the appointment of Tony Hoare as the next head of the PRG. It was Hoare who fostered a suitable environment at Oxford for the Z notation to emerge and flourish in the 1980s and 1990s.

1.2 Background

The Z notation is an industrial-strength formal specification notation based on typed set theory and first order predicate logic, used in the specification of discrete computer-based systems [10, 39]. As well as standard mathematical operators, Z also includes a number of additional operators that have proved to be useful for specifications in practice, using more specialised sets such as relations, functions, and sequences. In addition to the mathematical notation, Z also includes a schema notation that collects the mathematical description into schema boxes containing declarations and predicates. These schemas may be combined to form larger specifications using schema operators that largely match logical operators, aiding the structuring of large specifications at an industrial scale.

This chapter includes a description of an industrially used course that covers the mathematical and schema notation of Z. Delivery of the course is in the form of lectures interspersed with paper-and-pencil exercises. The course is based around an ongoing case study example and finished with a further example for study. Previous experience of standard mathematical set theory and predicate logic is helpful although not essential.

1.3 Brief Survey

Formal methods are useful for improving software engineering where high integrity is desirable or required [18, 19, 28]. Examples of real industrial use are available [2, 3, 25]. There are a number of formal methods available with various strengths – and weaknesses – depending on the situation in which they are applied. See http://formalmethods.wikia.com for a wiki with information on formal methods in general and the Z notation in particular. Z’s strength is its use as a general purpose specification language in a human-readable form, interspersed with informal text, that can be scaled up to an industrial level. A weakness is its lack of good tools.

Z can be used for formal specification with the aim of designing and documenting mainly software but also hardware systems [6]. For example, Z has been used to specify microprocessor instruction sets [4]. It can also be used to specify software tools [7] and even window-based user interfaces [8].

Z is not executable in the general case, although an executable semantics for Z has been explored [20]. It is possible to embed Z within other formal systems. For example, see a shallow embedding of Z in HOL (Higher Order Logic) [16].

Z has good type-checking support, notably the type-checker [40] based on the Z Reference Manual [39]. This is based around the document preparation system, widely used in academia. There are a number of style files available to allow formatting of the Z symbols and schema structures. These include zed.sty (the original style file), fuzz.sty (designed for use with ), zed-csp.sty (also including support for CSP [30]), and oz.sty (supporting the object-oriented extension of Z, Object-Z [38]). All these styles are essentially compatible with the core parts of the Z notation. This chapter has been formatted using zed-csp.sty, mainly because it is very comprehensive for the Z glossary in Appendix A.

is not widely used in industrial, where Word is much more common. There is a Z Word Tools plug-in for Word that allows Z symbols and schemas to be written in Word using an additional menu entry [26]. It also integrates the type-check to allow convenient type-checking of Z from within Word. Z has the potential to allow proofs, either at an informal level, or with tool support. Leading Z proof tools include Z/EVES [37] and ProofPower [33]. However, learning to use such a tool effectively requires a significant amount of time and effort, longer than is normally available on an industrial project,

Despite the issues of proof support for Z, a Z specification is still extremely useful for another important part of the development process in industrial-scale projects. It can be used to aid much more effective and comprehensive testing of a software artefact [21, 23, 31, 41], helping to ensure more complete coverage of branches in a program for example. It can even be used to specify testing criteria, which are often defined in a rather loose way, in a more precise manner [44, 45].

1.4 Overview of Z Structuring

The Z notation includes mathematics based on logic and set theory (see a glossary in Appendix A) together with the schema box structuring notation. It is the latter than makes Z powerful and useful for very large specifications (potentially consisting of thousands of pages) as well as small specifications, as typically presented by academics for didactic purposes. In this section we present some of the important basic aspects of a Z specification, especially with respect to structuring using schemas.

All Z specifications have the set of integers (\(\mathbb {Z}\)) included by default as a given set, with the standard arithmetic operators available. Additional given sets (or basic types) may be specified as needed, providing distinct types of sets from which more complex abstract data structures can be constructed. For example, to declare given sets X and Y, the following could be included at the start of a Z specification:

figure a

A Z schema has the form of a name (used to reference it later in the specification), a declaration part, and a predicate part that optionally relates components that have been declared in the schema (defaulting to true if omitted). For example, the following simple schema T declares an integer n with no constraints on its value:

figure b

It is possible to include a schema within another schema. For example, the following schema S includes the declarations and predicates of T. It also declares an additional set x and constrains the value of n to be the size of the set (an “invariant” predicate for the state schema S):

figure c

Note that \(\mathbb {P}\) indicates a power set (the set of all subsets of X in this case). x is drawn from this set (i.e., it is some subset of X, possibly the empty set \(\emptyset \), possible the full set X, or somewhere in between). The complete version of S if the included schema T is expanded is as follows:

figure d

Schemas may be “decorated” with appended subscripts and superscripts. The most normal decoration is the prime (or “dash”, \('\)), used by convention to indicate the “after state” of an operation schema (with a matching unprimed “before state”). All the components of the schema \(S'\) are also renamed with an appended prime (i.e., \(n'\) and \(x'\) in this simple example). Thus \(S'\) expands to:

figure e

In a state-based Z specification, the system is modelled as a series of operations (with related before and after states) that change the state of the system. For the system to start in the first place, there needs to be an initial state that is the system state, but normally together with some initial constraints (specified as predicates). Since this is the state after initialisation, it is normally specified in terms of an after state, namely \(S'\) in this example:

figure f

The constraint that \(n'\) is zero means that the size of \(x'\) is also zero and thus \(x'\) is empty. The predicate \(x' = \emptyset \) could equally well have been used.

For an operation schema in Z, a before state (undecorated) and an after state (decorated with primes) are related together. The most general operation, where the after state may take on any arbitrary value with respect to the before state, can be specified using schema inclusion as follows with the example S state schema:

figure g

This expands to:

figure h

Note that predicates on separate lines in a schema are joined with logical conjunction by default.

Most operation schemas in Z will include this general change of state together with further constraining predicates relating the after-state components (here \(n'\) and \(x'\)) with the before-state components (here n and x). Since the ChangeofState schema above is likely to be useful in a number of operation schemas in practice and since a real Z specification may specify operations on a number of sub-states that can later be combined into a complete system, there is a convention that a schema named \(\varDelta S\) (in the case of the S schema for example) is automatically available for the specification, with the same meaning as ChangeOfState above.

For the specification of operations, typically these may have inputs and outputs as well as the change of state. Inputs and outputs are conventionally indicated with an appended “?” and “!” respectively. So, as an example, consider an operation to add an input element e? to the set x:

figure i

Here there is a “precondition” predicate that e? is not already a member of the set x, There is also a “postcondition” predicate meaning that the set \(x'\) is the original set x with the element e? added to it. Note that the value of \(n'\) has not been specified explicitly, but implicitly it has a value of the size of the set \(x'\) due to the invariant predicate in \(S'\). The full expanded version of AddOp is as follows:

figure j

Sometimes operation schemas do not actually change the state of the system, for example in status operations where part of the state is returned as an output. Z includes a convention similar to the \(\varDelta \) convention, with matching before and after states where the values of the matching before and after components maintain their value. For example in this case:

figure k

Similarly to the \(\varDelta \) convention described earlier, there is a convention that a schema named \(\varXi S\) (again for example) is automatically available within the specification, having the same meaning as NoChangeOfState above. So in the running example, for a status operation that returns, using the output n!, the size of the set x (which is always constrained to be the same is n), the following status operation scheme could be specified:

figure l

This could be expanded as:

figure m

As can be seen, there is much clutter in the expanded version of the schema that obscures its actual purpose. Thus the use of schema inclusion is a very important part of the structuring techniques used by Z in practice, making the specification much shorter, less repetitive, and more readable.

There are further features for combining schemas, using operators that match the logical operators, but the introduction above should be sufficient for non-experts in Z to follow the example questions and answers in the next section.

2 Whither the Course?

Teaching to unsuspecting youngsters the effective use of formal methods is one of the joys of life because it is so extremely rewarding.

– Edsger W. Dijkstra (1930–2002)

A. M. Turing Award winner in 1972

There have been many Z courses over the years, since the original one at Oxford University started in the 1980s, initially inspired by Jean-Raymond Abrial (see Fig. 2) and later developed as a course for academic and industry, as well as being presented on the Masters degree course on Computation at the Programming Research Group there. Subsequently many universities incorporated Z into their undergraduate Computer Science degree programmes [35]. and it continues to be used for teaching, especially in software engineering courses, to this day.

Fig. 2.
figure 2

The front page of the hand-written notes on the Z course during the 1980s at the Programming Research Group, Oxford University. (Drawing by Ib Sørensen, from an idea by Bernard Sufrin.)

In addition to academic courses on Z, industrial courses have also developed for training practitioners in software engineering. On of these was at Praxis (later Altran Praxis and now Altran UK). The course, written in the troff document markup language of UNIX, is in use to this day. It has been presented by the author at Altran Praxis in Bath, UK, and more recently in abbreviated form, with some additional material, at the Summer School on Engineering Trustworthy Software Systems (SETSS) held at Southwest University, Chongqing, China, in September 2014. The course is proprietary and copyright by Altran so cannot be published publicly in full. However extracts are including in Appendix B to give a flavour of the material. The course is normally presented intensively over a period of around four days, with lectures together with paper-and-pencil exercises intermingled.

An interesting feature is that the course is actually really two courses, one for “readers” of Z and one for “writers” of Z. In practice, many more engineers must learn to read Z on a particular project and far fewer are needed to write Z. This is because Z is typically used by both programmers, implementing the software product, and by software testers, who can use the Z specification to direct the tests that are needed in a very systematic way [23]. Neither implementers nor testers need to be able to write Z, but both must read and understand Z effectively in a project where the specification is written in Z. These tend to be major teams on a typical software project, the testing team often outnumbering even the implementation team. Most professional and experienced software engineers are able to assimilate the ability to read Z relatively easily, in a similar way to the fact that reading a book such as a novel is much easier than writing one. After a few day’s on a Z course, followed by a week or two of using Z documents, a good software engineer can read and understand Z effectively.

In contrast, writing a Z specification is a much more difficult skill to acquire. Thus the course by Altran has additional material on this aspect. Writing an effective Z specification that is amendable to both implementation and testing in a cost effective manner is something that only comes with experience, typically over months, arguably for greatest effectiveness over years. Fortunately the number of people needed to specify a software product on a large software project is much smaller the the numbers needed for implementation and testing, perhaps even by an order of magnitude. A wise decision is only to include the most experienced software engineers on the specification team, ideally with several years of at least reading Z.

2.1 Exercise

Since the Z course produced by Altran/Praxis cannot be reproduced in full here, we include an example exercise and solutions for part of a Z course that has been delivered as a component of the final year of an undergraduate degree programme in Computer Science at Birmingham City University.

We use, as an example, a simplified air traffic control system. The questions are informal in nature and the task is to write Z that formally specifies the informal description in the questions. This emulates the task of a software specifier on a real project, where some informal requirements written in a natural language such as English, perhaps augmented with some diagrams, need to be formalised in a more rigorous and mathematically-based notation such as Z.

One issue of learning a notation like Z is that there are often examples of a completed specification available, but there is very little indication of how to reach that specification [11]. An example has previously been given of a simple invoicing system specified using a number of different notations, including Z [12], where the questions that should be answered as the specification is developed are explicitly stated. Here we first present the questions and then example solutions with an indication of how these can be derived mentally.

2.2 Questions

The following are questions on a simple air traffic control system that need to be answered using Z notation. A comprehensive glossary of the Z notation is available in Appendix A for reference.

  • Question 1: An air traffic control system involves a number of airspace sectors and a number of planes. Define two given sets to model these.

  • Question 2: The airspace consists of a number of sectors. Each sector may have a number of adjacent sectors, which are then related to each other. Note that the adjacency relation is symmetric; i.e., if a sector is adjacent to another sector, then the reverse is also true. Sectors cannot be adjacent to themselves (i.e., sectors cannot map to themselves in the adjacency relation). In addition, all sectors in the airspace have adjacent sectors. Define a state schema that models sectors and a relation indicating which sectors are adjacent, with appropriate constraining predicates. Note that \(\mathop {\mathrm {id}}X\) in Z is a one-to-one function that maps all elements in X to themselves.

  • Question 3: Each sector may contain a number of planes at any given time. Extend the previous state schema with a function that models planes in sectors. Planes can only be in valid sectors within the airspace.

  • Question 4: In each sector, some of the planes may be queued to leave the sector, in a sequence of planes. Extend the state schema in Question 3 to include a function that models the queued planes in each sector. Such queues can only be in valid sectors in the airspace. In addition these queues can only include a subset of the planes that are in each sector.

  • Question 5: There is more than one sector in the airspace. Initially there are no planes in the airspace. Define an initialisation schema that ensures these conditions.

  • Question 6: Define operations for the following, assuming success in each case, but including preconditions as needed:

    1. 1.

      Have a new plane added to one of the sectors (both specified as inputs), but not in the queue for the sector (e.g., after taking off from an airport or arriving from another airspace).

    2. 2.

      Queue an existing plane (specified as an input) that is not yet in a queue. The plane should be added to the last position of the queue in its sector.

    3. 3.

      Remove the plane at the head of a queue in a specified sector from the airspace (e.g., land at an airport or be transferred to another airspace). Output the plane involved.

    4. 4.

      Have the plane at the head of a queue in a sector move to an adjacent sector. Both sectors should be specified as inputs and the plane should not be included in the queue of the new sector.

  • Question 7: (optional)

    1. 1.

      Extend your answers in Question 6 to handle errors and provide total operations, with appropriate error messages.

    2. 2.

      Informally describe and formally specify further operations (e.g., changing airspace sectors).

2.3 Answers

Here for each question in the previous subsection we present the thought processes that lead to a solution, together with an example model answer in Z.

  • Answer 1: In Z, “given sets” (or “basic types”) are potentially infinite sets with no implicit structure on which the specification is going to operate. Z is typed so these sets are non-overlapping and are not compatible with standard set operations (e.g., union \(\cup \) or intersection \(\cap \)). The question suggests two such sets, which we could name SECTOR to model all the possible airspace sectors in the system and PLANE for all the possible airplanes in the system. Obviously these are two different types of entity, so comparing them, subsets of them, or elements of them in any way (e.g., with equality \(=\)) is not correct and in Z would produce a type error if the specification is mechanically type-checked.

    In our simple example, we can define these two given sets in Z at the beginning of a specification as follows:

    figure n

    Note that a convention (but not a requirement) in Z is to use all upper case name for given sets. This is not required, but it does make identifying them easier in a specification and is widely used in practice.

  • Answer 2: Once we have some given sets in Z, we can start to use these to build up more complex structures. Typically we do this with “schema” boxes, that collect together mathematical objects such as sets, relations, functions, sequences, etc. A feature of Z is that all these are modelled as various types of set, so many Z operators can be reused on more specific structures. For example, standard set operators like union and intersection can be used on all these more refined set-based structures if desired. In addition, further more specific operators are available in Z that can be applied only to restricted forms of sets (e.g., relations). Schemas in Z are often used to specify abstract state structures on which operations can perform changes to those structures.

    In thisquestion, we require a number of sectors. We can do this by defining a set sectors (for example) to be drawn from a set of subsets of SECTOR (a “power set” \(\mathbb {P}\ SECTOR\)). In the declarations below, “:” is much like that used in many programming languages to declare variables. In Z, it can be considered as meaning “is a member of” a set (written as \(\in \) when used in predicates (in the lower half of a schema box) rather than the declaration part (the upper half of the schema box). So x : X can be thought of as \(x\in X\). Further, a declaration of the form \(x_1\in \mathbb {P}x_2\) can be considered as meaning \(x_1\subseteq x_2\) (i.e., \(x_1\) is a subset of \(x_2\)). So below, \(sectors\subseteq SECTOR\) holds. This is because we wish to model the airspace is a number of sectors, which are a subset of all the possible sectors (the set SECTOR).

    Another property of airspace is that some sectors are adjacent to each other. I.e., it is possible for airplanes to fly directly between them. We model this as pairs of sectors that are considered to be next to each other. Adjacent sectors have a number of properties that always hold for all configurations of sectors in the airspace. For example, if a sector is adjacent to another sector, then the second sector is also adjacent to the first sector (i.e., it is symmetric, \(adjacent^\sim = adjacent\)). Sectors cannot be adjacent to themselves, so the intersection of adjacent sectors and sectors mapped to themselves is empty (\(adjacent \cap \mathop {\mathrm {id}}sectors = \emptyset \)). All sectors in the airspace have at least one adjacent sector (i.e., the domain of the adjacent sectors is the same as the set of sectors in the airspace, \(sectors = \mathop {\mathrm {dom}}adjacent\)). This means that the range of the adjacency relation is also the same as all the sectors in the airspace (\(sectors = \mathop {\mathrm {ran}}adjacent\)) since this relation is symmetric. So in all, the following holds:

    figure o
  • Answer 3: All planes in the airspace are in one of the sectors. We can model this as a partial function from airplanes to sectors. (). The sector for each plane must be one of those that is in the airspace (\(\mathop {\mathrm {ran}}planes \subseteq sectors\)). We can augment the state space by adding this information to the existing airspace Airspace0 (an “included” schema with all the information in that schema too) as follows:

    figure p
  • Answer 4: Within each sector there is a queue of planes (possibly empty) waiting to leave the sector, again modelled as a partial function, this time from sectors to an injective sequence of airplanes (). Being injective meane that the planes in the sequence are all different. Queues of planes waiting to leave each sector. Each sector in the airspace has a (possibly empty) queue associated with it (\(\mathop {\mathrm {dom}}queues = sectors\)). What is more, the planes in the queues within each sector are a subset of the planes in that sector (\(\forall s:sectors \bullet \mathop {\mathrm {ran}}(queues~s) \subseteq planes^\sim \) ). Some planes in the sector may not (yet) be waiting in the queue for that sector. Again we can augment the state space to create our complete abstract state scheme Airspace:

    figure q
  • Answer 5: The airspace at initialisation has more than one sector in it (\(\#sectors' > 1\)) and no planes (\(planes' = \emptyset \)). Thus the state after initialisation, indicated with a postpended prime (\('\)) by convention in Z, is as follows:

    figure r

    Note that the prime appended with the Airspace schema means that all its components (in this case sectors, adjacent, planes, and queues) all have primes appended to them as well (i.e., \(sectors'\), \(planes'\), etc.). In formulating the state at initialisation, we should consider all the state components. However it is normal for there to be invariant predicates relating some of these components. It is often the case that specifying one state component to be empty implies that one or more other related state components are restricted in some appropriate way, typically to be empty too. For example in this case, because there are no planes in the airspace initially, the queues in each sector (modelled by the queues state component) are restricted by the universally quantified predicate in Airspace to be empty too since a subset of an empty set can only be the empty set too. Note that nothing specific has been said about the adjacent state component apart from the constraints that are already in the predicate part of the Airspace0 schema since there is no additional predicate involving \(adjacent'\).

  • Answer 6: Below are various operations on the airspace, specified as schemas with a “before state” (with “unprimed” state components) and a matching “after state” (with “primed” state components, postfixed with the prime symbol \('\)). \(\varDelta Airspace\) indicates both a before state Airspace and an after state \(Airspace'\) where the prime \('\) filters through to the names of all the components parts of the state in the schema too.

    1. 1.

      A plane entering the airspace can be specified as follows:

      figure s

      The \(\varXi Airspace0\) is similar to \(\varDelta Airspace0\) but with all the primed state components in \(Airspace0'\) constrained to be the same as the unprimed equivalents in Airspace0. In this case, the state components in Airspace0 are sectors and adjacent. Inputs to operation schemas (with before and after states) are appended with a question mark (?) by convention to differentiate them from state components. Here there are two inputs, p? for the plane that is entering the airspace and s? for the sector that it enters.

      Next the predicates for the schema need to be formulated. First consider the precondition for the operation to be valid, only dealing with the before (unprimed) state and inputs. The plane p? must not be one of the planes already in the airspace. It is worth considering especially if there are any limitations on inputs for the operation to be successful. This is very often the case and it is helpful to specify this explicitly even if it is implied indirectly by other predicates. The implementer will find it useful and it will help in testing the implementation later too if the specification is used to direct the tests.

      Now consider the postcondition for the operation. I.e., how are the after state and outputs related to the before state and inputs? The plane p? is added to the sector s? that it enters. It is not in the queue to leave the sector initially so the queues are unchanged. The rest of the airspace state is also unchanged. It is important to explicitly specify when the after state is the same as the before state in a specification of an operation if this is what is required. Otherwise the after state may take on any value. It is important to go through all the after-state components and outputs in an operation and ensure that they are specified in some way. It is unusual to allow an after state or output to take on any value. This is easy for the implementer, but normally not very useful or desirable for the customer. Similarly, it is normally for all the inputs to be used in some way in the predicate part of the schema and all the outputs to be set in some useful way,

      Here \(\varXi Airspace0\) ensures that the rest of the otherwise unmentioned state components remain the same after the operation. This is a technique often used in Z to “frame” operations on selected parts of the state of interest in a particular set of operations. It helps in structuring the specification when there are several similar operations where much of the state is unchanged but a particular part is changed in a different way for individual operations. In this case, \(\varXi Airspace0\) in the declaration part of the schema acts as a short form for the predicate \(sectors'=sectors \wedge adjacent'=adjacent\), which would become repetitive if needed in multiple operations and would also obscure the important predicates in the operations.

    2. 2.

      Queueing a plane to leave a sector can be specified as follows. The plane starts at the back of the queue.

      figure t

      In this case, \(\varXi Airspace1\) is used to specify the fact that all the state components sectors, adjacent, and planes, remain the same. It is only queues that changes, in fact only one queue in one particular sector. p? is the input plane that is to be queued.

      Again, for the predicate part, we consider the precondition first. The plane p? is in the airspace but it is not in any of the queues in all of the sectors in the airspace. In considering the postcondition, only one individual queue is changed. All of the rest of the state remains the same since the sector where the plane is located does not change. The plane p? is added to the end of the queue for the sector in which it is located. The overriding operator (\(\oplus \)) is one that is commonly used in Z when a small part of a relation, often a function, is to be change to have a different value in the range associated with a particular element in the domain.

      The use of \(\varXi Airspace1\) in the declaration part of the schema above ensures that other state components apart from queues remain the same, so only queues needs to be considered explicitly for the postcondition.

    3. 3.

      The plane at the head of the waiting queue in a given sector leaves the airspace (e.g., comes in for landing or passes to another airspace).

      figure u

      Here there is an input s? to specify the sector to which the operation applies and an output p! giving the plane at the head of the queue that is leaving the sector. An appended exclamation mark (!) is used to indicate an output by convention in Z.

      As a precondition, the queue for the sector s? must be non-empty. This is an important precondition since at least one plane is needed in the queue to allow one to be removed. The plane p! is the one at the head of the queue. It is removed from the overall airspace. It must also be removed from the queue for the specified sector s?.

    4. 4.

      The plane at the head of the waiting queue in a given sector moves from that sector to an adjacent sector.

      figure v

      Two sectors are declared as inputs, s1? for the sector where the plane at the head of the queue is to be moved and s2? for an adjacent sector where it is to be moved.

      Again, a precondition is that the queue for the sector s1? must be non-empty. Another precondition is that the sector s2? must be immediately adjacent to the sector s1?. A postcondition is that the plane is moved from sector s1? to sector s2?. It is also removed from the queue in sector s1?. Note that it is not added to the queue in sector s2?.

  • Answer 7: (optional) There are a variety of answers possible for this part. It is designed to be more open-ended for the better students to tackle. Only those aiming for top marks are likely to attempt this question.

2.4 Z Course

The Z course produced by Altran is a commercial course and as such the copyright is owned by the company. Thus some extracts are included as Appendix B of this chapter to give a sample of the style of the course. Full model answers are also available, but these are not reproduced here for obvious reasons.

The following is a timetable for a typical four-day Z Readers Course. There are normally four sessions each day, two in the morning and two in the afternoon, with breaks between the sessions. These sessions are typically of 90 min duration. Lectures are interspersed with exercises, normally at the end of sessions.

  • Day 1

    • Session 1: General Introduction

    • Session 2: Case Study Introduction

    • Session 3: Underlying Mathematics: Sets

    • Session 4: Case Study (continued) and Relations

  • Day 2

    • Session 1: Relations (continued)

    • Session 2: Functions

    • Session 3: Case Study (continued)

    • Session 4: Underlying Mathematics: Logic

  • Day 3

    • Session 1: Introduction to Schemas

    • Session 2: Case Study Operations

    • Session 3: Schema Calculus

    • Session 4: Analysing Specifications

  • Day 4

    • Session 1: Schemas as Types

    • Session 2: Alternative Case Study

    • Session 3: Syndicate Exercise

    • Session 4: Syndicate Exercise (continued)

The Z Writers Course is longer than the Z Readers Course. In particular, more time is allocated to actually writing a Z specification, e.g., as a mini-project in small groups.

3 Conclusion

This chapter has presented the formal specification language Z, including information on an industrial Z course and some example Z questions and answers, with commentary on how to approach developing a formal Z specification from an informal description. A glossary of Z is included in Appendix A and parts of an industrial Z course are included in Appendix B, with some commentary,

Z is now a mature formal specification language with an ISO standard. It is still lacking in good industrial-strength tools but despite this deficiency it has been used in significant industrial projects involving teams of more than a hundred engineers and associated personnel. Research in Z has now slowed but that is an indication of its maturity. It is likely to continue to play an important part of safety and security-related projects when high integrity is essential. It can play an important part in a safety case, especially with respect to its use in improving the efficacy of testing. To paraphrase a well-known quotation by Winston Churchill, reports of Z’s death are greatly exaggerated!