\documentstyle[11pt,titlepage]{article}
%\documentstyle[11pt,tla,titlepage]{article}

\makeatletter

%%% file tla.sty
%%  TLA DOCUMENT STYLE
%%  (c) 1994 by Leslie Lamport
%
%   Changes:
%     27 Dec 95 : Removed bug that caused error on blank line inside
%                 \assume or \prove argument.
%      1 Mar 95 : Made \V work with negative argument.
%     14 Oct 94 : Made equation and eqnarray environments use TLA mode
%                 Also redefined \label and \ref so they work with
%                 arbitrary labels inside TLA mode.
%
%
%   This style calls the pf style, and the abbrev style.  These other 
%   styles should not be loaded separately.
%
%   This style puts LaTeX in TLA mode.  This mode causes the following 
%   changes to LaTeX's normal math mode:
%   
%  Characters are in the normal italic font, rather than math italic.
%  Thus $Off$ will produce something that looks like {\it Off} rather
%  than the usual formula that's supposed to equal $Of^{2}$.
%  
%  The following sequences produce the following commands when LaTeX is
%  `inside math mode', where being inside math mode means being in math
%  mode or in the argument of a command or in an environment (such as
%  \mbox or a minipage or tabular environment) that appears inside a math
%  formula.  (See below for how to customize the abbreviations.)
%  
%    ==   :  equals by definition (\deq)
%    =>   : \Rightarrow
%    :\:  : \backslash
%    []   : \Box 
%    <>   : \Diamond
%    ~>   : \leadsto
%    ~    : \lnot
%    -+-> : the TLA "while-plus" operator: an arrow with a "+" over it.
%    <--  : \longleftarrow
%    <-   : \leftarrow
%    <<   : \langle
%    >>   : \rangle
%    -->  : \longrightarrow
%    ->   : \rightarrow
%    |-   : \vdash
%    |=   : \models
%    |->  : \mapsto
%    #    : \neq
%    \/   : \lor
%    /\   : \land   (This command must be followed by a space, and must
%                   not come at the end of a line, unless the line is
%                   ended by a % )
%    "text"  :  {\rm ``{\sf text}''}  (a TLA+ string constant)
%    _.      :  \, 
%    __      :  Produces a `unit' space
%    ___     :  Produces two `unit' spaces
%    __..._  :  Produces n `unit' spaces
%           The default value of a unit space is 1em.  You can reset its 
%           value to .75em by \indentspace{.75em}.
%  
%  The style issues a \coloncommands declaration.  This declaration
%  causes LaTeX to enter colon-command mode.  In colon-command mode,
%  whenever LaTeX is inside math-mode, the string :xxx: is interpreted as
%  \xxx, for any `xxx'.  When LaTeX is inside math mode, a regular colon
%  must be followed by a space.  The declaration \nocoloncommands causes
%  LaTeX to leave colon-command mode.
%  
%  You can leave TLA mode with the \notla declaration, and re-enter it
%  with the \tla declaration.  
%  
%  In TLA mode, the following characters are active while inside math
%  mode:  
%  
%     : [ = < > " _ | / ! - #
%  
%  This means that these characters cannot be used for many purposes--
%  for example:
%  
%     You can't use [ to begin an optional argument.
%     You can't use the following with \left or \right: < > / |
%     You can't use - as a minus sign in something like \hspace{-3pt}.
%  
%  (Since \\ is often used with an optional argument for adding
%  space, the command \V is proved, where \V{.7} means \\[.7em])
%  You can make these characters inactive by a \notlachars command,
%  and reactivate them with \tlachars--for example, so you can write
%  
%       {\notlachars \sqrt[n]{2}}
%  
%  in TLA mode--so long as this doesn't appear in the argument of any
%  command.  The command \xtla{...} is equivalent to
%  
%       {\notlachars ... }
%  
%  WARNING: In tla mode, $ is fragile, so it must be \protect'ed if
%  it appears in a moving argument.
%  
%  The style also defines the following math commands (some particular
%  useful in colon-command mode):
%  
%    \A  :  \forall
%    \E  :  \exists
%    \EE :  bold \exists (TLA's temporal existential quantification)
%    \AA :  bold \forall (TLA's temporal universal quantification)
%    \X  :  \times
%  
%  The following commands, defined here (or in the pf style) are useful
%  in formatting math formulas:
%  
%    For conjunction and disjunction lists, use the conj and disj environments;
%    use noj for a nonbulleted list.
%   
%       \begin{conj}                   /\ x = 7
%          x = 7 \\                    /\ \/ x > z                       
%          \begin{disj}                   \/ (y < foo)  =>
%             x > z \\                         x = 7
%             \begin{noj}
%               (y < foo) => \\ 
%               __x = 7
%             \end{noj}
%           \end{disj}              
%       \end{conj}
%   
%    The environments noj2, noj3, and noj4 make 2-, 3-, and 4-column
%    arrays, with columns separated by &, as usual.
%    These are array environments.
%   
%    if/then/else's are made as follows:
%      \IF{x > 0}    \\                              IF x > 0
%           \THEN    foo                    \\         THEN foo
%           \ELSE    \IF{y > 3} \THEN y + 6 \\         ELSE IF y > 3 THEN y + 6
%                               \ELSE y + 7 \FI \\                   ELSE y + 7
%                    + 3  \FI \\                            + 3
%
%    Let's are made as follows:
%       \LET x == ... \\
%            y == ... 
%       \IN  ...  \NI
%
%    CASE's are made with the \CASE command, which just makes the
%    "CASE"--e.g.,
%
%      \CASE \begin{noj3}
%              p & -> & xy + 7 \\
%              q & -> & xx + 33
%            \end{noj3}
%  The commands \comment{text} and \tlacomment{text} produce
%  multiline comments (lines separated by \\) that take up no
%  vertical space.  Text is "normal" in \comment, and in TLA mode
%  in \tlacomment.
%
%  The style provides the following environments for TLA+ specs:
%     The module, decls, and submodule environments work as 
%     indicated below:
%                           
%       \begin{module}{name}                __________| name |___________
%                                          |          |      |           |
%    
%         \begin{decls}{parameters}          PARAMETERS
%            xyz    : \VARIABLE \\            xyz : VARIABLE
%            foobar : \CONSTANT               foobar : CONSTANT
%         \end{decls}
%    
%       \midbar                            |-----------------------------|
%    
%          \begin{decls}{actions}            ACTIONS
%              ...                            ...
%          \end{decls}
%   
%          \begin{submodule}{submod}          _________| submod |________
%                                            |         |        |        |
%                ...                              ...   
%    
%          \end{submodule}                   |___________________________|
%    
%       \end{module}                       |_____________________________|
%   
%   
%    The decls environment is a tabbing environment, so lines are ended with 
%    \\, and \= , \>, \\, etc. work as usual.  However, its entries are set 
%    in math mode (so TLA-mode commands work).  Inside a module or submodule
%    environment but outside a decls environment, LaTeX is in paragraph
%    mode, with \it in effect.
%
%    The nodecls environment is like the decls environment, except it 
%    has no title (and no argument) and does not indent and does
%
%    For splitting a module across figures, there is the nomodule
%    environment, which is like the module environment but does
%    not produce the top and bottom module lines.  These lines are 
%    produced by the commands \topbar{MODULE-NAME} and \bottombar.
%
%    The following commands produce the obvious keywords:
%
%       \IMPORT       \VARIABLE      \UNCHANGED      \UNION  
%       \EXPORT       \CONSTANT      \EXCEPT         \SUBSET  
%       \INCLUDE      \BOOLEAN       \ENABLED        \TRUE      
%       \AS           \ACTION        \CHOOSE         \FALSE  
%                     \STATEFCN      \DOMAIN         
%       
%    These are written as in
%
%       \INCLUDE Foo \AS Bar
%
%    not as "\INCLUDE\ Foo".
%
%    The following commands are used to introduce space:
%        \s{1.2}     A 1.2em horizontal space
%        \vs{1.2}    A 1.2em vertical space, made either with a vertical strut 
%                    extending 1.2em below the line, or a \vspace{1.2em}, 
%                    depending on whether used in outer par mode or not.
%        \V{1.2}     Equivalent to \\[1.2em] (which can't be used in math
%                    mode in TLA mode).
%
%
% CUSTOMIZING THE ABBREVIATIONS
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%  You can create a new set of abbreviations.  However, it is advisable
%  to keep the current ones and just add to them.  You do this with
%  a tlabbrev environment, which is just like an abbreviate environment
%  except without the first argument.  (See abbrev.sty for documentation
%  on the abbreviate environment.)  The following tlabbrev environment
%  creates the standard abbreviations.  Modify it to add your own
%  abbreviations.
%
% \begin{tlabbrev}{:[=<-/|#"_!>}{:[=<-/|#"_!\:>}
%   \x ==   {\ensuremath{\;\;\deq\;\;}}
%   \x =>   {\ensuremath{\Rightarrow}}
%   \x =    {=}
%   \x :\:  {\ensuremath{\,\backslash}}
%   \x ::   {::}
%   \x :    {\tlacolon}
%   \x []   {\ensuremath{\Box}}
%   \x [    {[}
%   \x <>   {\ensuremath{\Diamond}}
%   \x <--  {\ensuremath{\longleftarrow}}
%   \x <-   {\ensuremath{\leftarrow}}
%   \x <<   {\ensuremath{\langle\tlathin}}
%   \x <    {\ensuremath{<}}
%   \x >>   {\ensuremath{\tlathin\rangle}}
%   \x >    {\ensuremath{>}}
%   \x -->  {\ensuremath{\longrightarrow}}
%   \x --   {--}
%   \x -+-> {\ensuremath{\tlawhilep}}
%   \x -+-  {-+-}
%   \x -+   {-+}
%   \x ->   {\ensuremath{\rightarrow}}
%   \x -    {\ensuremath{-}}
%   \x |->  {\ensuremath{\mapsto}}
%   \x |-   {\ensuremath{\vdash}}
%   \x |=   {\ensuremath{\models}}
%   \x |    {\ensuremath{|}}
%   \x #    {\ensuremath{\neq}}
%   \x ~>   {\ensuremath{\leadsto}}
%   \x ~    {\ensuremath{\lnot}}
%   \x /    {\tlaslash}
%   \x "    {\ensuremath{\tlaquote}}
%   \x _.   {\,}
%   \x __   {\tlaunder}
%   \x _    {\tlasubscript}
%   \x !    {\ensuremath{\tlathin!\tlathin}}
% \end{tlabbrev}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%\input{abbrev.sty}
%%% file abbrev.sty
%% File abbrev.sty

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      DOCUMENTATION                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file defines the abbreviate environment, which allows you to do
% things like typing $=>$ instead of $\Rightarrow$.  It also defines
% a few useful commands, including one to make math-mode use ordinary
% italic characters.
%
%
% THE abbreviate ENVIRONMENT
% ~~~~~~~~~~~~~~~~~~~~~~~~~~
% This environment is explained in terms of the following example:
% 
%    \begin{abbreviate}{FOO}{=#(}{=#(}
%      \x ==>  {\Longrightarrow}
%      \x ==   {==}
%      \x =>  {\Rightarrow}
%      \x =   {=}
%      \x #   {\neq}
%      \x (+) {\oplus}
%      \x (+  {(+}
%      \x (   {(}
%    \end{abbreviate}
% 
% This defines the declaration \FOO that does the following:
%   * Makes the three characters  
%           =  #  ( 
%     active--so they are commands like the character ~ (tilde).
% 
%   * Defines these characters in such a way that 
%       ==> is an abbreviation for  \Logrightarrow, 
%       ==  does what it normally does 
%       =   does what it normally does
%       #   is an abbreviation for \neq
%       etc.
% 
% It also defines the declaration \noFOO to undo the effects of the
% declaration \FOO.  Here are the rules
% 
%    * The following characters can appear as the first character
%      of an abbreviation:
% 
%         ! @ # $ % ^ & * ( ) _ - + = ~ ` | [ ] : ; " ' < > , . ? /
% 
%    * The other characters in an abbreviation can be anything except
%      the three characters  \  {  } .  They can contain % only if
%      %  appears in the last two arguments of the abbreviate environment.
%
%    * The second and third arguments of the abbreviate environment consist 
%      of the first characters that appear in abbreviations.  However,
%      ~ (tilde) does not appear in these arguments, even if it's
%      used as the first character of an abbreviation. [As a NOTE below
%      explains, the second and third arguments need not always have
%      the same characters.]
% 
%    * An abbreviation definition consists of \x followed by
%      the abbreviation, followed by one or more spaces, followed
%      by its definition, enclosed in braces.
%
%    * The sequence of abbreviations being defined must obey the following 
%      rules:
%
%         - The first abbreviation is arbitrary.
%
%         - Every subsequent abbreviation must be obtained by deleting
%           the last character from the previous abbreviation and adding
%           any (possibly empty) string of characters.
%
%         - The last abbreviation defined must be a single character.
%
%      It is a consequence of these rules that, to define an abbreviation,
%      It is necessary to define every prefix of that abbreviation.
%
%
%   NOTE: You can have multiple abbreviate environments to define
%   different sets of abbreviations.  
%
%   WARNING: When a character is active, it doesn't behave like it normally
%   does.  In particular, if  [  or  ]  is active, then [ ] cannot be
%   used to enclose optional arguments.   Use something like
%
%           \noFOO \command[arg] \FOO   or  {\noFOO \command[arg]}
%
%   if you need a command with optional arguments.
%
%   NOTE: In the example above, the command \FOO both activates the
%   characters  = # ( and defines their active versions appropriately.
%   The abbreviate environment also defines the command \FOOact, 
%   which just activates the characters.  Since the definitions 
%   aren't changed by \noFOO, the sequence of commands
%
%      \FOO \noFOO \FOOact 
%
%   is equivalent to \FOO.  If you're writing macros that do a lot
%   of messing around, you may want to take advantage of this.
%
%   NOTE: You can use commands of the form \<single-letter>, such
%   as \: in an abbreviation, as long as it's not the first letter.
%   If you use such a command, it must go in the third argument (but
%   NOT the second) of the abbreviate environment.
%
%
%   USEFUL COMMANDS
%   ~~~~~~~~~~~~~~~
%
% \ensuremath{FORMULA}
%    Typesets FORMULA in math mode, regardless of current mode.
%    (This is a standard LaTeX-2e command.)
%
% \noTeXmath
% \TeXmath   
%    In math mode, TeX normally typesets characters in math italic,
%    which makes $different$ look like $d$ time $i$ times $f$ times ...
%    and not like {\it different}.  The \noTeXmath causes TeX to use
%    ordinary italic, so $different$ is the same as {\it different}.
%    This makes it easier to use multi-letter identifiers in formulas.
%    The \TeXmath command reverts to TeX's normal behavior
%
% \makeactive{CHARS} : 
%    CHARS should be a string of characters, not containing any of the
%    three characters "\", "{", or "}".  This activates all the characters
%    (sets their catcode to active [catcode = 13]).
%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                THE abbreviate ENVIRONMENT                      %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DEFINE COUNTERS
%
\newcounter{abr@ctr}
\newcounter{abr@level} \setcounter{abr@level}{0}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% THE abbreviate ENVIRONMENT
%
% \abbreviate{PREFIX}{ACTIVECHARS}{ACTIVECHARS}
%
\def\abbreviate#1{%
  \def\abr@prefix{#1}%      \abr@prefix := PREFIX
  \global\let\abr@tilde~%   \abr@tilde  := real tilde
  \gdef\abr@activechars{}%
  \let~\relax
  \abr@sanitize
  \abr@abbreva}

\def\abr@abbreva#1{%          %% \abr@activate  := catcode characters to active
  \gdef\abr@activate{}%       %% \abr@deactivate := make everything normal
  \gdef\abr@deactivate{}%
  \@tfor\i:=#1\do{%
    %%\typeout{Loop: i = \i}
    \xdef\abr@activate{\abr@activate\catcode`\i\active}%
    \xdef\abr@deactivate{\abr@deactivate\catcode`\i12\relax}}%
    \xdef\abr@deactivate{\abr@deactivate\noexpand\abr@unsanitize
                         \noexpand\let\noexpand~\noexpand\abr@tilde}%
   \abr@activate
   \abr@abbrevb}

\def\abr@abbrevb#1{%   % Let all active characters to \relax and 
   \@tfor\i:=#1\do{%   % let \x to \abr@getsub
     \expandafter\let\i\relax}%
   \let\x\abr@getsub}

\def\endabbreviate{%
  \expandafter\abr@defineactives\abr@activechars\do\abr@tempx
  \expandafter\global\expandafter\let\csname\abr@prefix\endcsname\abr@tempx
  \expandafter\global\expandafter\let
         \csname\abr@prefix act\endcsname\abr@activate
  \expandafter\global\expandafter\let
      \csname no\abr@prefix\endcsname\abr@deactivate}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% THE INVARIANT
%
% The following invariant is maintained in the body of the abbreviate
% environment, where def_i[foo] is the definition of (the macro
% expansion of) foo at \begingroup nesting level i.  (Nesting level 0 is
% the top.)
% 
% IF the last command processed was
%     c_0 ... c_n {val} 
% THEN Exists \cmd_1 ... \cmd_n :
%   LET X(i) == \abr@ifnextchar c_i{\cmd_i}{\csname def_i[abr@else]\endcsname}
%   IN  * \value{abr@level} = n
%       * current \begingroup nesting level = n
%       *   \csname \abr@prefix\string c_0] \endcsname  =g  IF n = 0 THEN val
%                                                                    ELSE X(1)
%       * For all i in {1, ... ,n-1} : 
%          \cmd_i =g c_i -> X(i+1)
%       * For all i in {1, ... , n} :
%          \csname def_i[abr@else]\endcsname is undefined at level 0.
% 
%       * \cmd_n =g c_n -> the right sequence to process c_0...c_n
%       * \prefix@activechars = ... c_0
% 

% \abr@addcmd{STRING}{VAL} 
%    The guts of the abbreviate environment. \x STRING {VAL} expands
%    to \abr@addcmd{STRING}{VAL}.  
%
%  BEGIN
%    abr@ctr := 0
%    Remaining := STRING
%    WHILE Remaining # empty
%    DO  \char     := Head(Remaining)
%        Remaining := Tail(Remaining)
%        IF abr@ctr < abr@level
%          THEN %%%  Do nothing
%          ELSE %%% Current string length >= previous one
%               IF abr@ctr = abr@level 
%                 THEN %% this is beginning of new string suffix
%                      IF abr@level = 0
%                        THEN %% new beginning char
%                              \abr@then :=g \abr@prefix \string\char
%                              \abr@activechars := 
%                                 \abr@activechars :o: \char
%                        ELSE %% have to clean up preceding char
%                             \abr@temp :=g \abr@else
%                             \abr@then :=g new_cs
%                             \abr@else := new_cs
%                             \gdef \csname \abr@temp\endcsname 
%                                  {\abr@ifnextch {\char}%
%                                       {\csname\abr@then\endcsname}%
%                                       {\csname\abr@else\endcsname}}
%                      FI
%                 ELSE %% We've gotten started on new suffix
%                      \abr@temp :=g \abr@then
%                      \abr@then :=g new_cs
%                      \begingroup
%                      \abr@else := new_cs
%                      IF abr@ctr = 1
%                        THEN %% previous char was first one
%                             \gdef \csname \abr@temp\endcsname
%                               {\abr@ifnextch {\char}%
%                                       {\csname\abr@then\endcsname}%
%                                       {\csname\abr@else\endcsname}}
%                        ELSE \gdef \csname \abr@temp\endcsname \lastchar
%                               {\abr@ifnextch {\char}%
%                                       {\csname\abr@then\endcsname}%
%                                       {\csname\abr@else\endcsname}}
%                      FI
%               FI
%               \prevchar := \char
%        FI
%        abr@ctr := abr@ctr + 1
%    OD
%    %% 
%    IF abr@ctr = abr@level
%      THEN %% Current string one char shorter than previous one.
%           \gdef \csname \abr@else \endcsname {VAL}
%           \endgroup
%      ELSE %% Current string of length >= previous one.
%           IF abr@ctr = 1
%             THEN %% just a one-char string
%                  \gdef\csname \abr@then \endcsname{VAL}
%             ELSE %% multi-char string
%                  \gdef\csname \abr@then \endcsname \prevchar{VAL}
%           FI
%    FI
%    abr@level = abr@ctr - 1
% END definition of \abr@addcmd

\def\abr@addcmd#1#2{%
\setcounter{abr@ctr}{0}%
\@tfor\char:=#1\do{%
  \ifnum \value{abr@ctr} < \value{abr@level}%
    \else \ifnum \value{abr@ctr} = \value{abr@level}%
              \ifnum \value{abr@level} = \z@
                 \xdef\abr@then{\abr@prefix \expandafter\string\char}
                  \xdef\abr@activechars{\abr@activechars\char}
                 %\typeout{ELSE THEN THEN, abr@then := \abr@then}
                \else  \xdef\abr@temp{\abr@else}%
                       \abr@gnewcs\abr@then
                       \abr@newcs\abr@else
                        %\typeout{ELSE THEN ELSE, abr@temp = \abr@temp}
                       \expandafter\xdef\csname\abr@temp\endcsname{%
                           \noexpand\abr@ifnextch\char%
                           {\expandafter\noexpand\csname\abr@then\endcsname}%
                           {\expandafter\noexpand\csname\abr@else\endcsname}}
              \fi
            \else  \xdef\abr@temp{\abr@then}
                   \abr@gnewcs\abr@then
                   \begingroup
                   \abr@newcs\abr@else
                   \ifnum \value{abr@ctr}=\@ne
                       %\typeout{ELSE ELSE THEN, abr@temp = \abr@temp}
                      \expandafter\xdef\csname\abr@temp\endcsname{%
                           \noexpand\abr@ifnextch\char%
                           {\expandafter\noexpand\csname\abr@then\endcsname}%
                           {\expandafter\noexpand\csname\abr@else\endcsname}}
                     \else                    
                       %\typeout{ELSE ELSE ELSE, abr@temp = \abr@temp}
                        \expandafter\expandafter\expandafter\xdef
                           \expandafter\csname\expandafter\abr@temp
                           \expandafter\endcsname\prevchar{%
                           \noexpand\abr@ifnextch\char%
                           {\expandafter\noexpand\csname\abr@then\endcsname}%
                           {\expandafter\noexpand\csname\abr@else\endcsname}}
                   \fi
          \fi
          \let\prevchar\char
  \fi
  \addtocounter{abr@ctr}{1}%
 }%
  \ifnum \value{abr@ctr} = \value{abr@level}%
    %\typeout{DONE THEN abr@else = \abr@else}
    \expandafter\gdef\csname \abr@else \endcsname{#2}%
     \endgroup
   \else \ifnum \value{abr@ctr}=\@ne
           %\typeout{DONE ELSE THEN abr@then = \abr@then}
            \expandafter\gdef\csname\abr@then\endcsname{#2}
          \else 
            %\typeout{DONE ELSE ELSE abr@then = \abr@then}
            \expandafter\abr@gdef\prevchar{\abr@then}{#2}%
          \fi
  \fi
  \setcounter{abr@level}{\value{abr@ctr}}
  \addtocounter{abr@level}{-1}} %% END definition of \abr@addcmd

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      USEFUL COMMANDS                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% 
% \makeactive{CHARS} : 
%    CHARS should be a string of characters, not containing any of the
%    three characters "\", "{", or "}".  This \catcodes all the characters
%    to active (catcode 13).
%
\def\abr@makeactive#1{\catcode`#1\active}
\def\makeactive#1{\@tfor\i:=#1\do{\expandafter\abr@makeactive\i}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \ensuremath{FORMULA}
%    Typesets FORMULA in math mode, regardless of current mode.
%
\def\ensuremath#1{\relax\ifmmode #1\else $#1$\fi}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \noTeXmath
% \TeXmath   
%    The \noTeXmath causes TeX to use ordinary italic instead of math
%    italic in math mode.  The \TeXmath command reverts to TeX's normal
%    behavior.  (Modified 10 Aug to work with arbitrary \itfam.)
%    

\newcommand{\abr@c}{\c@abr@ctr\advance\c@abr@ctr\@ne}

% Let it work with LaTeX2e's native mode:
% D. Roegel, 29/8/1994
\ifx\documentclass\undefined
\else
  \DeclareSymbolFont{tlaitalics}{\encodingdefault}{cmr}{m}{it}
  \let\itfam\symtlaitalics
\fi

\newcommand{\noTeXmath}{%
\c@abr@ctr=\itfam
\multiply\c@abr@ctr"100\relax
\advance\c@abr@ctr "7061\relax
\mathcode`a=\abr@c
\mathcode`b=\abr@c
\mathcode`c=\abr@c
\mathcode`d=\abr@c
\mathcode`e=\abr@c
\mathcode`f=\abr@c
\mathcode`g=\abr@c
\mathcode`h=\abr@c
\mathcode`i=\abr@c
\mathcode`j=\abr@c
\mathcode`k=\abr@c
\mathcode`l=\abr@c
\mathcode`m=\abr@c
\mathcode`n=\abr@c
\mathcode`o=\abr@c
\mathcode`p=\abr@c
\mathcode`q=\abr@c
\mathcode`r=\abr@c
\mathcode`s=\abr@c
\mathcode`t=\abr@c
\mathcode`u=\abr@c
\mathcode`v=\abr@c
\mathcode`w=\abr@c
\mathcode`x=\abr@c
\mathcode`y=\abr@c
\mathcode`z=\abr@c
\c@abr@ctr=\itfam
\multiply\c@abr@ctr"100\relax
\advance\c@abr@ctr "7041\relax
\mathcode`A=\abr@c
\mathcode`B=\abr@c
\mathcode`C=\abr@c
\mathcode`D=\abr@c
\mathcode`E=\abr@c
\mathcode`F=\abr@c
\mathcode`G=\abr@c
\mathcode`H=\abr@c
\mathcode`I=\abr@c
\mathcode`J=\abr@c
\mathcode`K=\abr@c
\mathcode`L=\abr@c
\mathcode`M=\abr@c
\mathcode`N=\abr@c
\mathcode`O=\abr@c
\mathcode`P=\abr@c
\mathcode`Q=\abr@c
\mathcode`R=\abr@c
\mathcode`S=\abr@c
\mathcode`T=\abr@c
\mathcode`U=\abr@c
\mathcode`V=\abr@c
\mathcode`W=\abr@c
\mathcode`X=\abr@c
\mathcode`Y=\abr@c
\mathcode`Z=\abr@c}

\newcommand{\TeXmath}{%
\mathcode`a="7161%
\mathcode`b="7162%
\mathcode`c="7163%
\mathcode`d="7164%
\mathcode`e="7165%
\mathcode`f="7166%
\mathcode`g="7167%
\mathcode`h="7168%
\mathcode`i="7169%
\mathcode`j="716A%
\mathcode`k="716B%
\mathcode`l="716C%
\mathcode`m="716D%
\mathcode`n="716E%
\mathcode`o="716F%
\mathcode`p="7170%
\mathcode`q="7171%
\mathcode`r="7172%
\mathcode`s="7173%
\mathcode`t="7174%
\mathcode`u="7175%
\mathcode`v="7176%
\mathcode`w="7177%
\mathcode`x="7178%
\mathcode`y="7179%
\mathcode`z="717A%
\mathcode`A="7141%
\mathcode`B="7142%
\mathcode`C="7143%
\mathcode`D="7144%
\mathcode`E="7145%
\mathcode`F="7146%
\mathcode`G="7147%
\mathcode`H="7148%
\mathcode`I="7149%
\mathcode`J="714A%
\mathcode`K="714B%
\mathcode`L="714C%
\mathcode`M="714D%
\mathcode`N="714E%
\mathcode`O="714F%
\mathcode`P="7150%
\mathcode`Q="7151%
\mathcode`R="7152%
\mathcode`S="7153%
\mathcode`T="7154%
\mathcode`U="7155%
\mathcode`V="7156%
\mathcode`W="7157%
\mathcode`X="7158%
\mathcode`Y="7159%
\mathcode`Z="715A}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      AUXILIARY COMMANDS                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \abr@newcs\CMD   
% \abr@gnewcs\CMD :
%    Defines \CMD to be a new string prefixed with \abr@prefix.  
%    The definition is local with \abr@newcs, and global with
%    \abr@gnewcs
%
\newcount\abr@csctr
\def\abr@newcs#1{\global\advance\abr@csctr\@ne
                 \edef#1{\abr@prefix\the\abr@csctr}}
\def\abr@gnewcs#1{\global\advance\abr@csctr\@ne
                 \xdef#1{\abr@prefix\the\abr@csctr}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \abr@sanitize   
% \abr@unsanitize 
%    "sanitizing" catcodes $ & # ^ _ %  to "other".
%    "unsanitizing" catcodes these characters back to normal.
%
\def\abr@mkother#1{\catcode`#112\relax}
\begingroup
\abr@mkother$\abr@mkother&\abr@mkother#\abr@mkother^\abr@mkother_
\catcode`\%12\relax
\gdef\abr@sanitize{\abr@mkother$\abr@mkother&\abr@mkother#\abr@mkother
                 ^\abr@mkother_\abr@mkother%}
\gdef\abr@unsanitize{\catcode`$3\catcode`&4\catcode`#6\catcode`^7\catcode
                     `_8\catcode`%14\relax}
\endgroup

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \abr@gdef CHAR{STRING}{DEF} 
%    CHAR must be a character.  
%    This command does \gdef\STRING CHAR{DEF}
%
\def\abr@gdef#1#2#3{\expandafter\gdef\csname#2\endcsname#1{#3}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \abr@defineactive{CHARS}\CS
%    CHARS must be a string of active characters.
%    Defines \CS to do a \let c=\csname \abr@prefix\string c,
%    For all characters c in the string CHARS.

\def\abr@defineactive#1#2{\gdef#2{}%
  \let\abr@temp\relax
  \@tfor\char:=#1\do{%
    \xdef#2{#2\expandafter\abr@temp\char}}%
    \def\abr@temp##1{%
        \noexpand\let\noexpand##1\expandafter\noexpand
        \csname\abr@prefix\string##1\endcsname}%
  %\show#2
   \xdef#2{#2}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \abr@getsub STRING \do {VAL}
%   Expands to \abr@addcmd{STRING}{VAL}, where
%   STRING is evaluated with the special characters activated,
%   and VAL is evalued with them deactivated.  
%   It assumes that the characters are activated, and it
%   leaves them activated.
%
\def\abr@getsub#1 {\def\abr@temp{#1}\abr@deactivate\abr@getsuba}
\def\abr@getsuba#1{%
  \abr@activate 
  \let~\relax
  \expandafter\abr@addcmdx\abr@temp\do{#1}}
%\def\abr@addcmdx#1\do#2{\abr@addcmd{#1}{#2\relax}}  
\def\abr@addcmdx#1\do#2{\abr@addcmd{#1}{#2}}  

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \abr@ifnextch{c}{TRUE}{FALSE}
%   If the immediately following character is c, then TRUE, else FALSE.
%   This should be at the end of whatever macro is looking ahead.

\def\abr@ifnextch#1#2#3{\let\@tempe =#1\def\@tempa{#2}\def\@tempb{#3}\futurelet
    \@tempc\abr@ifnsnch}
\def\abr@ifnsnch{\ifx 
   \@tempc \@tempe\let\@tempd\@tempa\else\let\@tempd\@tempb\fi \@tempd}

% \abr@defineactives\do\CS
%    CHARS must be a string of active characters.
%    Defines \CS to do \abr@activate followed by a 
%       \let c=\csname \abr@prefix\string c, 
%    for all characters c in the string.
%
\def\abr@defineactives#1\do#2{\gdef#2{}%
  \let\abr@temp\relax
  \@tfor\char:=#1\do{%
    \xdef#2{#2\expandafter\abr@temp\char}}%
    \def\abr@temp##1{%
        \noexpand\let\noexpand##1\expandafter\noexpand
        \csname\abr@prefix\string##1\endcsname}%
   \xdef#2{\abr@activate#2}}

%%%%%%%%%%%%%%%%%%%%%%%
%  DEBUGGING
%
%  \@show{FOO} : \show\FOO
\newcommand{\@show}[1]{\expandafter\show\csname#1\endcsname}

%%% end file abbrev.sty

%% Have to redefine \abr@sanitize  and \abr@unsanitize so they
%% don't muck with $.  For efficiency, remove the mucking about
%% with  &  and %  as well
\gdef\abr@sanitize{\abr@mkother##\abr@mkother^\abr@mkother_}
\gdef\abr@unsanitize{\catcode`##6\catcode`^7\catcode`_8\relax}

%% \noTeXmath
%% \TeXmath
%%   The \noTeXmath command makes all letters in math mode come
%%   from the text italic font (family 4) rather than the usual math
%%   italic family.  Thus $Word$ is just an italic word, not a
%%   weird math formula.  Useful when math symbols are mostly
%%   multiletter. \TeXmath resets to normal.

% 
%%
%% Redefine Math Mode commands to use \tla@everymath
%%  Changed 14 Oct 94 to redefine \equation and \eqnarray as well.
%%
%%  (Can't use \everymath because $ apparently gives next character its 
%%  catcode before executing \everymath)

\def\tla@math{\relax\ifmmode $\else $\tla@everymath\fi}
\let\@begmath\(
\let\@begdispmath\[
\let\@begeqn\equation
\let\@begeqnarray\eqnarray
\def\tla@everymath{}  %% initialization

\catcode`$\active
\let$\tla@math
\def\({\@begmath\tla@everymath}
\def\[{\@begdispmath\tla@everymath}
\def\equation{\@begeqn\tla@everymath}
\def\eqnarray{\tla@everymath\@begeqnarray}

%% Redefine \label and \ref

\let\@oldlabel\label
\def\label{\begingroup\notla\@xlabel}
\def\@xlabel#1{\@oldlabel{#1}\endgroup}

\let\@oldref\ref
\def\ref{\begingroup\notla\@xref}
\def\@xref#1{\@oldref{#1}\endgroup}

\newenvironment{tlabbrev}{\begin{abbreviate}{tla@abbrev}}{\end{abbreviate}}


\begin{tlabbrev}{:[=<-/|#"_!>}{:[=<-/|#"_!\:>}
  \x ==   {\ensuremath{\;\;\deq\;\;}}
  \x =>   {\ensuremath{\Rightarrow}}
  \x =    {=}
  \x :\:  {\ensuremath{\,\backslash}}
  \x ::   {::}
  \x :    {\tlacolon}
  \x []   {\ensuremath{\Box}}
  \x [    {[}
  \x <>   {\ensuremath{\Diamond}}
  \x <--  {\ensuremath{\longleftarrow}}
  \x <-   {\ensuremath{\leftarrow}}
  \x <<   {\ensuremath{\langle\tlathin}}
  \x <    {\ensuremath{<}}
  \x >>   {\ensuremath{\tlathin\rangle}}
  \x >    {\ensuremath{>}}
  \x -->  {\ensuremath{\longrightarrow}}
  \x --   {--}
  \x -+-> {\ensuremath{\tlawhilep}}
  \x -+-  {-+-}
  \x -+   {-+}
  \x ->   {\ensuremath{\rightarrow}}
  \x -    {\ensuremath{-}}
  \x |->  {\ensuremath{\mapsto}}
  \x |-   {\ensuremath{\vdash}}
  \x |=   {\ensuremath{\models}}
  \x |    {\ensuremath{|}}
  \x #    {\ensuremath{\neq}}
  \x ~>   {\ensuremath{\leadsto}}
  \x ~    {\ensuremath{\lnot}}
  \x /    {\tlaslash}
  \x "    {\ensuremath{\tlaquote}}
  \x _.   {\,}
  \x __   {\tlaunder}
  \x _    {\tlasubscript}
  \x !    {\ensuremath{\tlathin!\tlathin}}
\end{tlabbrev}

%% -+-> : 
\def\tla@while{-\hspace{-.2em}\triangleright}
\def\tlawhilep{\stackrel
  {\mbox{\raisebox{-.3em}[0pt][0pt]{$\scriptscriptstyle+\;\,$}}}{\tla@while}}

%% \tlachars 
%% \notlachars 
%%    Sets / unsets the catcodes of the following characters to active
%%    :  [  =  <  -  /  |  #  "  _   ! 

\let\tlachars\tla@abbrevact
\let\notlachars\notla@abbrev



\newif\if@tlamode
\@tlamodetrue

%%%%  The following definitions are made with TLA catcodes activated and 
%%%%  with "." catcoded to mean "#".

\begingroup
\catcode`?6\relax
\tlachars

%% :
\gdef\tla@cmdcolon?1:{\ensuremath{\csname ?1\endcsname}}

%% "
\gdef\tlaquote?1"{\mbox{\rm``{\sf ?1}''}}



%% _ : 
  \gdef\tlaunder{\hspace*{\tla@indentspace}%
                         \@nsifnextchar{_}{\tla@spaceunder}{}}
  \gdef\tla@spaceunder_{\hspace*{\tla@indentspace}%
                         \@nsifnextchar{_}{\tla@spaceunder}{}}

\endgroup

%%%%%%%%%%%%%%%%%%%%%%%%  end of active characters  %%%%%%%%%%%%%%%%%


%% \optional
\newcommand{\xtla}{\begingroup \notlachars \@xtla}
\newcommand{\@xtla}[1]{#1\endgroup}


%% :
%% \coloncommands
%% \nocoloncommands
%%    Declarations that enable or disable the interpreting of :...: as 
%%    commands in TLA mode. However, :\: is always interpreted as \backslash
%%    in TLA mode.  The default is \coloncommands.
\newcommand{\coloncommands}{%
  \def\tlacolon{\@ifspace{\tla@realcolon}{\tla@cmdcolon}}} 
\newcommand{\nocoloncommands}{\def\tlacolon{\tla@realcolon}}

\coloncommands  %% THE DEFAULT
\def\tla@realcolon{\ifmmode \,:\,\else{\rm :}\fi}

%% [   makes [] : \Box       %%% must be changed if ] is made active
%\def\tla@lb{\@nsifnextchar{]}{\tla@lbx}{[}}
%\def\tla@lbx]{\ensuremath{\Box}}

%% =   
%\def\tla@realeq{=}

%% <
%\def\tla@reallt{\ensuremath{<}}

%% >
%\def\tla@realgt{\ensuremath{>}}

%% !
%\def\tla@bang{\ensuremath{\tlathin!\tlathin}}

%% / : defines \tlaslash so \tlaslash\ expands to \land
\def\tlaslash{\@nsifnextchar{\ }{\tla@slashx}{/}}
\def\tla@slashx\ {\ensuremath{\land}}

% The following was a valiant attempt to make /\ work when
% not followed by a space.  However, it doesn't work if the /\ is
% inside a command argument, in which case the following "\..." has already
% been tokenized before the "/" gets a chance to look at what's ahead.
% (Isn't TeX wonderful?)
%   \def\@makebsother{\catcode`\\=12\relax}
%   \def\@makebsescape{\catcode`\\=0\relax}
%   \begingroup
%   \catcode`?=0\relax
%   \@makebsother
%   ?gdef?tlaslash
%         {?@makebsother?@nsifnextchar{\}{?tla@slashx}{?@makebsescape/}}
%   ?gdef?tla@slashx\{?@makebsescape?ensuremath{?land}}
%   ?endgroup



%% -
%\def\tla@realminus{-}

%%_
\def\tlasubscript#1{\ensuremath{\mbox{}_{#1}}}

%% |
%\def\tla@realvert{\ensuremath{|}}



%% # produces \neq
%\def\tla@hash{\ensuremath{\neq}}


%% \tla ==  Make characters active;
%%          
\def\tla{\@tlamodetrue
          \def\tla@everymath{%
                \noTeXmath
                 \tla@abbrev
                \def\/{\lor}}%
           \tla@abbrev
           \notla@abbrev
         \ifmmode\tla@everymath\fi}

\def\notla{\def\tla@everymath{}%
  \@tlamodefalse
  \TeXmath
  \def\/{\@italcor}%
  \let~\@realtilde
  \notlachars}



%%% MISCELLANY
%% \ensuremath: the LaTeX2e command
%
\def\ensuremath#1{\relax\ifmmode #1\else $#1$\fi}

% \@italcor = normal \/
% \@realtilde = normal ~
\let\@italcor\/ %%%%% \/ redefined to \or
\let\@realtilde~

% SPACING
%
% \tlathin : a math-mode space 1/2 the width of \,
%
\def\tlathin{\mskip.5\thinmuskip}
\def\indentspace#1{\def\tla@indentspace{#1}}
\indentspace{1em}


% \@ifspace{A}{B} executes A if the next token is a space token,
% else it executes B and replaces next token.
%

\def\@ifspace#1#2{\def\@tempa{#1}\def\@tempb{#2}\futurelet\@tempc\@ifspacex}
\def\@ifspacex{\ifx\@sptoken\@tempc\let\@tempd\@tempa\else
     \let\@tempd\@tempb\fi\@tempd}

% \@nsifnextchar like \@ifnextchar, except it doesn't skip over
% space tokens.
\def\@nsifnextchar#1#2#3{\let\@tempe #1\def\@tempa{#2}\def\@tempb{#3}\futurelet
    \@tempc\@ifnsnch}
\def\@ifnsnch{\ifx \@tempc \@tempe\let\@tempd\@tempa\else\let\@tempd\@tempb\fi
      \@tempd}

%%%%%%%%%%%%%%%%%%%%%%%%%%%% MATH SYMBOLS %%%%%%%%%%%%%%%%%%%
%
\newcommand{\deq}{\mathrel{\stackrel{\scriptscriptstyle\mathchar"7001}{=}}}
\def\A{\forall\,}
\def\E{\exists\,}
\newcommand{\EE}{\makebox{$\raisebox{.05em}{\makebox
   [0pt][l]{$\exists\s{-.517}\exists\s{-.517}\exists$}}\exists\s{-.517}\exists
            \s{-.517}\exists\,$}}
\renewcommand{\AA}{\makebox{$\raisebox{.05em}{\makebox
   [0pt][l]{$\forall\s{-.517}\forall\s{-.517}\forall$}}\forall\s{-.517}\forall
            \s{-.517}\forall\,$}}
\newcommand{\X}{\ensuremath{\times}}

%%%%%%%%%%%%%%%% INITIALZE

%%%%%%%%%%% LOAD pf.sty %%%%%%%%%%%%%%%
\typeout{Loading pf style}
%\input{pf.sty}
%%%% file pf.sty
% pf.sty
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                       THE pf STYLE                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  CONTENTS
%    1. Introduction
%    2. The Basic Commands
%    3. Different Styles of Numbering 
%    4. Indentation
%    5. Assumptions
%    6. Portions of a Proof
%    7. Conjunctions and Disjunctions
%    8. Miscellany
%    9. List of all Commands and Environments
%
%  1. INTRODUCTION
%
%    The pf style provides commands and environments for typesetting
%    hierarchically structured proofs.  Below is an example of what 
%    such a proof looks like, and the commands that generate it.
%    The commands are explained individually below.  Then
%
%    THE OUTPUT                         THE INPUT
%    ~~~~~~~~~~                         ~~~~~~~~~
%    Any text...                        Any text
%                                       \begin{proof}
%    1. Text of step 1.                   \step{label-1}{Text of step 1.}
%                                         \begin{proof}
%       1.1. Text of step.                  \step{label-1.1}{Text of step}
%                                            \begin{proof}
%            Proof: Paragraph                  \pf\ Paragraph proof.~\qed
%            proof. []                       \end{proof}
%                                      
%       1.2. Text of step.                   \step{label-1.2}{Text of step.}
%                                            \begin{proof}
%            Proof: Paragraph                  \pf\ Paragraph proof.~\qed
%            proof. []                       \end{proof}
%
%       1.3. QED                             \qedstep
%                                            \begin{proof}
%            1.3.1. Text of step               \step{label-1.3.1}{Text...}
%                   Proof: ... []              \begin{proof} ... \end{proof}
%                                            
%            1.3.2. QED                        \qedstep
%                   Proof: ...                 \begin{proof}...\end{proof}
%                                            \end{proof}
%                                         \end{proof}
%
%    2. Text of step 2.                   \step{label-2}{Text of step 2.}
%        Proof: ...                        \begin{proof} \pf\ ... \end{proof}
%
%    3. QED                               \qedstep
%       Proof: ...                        \begin{proof} \pf\ ... \end{proof}
%     
%
%   The best way to read such proofs is hierarchically.  To find out
%   how, search below for the \pfhidelevel command and the \hideqedproof
%   command.
%
%
% 2. THE BASIC COMMANDS
%
% The proof Environment:
%   Increments the proof depth, and indents the enclosed text the
%   appropriate amount.  For example, if the proof environment follows a
%   \step command that produces step number 2.6.7, then the first \step
%   command inside the environment will produce step number 2.6.7.1.
%
% \step{LABEL}{TEXT}
%    This command produces a proof step such as
%        2.6.7.1. TEXT
%    The step number 2.6.7.1 is determined by the position of the \step
%    command in the proof.  The LABEL is a symbol label used to refer to the
%    step number.  A subsequent \stepref{LABEL} command will generate the
%    step number 2.6.7.1.  The same LABEL may be re-used, but
%    not in a context where it is legal to refer to a previous step with the
%    same label.  (See the discussion of step numbering below.)
%    
%    This command is equivalent to
%           \begin{step+}{LABEL}
%              TEXT
%           \end{step+}
%    The step+ environment form is more convenient if TEXT is long or
%    complicated.
%
% \qedstep
%    This command produces something like
%    
%       2.6.7.5. QED
%    
%    If the proof of step 2.6.7 is a sequence of steps (rather than a
%    paragraph proof), then the last step in its proof is normally of this
%    form.  The "QED" in the statement simply denotes the current
%    goal---what must be proved to prove step 2.6.7.  The proof of this QED
%    step will be followed immediately by the
%    \end{proof} command that ends the proof of step 2.6.7.
%    
%    The pf style does not enforce this method of structuring proofs;
%    the proof of statement 2.6.7 could end with an ordinary \step
%    command.
%
% \pf, \qed
%    These are simple text-producing commands that normally begin and end a
%    paragraph-style proof.  However, they are not required.  Remember to
%    put a "\ " after the \pf command, and to tie the \qed command to the
%    last word of the proof with a "~".
%
% \pfsketch
%    
%    An intuitive prook sketch often introduces a multi-step proof, as in
%    
%         1.3. All odd numbers are prime.
%              Proof sketch:  The proof is by induction, with the
%              base case proved in step 1 and the induction step in
%              step 2.
%              1.3.1. The number 1 is a prime.
%                     Proof: ...
%              1.3.2. If n is an odd prime, then n+2 is prime.
%                     Proof: ...
%              1.3.3. QED
%                     Proof: 1.3.1, 1.3.2, and mathematical induction.
%    
%    This is entered as 
%    
%      \step{label-1.3}{All odd numbers  are prime}
%      \begin{proof}
%      \pfsketch\ The proof is by induction...
%       \step{label-1.3.2}{The number 1 is a prime}
%       ...
%      \end{proof}
%    
%    The \pfsketch command is, like \pf, just produces the text.  It isn't
%    required by the pf style.
%    
%
%  3. DIFFERENT STYLES OF NUMBERING 
%
%    In the long style of proof numbering, a step number is something like
%    2.6.7.5, meaning that it is the fifth step in the proof of statement
%    2.6.7, which is the seventh step in the proof of statement 2.6, which
%    is...  Statement 2.6.7.5 has the short name <4>5, meaning it is the
%    fifth statement in the current level-4 proof.  Numbering style is
%    controlled by the commands
%    
%      \pfshortnumbers{N} : Use short step numbers for all levels
%                           >= N (Default is N = 1, using only short
%                           numbers.
%    
%    These are local declarations that obey the usual scoping rules.  Thus,
%    putting a \pfshortnumbers declarations right after a \begin{proof}
%    command causes all steps in that proof to have short numbers.
%
%    Steps 2.6.7.5, 2.6.6.5, and 4.9.1.5 all have the same short numbers
%    <4>5.  However, no ambiguity arises from the use of short numbers
%    because at most one of these steps can be mentioned at any point in a
%    proof.  Let the ANCESTORS of step 2.6.7.5 be steps 2.6.7, 2.6, and 2.
%    Let the ELDER SIBLINGS of step 2.6.7.5 be steps 2.6.7.1, 2.6.7.2,
%    2.6.7.3, and 2.6.7.4.  The proof statement 2.6.7.5 may refer only
%    to steps in the following two sets:
%       (i) The elder siblings of itself and of its ancestors.
%      (ii) Itself and its ancestors.
%    The steps in (i) are the previously-proved assertions that can be used
%    in the proof of 2.6.7.5.  The assumptions of the steps in (ii) are the
%    ones that are being assumed in the proof.  (Assumptions are discussed
%    below.)
%    
%    The command \stepref{LABEL} anywhere in the proof of step 2.6.7.5 (or in
%    the step itself) produces the step number of a step lying in sets (i)
%    or (ii) having LABEL as its label (the first argument of its \step
%    command).  An error message is generated if the \step command has a
%    label that is the label of a step in set (i) or (ii).
%    
%    Note that the last step of a proof is never an elder sibling, so it
%    can't be in the set (i) for any statement.  A QED-step has no
%    assumptions, so it can't be in the set (ii) for any statement.  That is
%    why the \qedstep command does not specify a label.  Actually, \qedstep
%    is defined to equal \label{qedstepN}{...}, where N is the current
%.   level number. Thus, an error will be generated if two \qedstep commands 
%    occur in the same proof, since they will have the same labels.

%
%    Short step numbers are really nice.  They take up less space and are
%    easier to read.  They are the preferred form for long proofs.  However,
%    long step numbers are better for referring to a proof step from outside
%    the proof.  The pf style allows you to print the long numbers of steps as
%    marginal notes, something like
%    
%       Theorem:  ...
%       ...
%     2.4.5.6.         <4>6. All odd numbers greater than 2 are prime.
%     2.4.5.6.1.             <5>1. The number 3 is prime.
%       ...
%    
%    (The long numbers are printed in a smaller font, so it looks
%    better than you'd guess from this.)  The relevant commands are:
%    
%    \pfsidenumbers{N}{D} 
%       Print side numbers for proof steps of all levels \geq N, left-aligned 
%       a distance D to the left of the left margin of the text.
%    
%    \pfnosidenumbers  
%       Do not print side numbers (the default)
%
%
%  4. INDENTATION
%
%    There are two styles of indentation:
%    
%       Long Style 
%          1. XXXXX
%             1.1. XXXXX
%                  1.1.1. XXXXX
%                         1.1.1.1. XXXX
%                                  Proof: ...
%    
%       Short Style 
%          1. XXXXX
%            1.1. XXXXX
%              1.1.1. XXXXX
%                1.1.1.1. XXXX
%                  Proof: ...
%    
%    In the long style, the proof of a statement lines up with the text of
%    the statement.  In the short form, each level is indented the same
%    distance from the next higher level.  The relevant declarations
%    are
%    
%    \pflongindent 
%       Indent proofs to full width of item label
%    
%    \pfshortindent 
%       Indent proofs by the length parameter \pfindent (the default)
%
%
%  5. ASSUMPTIONS
%
%    A common form of a step is 
%        
%          <4>5. Assume: 1. n is an odd number
%                        2. n > 2
%                Prove:  n is prime 
%    
%    This asserts that the Prove clause follows from the Assume clause.  The
%    "QED" at the end of the proof of this step refers to the Prove clause.
%    The input to produce this is
%    
%        \step{label-4.5}{
%          \assume{\begin{enumerate}
%                    \item $n$ is an odd number
%                    \item $n>2$
%                  \end{enumumerate}}
%          \prove{$n$ is prime}}
%    
%    The relevant command syntax is
%    
%       \assume{TEXT}
%       \prove{TEXT}
%    
%    The formatting of the enumerate environment is changed to work
%    propertly inside a proof environment.  (It is actually redefined
%    to be the pfenum environment, described far below.)  Note that
%    \label and \ref command for subitem b of item 3 produces the label
%    "3b".  Note: there is an enumerate* environment that is like
%    enumerate, except it indents the items.
%     
%    
%    Another form of assumption is a Case assumption.  The statement
%    
%          <5>1. Case: n is of the form 4n+1
%    
%    means
%    
%          <5>1. Assume: n is of the form 4n+1
%                Prove:  QED
%    
%    where QED is the current goal.  A proof by cases is structured
%    as follows
%    
%          <4>5. Assume: 1. n is an odd number
%                        2. n > 2
%                Prove:  n is prime 
%    
%               <5>1. Assume: n equals 4m+1 for some m
%                     Prove:  QED
%                     Proof:  ... []
%    
%               <5>2. Assume: n equals 4m+3 for some m
%                     Prove:  QED
%                     Proof: ... []
%    
%               <5>3. QED
%                     Proof: By <5>1, <5>2, and assumption <4>.2 (which 
%                     states that n is odd), since any odd number has
%                     the form 4m+1 or 4m+3. []
%    
%    A case assumption is produced with a \case command, which works like
%    \assume and \prove.  It has the syntax
%    
%        \case{TEXT}
%    
%    Corresponding to the \assume, \prove, and \case commands are
%    the assume+, prove+, and case+ environments.  For example, \prove{TEXT}
%    is equivalent to \begin{prove+} TEXT \end{prove+}
%    
%    Note the reference, in the proof of <5>3, to the second conjunct of the
%    Assume clause in statement <4>5 as "assumption <4>.2".  Since a proof
%    of a step can only use assumptions in that step or its ancestors, a
%    level number suffices to identify an assumption.  The Assume clause of
%    statement <4>5 is called "assumption <4>".  The ".2" refers to the
%    second item in that clause.  As mentioned below, this use of ".2" to
%    refer to the second component of a conjunction can be used 
%    in other circumstances as well.
%    
%    When long numbering is used, assumptions must be referred to by the
%    name of the statement containing the assumption.  Thus, "assumption
%    2.6.7.5.2" could potentially mean either the Assume clause of statement
%    2.6.7.5.2, or the second item in the Assume clause of 2.6.7.5.  One way
%    to remove the ambiguity is to use something other than "." in long step
%    numbers.  The possibilities 2:6:7:5 and 2-6-7-5 don't look too good;
%    the best alternative to "." seems to be a raised period ($\cdot$).  The
%    "." is changed by redefining \pfdot, as described below.  Assumptions
%    are referred to with the following commands:
%    
%       \levelref{LABEL}
%         If \stepref{LABEL} produces <4>5, then \levelref{label} 
%         produces <4>.
%         If \stepref{LABEL} produces 2.6.7.5, then \levelref{label} also 
%         produces 2.6.7.5.
%
%       \toplevel
%         If \stepref{LABEL} produces <4>5, then \toplevel
%         produces "<0>".
%         If \stepref{LABEL} produces 2.6.7.5, then \toplevel
%         produces "0".
%
%
%  6. PORTIONS OF A PROOF
%
%    You may want to format only part of a proof--for example, you might
%    want to write the proof of statement 2.1.3 as a separate proof.  You'd
%    want something like
%    
%    2.1.3. All odd numbers are prime.
%           2.1.3.1. ...
%    
%    To do this, first imagine the shortest proof you can that has a
%    statement numbered 2.1.3: 
%    
%        1. X
%        2. X
%           2.1. X
%                2.1.1. X
%                2.1.2. X
%                2.1.3. All odd numbers are prime.
%                       2.1.3.1. ...
%    
%    Write this using the \step command and prove environment.  Now, change
%    every \step{LABEL}{X} command to \nostep{LABEL}, and change the proof
%    environments surrounding the proofs of steps 2 and 2.1 by noproof
%    environments.  This yields
%    
%        \begin{proof}
%          \nostep{label-1}
%          \nostep{label-2}
%          \begin{noproof}
%            \nostep{label-2.1}
%            \begin{noproof}
%              \nostep{label-2.1.1}
%              \nostep{label-2.1.2}
%        
%               \step{label-2.1.3} All oddnumbers are prime
%               \begin{proof}
%                  \step{label-2.1.3.1} ...
%               \end{proof}
%              \end{noproof}
%            \end{noproof}
%        \end{proof}
%    
%    which produces the desired result.  Note that the labels of the \nostep
%    commands can be used to refer to the corresponding step numbers.
%
%  7. CONJUNCTIONS AND DISJUNCTIONS
%
%    It is very convenient to write conjunctions as lists bulleted by \land.
%    This is done with the conj environment, where
%    
%     $X =  \begin{conj}    PRODUCES    X =  /\ A
%             A \\ B \\ C                    /\ B
%           \end{conj}$                      /\ C
%
%    The conj* environment is similar, except it numbers the conjuncts.
%    
%     $X = \begin{conj*}    PRODUCES    X = 1./\ A
%            A \\ B \\ C                    2./\ B
%          \end{conj*}$                     3./\ C
%
%    If X is defined in this way, then X.2 denotes the formula B.
%
%    The disj and disj* environments are similar. Disjuncts
%    are numbered a, b, c 
%
%    These environments are implemented with the array environment.
%    They should nest properly.  They can be used only in math mode.
%
%
%  8. MISCELLANY
%
%    \pfhidelevel{N} : A counter that controls what levels of proof
%        are shown.  The command \setcounter{pfhidelevel}{2} causes
%        only level-1 and level-2 steps to be printed, and the proofs
%        of level-2 steps (including all level-3 and higher steps)
%        to be omitted.  The default value of the counter is very large.
%        The value of the counter should always be positive.
%
%   \unhideqedproof 
%   \hideqedproof   : Used in conjunction with the pfhidelevel counter.
%        The \unhideqedproof command causes one extra level of proof 
%        to be displayed for the lowest level \qedstep.  The \hideqedproof
%        returns to the default of not showing this extra level.
%       
%    \pflet  : like \prove and \assume, but with keyword "Let"
%
%    \kwfont : Selects the font for the keywords "Proof", "Assume",
%              "Prove", and "Case".  Default is \sc; you can 
%              change it by something like \renewcommand{\kwfont}{\em}
%
%    \pfdot : Defines the "." in long step numbers.  Try
%             \renewcommand{\pfdot}{\mbox{$\cdot$}} for variety.
%
%    \pfindent : The amount by which proof levels are indented in
%                the short indent option.  Changed with \setlength.
%                This is a local declaration.
%
%    \pfstepnumber{LEVEL}{NUMBER}{LONGNUMBER} :
%        Generates either <LEVEL>NUMBER or LONGNUMBER, depending
%        on the numbering style in effect.
%
%    \pflevelnumber{LEVEL}{LONGNUMBER} :
%        Generates either <LEVEL> or LONGNUMBER, depending
%        on the numbering style in effect.
%
%    The following parameters control vertical spacing.  
%    
%      \pftopsep  : space above first proof environment
%      \pfbotsep  : space below first proof environment
%      \pfsep     : space above and below inner proof environment
%      \stepsep   : space above and below proof step
%    
%    The last two are set to zero, and probably should remain there.  It
%    might be desirable to have vertical spacing depend more finely on the
%    level number.  This can be done using the \makefcn command (see far
%    below), and will be if there seems to be a need.  However,
%    zero extra vertical spacing seems to be fine.
%
%    \pf, \qed, \pfsketch  :  Described above.  Can be changed with 
%                             \renewcommand
%
%
%  9. LIST OF ALL COMMANDS AND ENVIRONMENTS
%
%    Text-Producting Commands            Environments
%      \pf, \pfsketch                      proof
%      \qed                                noproof
%      \step                               step+   [version of \step]        
%      \nostep                             assume+ [version of \assume]
%      \qedstep                            prove+  [version of \prove]        
%      \assume                             case+   [version of \case]        
%      \prove                              conj, conj*
%      \pflet                              disj, disj*
%      \case                               pfenum, enumerate*
%      \pfdot ["." in long names]          
%      \stepref, \levelref, \toplevel
%      \pfstepnumber, \pflevelnumber
%      
%    Declarations
%      \kwfont [keyword font]
%      \pfshortnumbers
%      \pfsidenumbers, \pfnosidenumbers
%      \pflongindent, \pfshortindent
%      \pfindent
%      \pftopsep, \pfbotsep  
%      \pfsep, \stepsep   


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                       SPACING                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% COMMANDS
%   \pflongindent == Indent proofs to full width of item label
%   \pfshortindent == Indent proofs by \pfindent [the default]

\newif\if@pfLongIndent %  true if indent proof to width of label.
\@pfLongIndentfalse
\newcommand{\pflongindent}{\@pfLongIndenttrue}
\newcommand{\pfshortindent}{\@pfLongIndentfalse}

% PARAMETERS
%  \pfindent   == indentation at beginning of a proof
%  \pftopsep   == space above first proof environment
%  \pfbotsep   == space below first proof environment
%  \pfsep      == space above and below inner proof environment
%  \stepsep    == space above and below proof step
%  pfhidelevel == counter, specifying level at which proofs are hidden

\newlength{\pfindent}      
\newlength{\pftopsep}  
\newlength{\pfbotsep}  
\newlength{\pfsep}  
\newlength{\stepsep}        
\newbox{\pfbox}
\newcounter{pfhidelevel}
\setcounter{pfhidelevel}{9999}
\newcommand{\pfhidelevel}[1]{\setcounter{pfhidelevel}{#1}}

\setlength{\pfindent}{1em} 
\setlength{\pftopsep}{1ex}     % space above first proof environment
\setlength{\pfbotsep}{1ex}     % space below first proof environment
\setlength{\pfsep}{0pt}        % space above and below inner proof environment
\setlength{\stepsep}{0pt}      % space above and below proof step

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                   STEP NUMBERING                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% COMMANDS
%   \pfshortnumbers{N} == Use short step numbers for all levels >= N
%
%   \pfsidenumbers{N}{D} == print side numbers for proof steps of all
%                           levels >= N, left-aligned length D 
%                           to left of left margin
%   \pfnosidenumbers     == do not print side numbers (the default)

%\newcommand{\pflongnumbers}{\@pfLongNumberstrue}
\newcommand{\pfshortnumbers}[1]{\pfshortNumberLevel=#1\relax}

\newcount\pfshortNumberLevel \pfshortNumberLevel=0

% \@pfLongNumbersfalse}
% \newif\if@pfLongNumbers %  true if indent proof to width of label.
%\@pfLongNumbersfalse

\newcommand{\pfstepnumber}[3]{%
   \ifnum \pfLevelCount < \pfshortNumberLevel
       #3%
     \else $\langle#1\rangle#2$%
   \fi}

\newcommand{\pflevelnumber}[2]{%
   \ifnum \pfLevelCount < \pfshortNumberLevel
       #2%
     \else $\langle#1\rangle$%
   \fi}

\newif\if@pfSideNumbers %  true if putting long numbers at margin
\@pfSideNumbersfalse
\newcounter{pf@sidenumberdepth}
\newlength{\pf@sidenumberoutdent}
\newcommand{\pfsidenumbers}[2]{\@pfSideNumberstrue
     \setcounter{pf@sidenumberdepth}{#1}%
     \addtocounter{pf@sidenumberdepth}{-1}%
     \setlength{\pf@sidenumberoutdent}{#2}}
\newcommand{\pfnosidenumbers}{\@pfSideNumbersfalse}


\newcount\pfLevelCount  \pfLevelCount=0 % current level number
\newcount\pfStepCount   \pfStepCount=0  % current step number
\newcommand{\pfLongLevel}{} % The long version of current level--e.g., 2.7.5
\newcommand{\pfLongStep}{}  % The long version of current step--e.g., 2.7.5.2
\newcommand{\pfStepName}{}  % {current level name}{current step name} 

% \pfSetName ==  LongStep := current long step name
%                StepName := current step name
\newcommand{\pfSetName}{%
  \edef\pfLongStep{%
    \ifnum\pfLevelCount>\@ne
      \pfLongLevel\pfdot\the\pfStepCount
     \else\the\pfStepCount\fi}%
  \edef\pfStepName{%
   \ifnum \pfLevelCount < \pfshortNumberLevel
    {\pfLongStep}{\pfLongStep}%
    \else
     {$\langle\the\pfLevelCount\rangle$}%
     {$\langle\the\pfLevelCount\rangle\the\pfStepCount$}%
   \fi}}

% \pfSetRef{foo} ==  IF \pf@foo UNDEFINED
%                       THEN \pf@foo := StepName 
%                       ELSE WARNING
\newcommand{\pfSetRef}[1]{%
  \@ifundefined{pf@#1}%
    {\expandafter
      \edef\csname pf@#1\endcsname{\pfStepName}}%
    {\typeout{WARNING:
         proof step "#1" (<\the\pfLevelCount>\the\pfStepCount) 
        already defined}}%
    }


\newcommand{\pfPrintStepNumber}[2]{#2}
\newcommand{\pfPrintLevelNumber}[2]{#1}

% \stepref{FOO} == Print \pf@FOO as a step number
\newcommand{\stepref}[1]{\@ifundefined{pf@#1}{{\bf ??}\typeout{WARNING:
 proof step "#1" undefined}}{\expandafter\expandafter\expandafter
 \pfPrintStepNumber\csname pf@#1\endcsname}}

\newcommand{\levelref}[1]{\@ifundefined{pf@#1}{{\bf ??}\typeout{WARNING:
 proof step #1 undefined}}%
  {\expandafter\expandafter\expandafter
 \pfPrintLevelNumber\csname pf@#1\endcsname}}

\newcommand{\toplevel}{\pflevelnumber{0}{0}}

\newlength{\pf@outdent}
\newcommand{\pfSideNumber}{%
  \if@pfSideNumbers 
   \ifnum\pfLevelCount>\value{pf@sidenumberdepth}%
    \hspace*{-\pf@outdent}%
    \makebox[0pt][l]{\footnotesize\pfLongStep}%
    \hspace*{\pf@outdent}%
    \else\fi
   \else\fi}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                   THE pflist ENVIRONMENT                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% The pflist environment is the same as list environment except 
%% it can be nested deeper.

\def\pflist#1#2{\ifnum \@listdepth >15\relax \@toodeep 
     \else \global\advance\@listdepth\@ne \fi
  \rightmargin \z@ \listparindent\z@ \itemindent\z@
  \csname @list\romannumeral\the\@listdepth\endcsname 
  \def\@itemlabel{#1}\let\makelabel\@mklab \@nmbrlistfalse #2\relax
  \@trivlist
  \parskip\parsep \parindent\listparindent
  \advance\linewidth -\rightmargin \advance\linewidth -\leftmargin
  \advance\@totalleftmargin \leftmargin
  \parshape \@ne \@totalleftmargin \linewidth 
  \ignorespaces}

\def\endpflist{\global\advance\@listdepth\m@ne
    \endtrivlist}

\let\@listvii=\@listv
\let\@listviii=\@listv
\let\@listix=\@listv
\let\@listx=\@listv
\let\@listxi=\@listv
\let\@listxii=\@listv
\let\@listxiii=\@listv
\let\@listxiv=\@listv
\let\@listxv=\@listv
\let\@listxvi=\@listv

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                   THE proof ENVIRONMENT                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

\newenvironment{proof}{%       BEGIN:
  \edef\pfLongLevel          % LongLevel := 
   {\ifnum\pfLevelCount>\z@  %    IF LevelCount > 0
     \ifnum\pfLevelCount>\@ne%     THEN IF LevelCount > 1
      \pfLongLevel\pfdot\else\fi  %            THEN LongLevel * "." FI
      \the\pfStepCount       %          * StepCount
     \else\fi}%              %     ELSE FI
  \advance\pfLevelCount\@ne  %   LevelCount := LevelCount + 1
  \@tempcnta=\value{pfhidelevel}%
  \ifnum\@tempcnta<\@ne
    \setcounter{pfhidelevel}{1}%
    \typeout{WARNING: pfhidelevel < 1, setting to 1}%
    \@tempcnta=\@ne\fi
  \advance\@tempcnta\@ne
  \if@qedstep
    \advance\@tempcnta\@ne
    \ifnum\pfLevelCount 
        = \@tempcnta 
     \sbox{\pfbox}\bgroup\begin{minipage}{\textwidth}\fi
  \else     
   \ifnum\pfLevelCount 
        = \@tempcnta 
     \sbox{\pfbox}\bgroup\begin{minipage}{\textwidth}\fi\fi
  \pfStepCount=\z@           %   StepCount  := 0
  \ifnum\pfLevelCount>\@ne   %   IF LevelCount > 1
   \begin{pflist}{}{%          %     THEN Begin List with
    \topsep=\pfsep\relax     %           \topsep     := \pfsep
    \itemsep=\z@             %           \itemsep    := 0
    \parsep=\z@              %           \parsep     := 0
    \partopsep=\z@           %           \partopsep  := 0
    \if@pfLongIndent         %          IF LongIndent
     \settowidth{\leftmargin}%%           THEN
      {\expandafter          %              \leftmargin := width of step name
       \pfPrintStepNumber    %                             + \labelsep
       \pfStepName.}%
     \advance\leftmargin
     \labelsep 
    \else                    %           ELSE
    \leftmargin=\pfindent    %            \leftmargin := \pfindent
    \fi\relax        
   }   \item[]
   \else \par                %     ELSE \par
    \addvspace{\pftopsep}%   %          addvspace of \pftopsep
    \parindent=\z@           %          \parindent := 0
    \parskip = \z@           %          \parskip := 0
    \@ifundefined{mathindent}{%
      \abovedisplayskip=\z@ plus .2ex       % set display skips
      \abovedisplayshortskip=\z@ plus .2ex
      \belowdisplayskip=\z@ plus .2ex
      \belowdisplayshortskip=\z@ plus .2ex}{%
      \mathindent=1em}%
    \let\enumerate\pfenum       %   enumerate environment <- pfenum
    \let\endenumerate\endpfenum %
 \fi
\@qedstepfalse
    }%                       % END:
  {\ifnum\pfLevelCount>\@ne  %   IF LevelCount > 1
    \end{pflist}%              %     THEN End List
   \else \par                %     ELSE \par
     \addvspace{\pfbotsep}%  %          addvspace of \pfbotsep
   \fi
  \@tempcnta=\value{pfhidelevel}%
  \advance\@tempcnta\@ne
  \if@qedstep
    \advance\@tempcnta\@ne
    \ifnum\pfLevelCount 
        = \@tempcnta 
     \end{minipage}\egroup\sbox{\pfbox}{}\@qedstepfalse\fi
  \else 
      \ifnum\pfLevelCount 
        =\@tempcnta 
        \end{minipage} 
        \egroup\sbox{\pfbox}{}\fi
 \fi}


\newenvironment{noproof}{%   % BEGIN:
  \edef\pfLongLevel          % LongLevel := 
   {\ifnum\pfLevelCount>\z@  %    IF LevelCount > 0
     \ifnum\pfLevelCount>\@ne%     THEN IF LevelCount > 1
      \pfLongLevel.\else\fi  %            THEN LongLevel * "." FI
      \the\pfStepCount       %          * StepCount
     \else\fi}%              %     ELSE FI
  \advance\pfLevelCount\@ne  %   LevelCount := LevelCount + 1
  \pfStepCount=\z@           %   StepCount  := 0
  \par                       %   \par
  \parindent=\z@             %          \parindent := 0
  \parskip = \z@             %          \parskip := 0
  \@ifundefined{mathindent}{%
      \abovedisplayskip=\z@ plus .2ex       % set display skips
      \abovedisplayshortskip=\z@ plus .2ex
      \belowdisplayskip=\z@ plus .2ex
      \belowdisplayshortskip=\z@ plus .2ex}{%
      \mathindent=1em}%
  \let\enumerate\pfenum       %   enumerate environment <- pfenum
  \let\endenumerate\endpfenum %
  }%                         % END:
  {\par}                     %  \par

%% step 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     \step, \assume, ETC.                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\newcommand{\step}[2]{\begin{step+}{#1}#2\end{step+}}
\newif\if@qedstep %  true right after a \qedstep if in the scope of an 
                  %  \unhideqedproof declaration
\@qedstepfalse

\newif\if@unhideqedstep % set true by \unhideqproof, false by \hideqproof. 

\@unhideqedstepfalse
\newcommand{\unhideqedproof}{\@unhideqedsteptrue}
\newcommand{\hideqedproof}{\@unhideqedstepfalse}

\newcommand{\qedstep}{\step{qedstep\the\pfLevelCount}{Q.E.D.}
\if@unhideqedstep\@qedsteptrue\fi}

\newcommand{\nostep}[1]{% 
  \advance\pfStepCount\@ne       % StepCount := StepCount + 1
  \pfSetName                     % SetName
  \pfSetRef{#1}%                 % SetRef
  }

\newenvironment{step+}[1]%
 {\endgroup                      % Move Outside environment scope
  \advance\pfStepCount\@ne       % StepCount := StepCount + 1
  \pfSetName                     % SetName
  \pfSetRef{#1}%                 % SetRef
 \begingroup\@endpefalse         % Move inside environment scope
   \def\@currenvir{step+}%       %   by simulating \begin{step+}
 \begin{pflist}{}{%                % Begin list environment with
   \setlength
     {\pf@outdent}{\textwidth}%  %   \pf@outdent = outdent
   \addtolength                  %                 for side numbers
    {\pf@outdent}{-\linewidth}%  
   \addtolength
    {\pf@outdent}%
    {\pf@sidenumberoutdent}%
   \topsep=\stepsep\relax        %   \topsep     := \stepsep
   \itemsep=\z@                  %   \itemsep    := 0
   \parsep=\z@                   %   \parsep     := 0
   \partopsep=\z@                %   \partopsep  := 0
   \settowidth{\labelwidth}%     %   \labelwidth := width of step name.
     {\expandafter
      \pfPrintStepNumber
      \pfStepName.}%
   \leftmargin=\labelwidth\relax %   \leftmargin := \labelwidth
   \advance\leftmargin\labelsep %                   + \labelsep
   \relax}%
 \item[\pfSideNumber%               % \item[ \pfSideNumber
  \expandafter                       %        StepNumber]
  \pfPrintStepNumber\pfStepName.]}%
 {\end{pflist}}

%%%%% \assume, \prove, and \case commands

\newenvironment{assume+}{%
 \begin{pflist}{}{%                % Begin list environment with
   \topsep=\z@                   %   \topsep     := 0
   \itemsep=\z@                  %   \itemsep    := 0
   \parsep=\z@                   %   \parsep     := 0
   \partopsep=\z@                %   \partopsep  := 0
   \settowidth{\labelwidth}%     %   \labelwidth := width "Assume:"
     {{\kwfont Assume\/}:}%
   \leftmargin=\labelwidth\relax %   \leftmargin := \labelwidth
   \advance\leftmargin\labelsep  %                   + \labelsep
   \relax}%
 \item[{\kwfont Assume\/}:]}%    % \item[Assume:]]
 {\end{pflist}}

\newcommand{\assume}[1]{\begin{assume+}#1\end{assume+}}

\newcommand{\prove}[1]{\begin{prove+}#1\end{prove+}}
\newenvironment{prove+}{%
 \begin{pflist}{}{%                % Begin list environment with
   \topsep=\z@                   %   \topsep     := 0
   \itemsep=\z@                  %   \itemsep    := 0
   \parsep=\z@                   %   \parsep     := 0
   \partopsep=\z@                %   \partopsep  := 0
   \settowidth{\labelwidth}%     %   \labelwidth := width "Assume:"
     {{\kwfont Assume\/}:}%
   \leftmargin=\labelwidth\relax %   \leftmargin := \labelwidth
   \advance\leftmargin\labelsep  %                   + \labelsep
   \relax}%
 \item[{\kwfont 
          Prove\/}:\hfill]}%     % \item[Prove:]]
 {\end{pflist}}

\newcommand{\pflet}[1]{\begin{pflet+}#1\end{pflet+}}
\newenvironment{pflet+}{%
 \begin{pflist}{}{%                % Begin list environment with
   \topsep=\z@                   %   \topsep     := 0
   \itemsep=\z@                  %   \itemsep    := 0
   \parsep=\z@                   %   \parsep     := 0
   \partopsep=\z@                %   \partopsep  := 0
   \settowidth{\labelwidth}%     %   \labelwidth := width "Assume:"
     {{\kwfont Let\/}:}%
   \leftmargin=\labelwidth\relax %   \leftmargin := \labelwidth
   \advance\leftmargin\labelsep  %                   + \labelsep
   \relax}%
 \item[{\kwfont 
          Let\/}:\hfill]}%     % \item[Let:]]
 {\end{pflist}}

%\newcommand{\prove}[1]{%
% \begin{pflist}{}{%                % Begin list environment with
%   \topsep=\z@                   %   \topsep     := 0
%   \itemsep=\z@                  %   \itemsep    := 0
%   \parsep=\z@                   %   \parsep     := 0
%   \partopsep=\z@                %   \partopsep  := 0
%   \settowidth{\labelwidth}%     %   \labelwidth := width "Assume:"
%     {{\kwfont Assume\/}:}%
%   \leftmargin=\labelwidth\relax %   \leftmargin := \labelwidth
%   \advance\leftmargin\labelsep  %                   + \labelsep
%   \relax}%
% \item[{\kwfont Prove\/}:\hfill]     % \item[Prove:]]
% #1
% \end{pflist}}

\newcommand{\case}[1]{%
 \begin{pflist}{}{%                % Begin list environment with
   \topsep=\z@                   %   \topsep     := 0
   \itemsep=\z@                  %   \itemsep    := 0
   \parsep=\z@                   %   \parsep     := 0
   \partopsep=\z@                %   \partopsep  := 0
   \settowidth{\labelwidth}%     %   \labelwidth := width "Case:"
     {{\kwfont Case\/}:}%
   \leftmargin=\labelwidth\relax %   \leftmargin := \labelwidth
   \advance\leftmargin\labelsep  %                   + \labelsep
   \relax}%
 \item[{\kwfont
           Case\/}:]             % \item[Case:]]
 #1
 \end{pflist}}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                       MISCELLANY                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\newcommand{\pf}{{\kwfont Proof\/}:}
\newcommand{\pfsketch}{{\kwfont Proof sketch\/}:}
%\newcommand{\qed}{\rule{.4em}{1.75ex}}
\newcommand{\qed}{{\fboxsep=\z@\fbox{\rule{.5em}{0pt}\rule{0pt}{2ex}}}}
\let\kwfont=\sc
\def\pfdot{.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                        STACKS                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \@push{\stack}{element}  == \stack := <<element>> :o: \stack
% \@pop{\stack}{\cmd}  == \cmd := head(\stack)
%                            \stack := tail(\stack)
% \newstack{\stack}  == \stack := emptystack
%
% \@head{\stack}{\var}  ==  \var := head(\stack)
%   Note: to push a counter value, use \the\value{ctr}
%         to push a length \foo, use \the\foo

%
\def\@push#1#2{{\let\@nil\relax\let\@elt\relax\xdef#1{#2\@elt#1}}}
\def\@pop#1#2{{\let\@nil\relax\let\@elt\relax
              \xdef#2{\expandafter\@innerhead#1}
              \xdef#1{\expandafter\@innerpop#1}}}
\def\@innerpop#1\@elt#2\@nil{#2\@nil}
\def\@head#1#2{{\let\@elt\relax\xdef#2{\expandafter\@innerhead#1}}}
\def\@innerhead#1\@elt#2\@nil{#1}
\def\newstack#1{\gdef#1{\@nil}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%           LISTS OF CONJUNCTIONS AND DISJUNCTIONS            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%    \begin{conj}       ->   /\ A
%      A \\ B \\ C           /\ B
%    \end{conj}              /\ C
%
%    \begin{conj*}      ->   1./\ A
%      A \\ B \\ C           2./\ B
%    \end{conj*}             3./\ C
%
%    The disj and disj* environments are similar. Disjuncts
%    are numbered a, b, c 
%
%    These environments are arrays; they must be used in math mode.

\newcounter{pf@conjCounter}   % counter for conj* and disj*
\newstack\pf@conj             % stack of counters

\newenvironment{conj}{%
 \begin{array}[t]{@{\land\;}l@{}}%
 }{%
 \end{array}}

\newenvironment{disj}{%
 \begin{array}[t]{@{\lor\;}l@{}}%
 }{%
 \end{array}}

\newenvironment{conj*}{%
 \@push\pf@conj{\the\value{pf@conjCounter}}%
 \setcounter{pf@conjCounter}{0}%
 \begin{array}[t]{@{\addtocounter{pf@conjCounter}{1}%
   \mbox{\protect\small\protect\arabic{pf@conjCounter}.}
   \land\;}l@{}}%
 }{%
 \end{array}%
 \@pop\pf@conj\pf@temp
  \setcounter{pf@conjCounter}{\pf@temp}}

\newenvironment{disj*}{%
 \@push\pf@conj{\the\value{pf@conjCounter}}%
 \setcounter{pf@conjCounter}{0}%
 \begin{array}[t]{@{\addtocounter{pf@conjCounter}{1}%
   \mbox{\protect\small\protect\alph{pf@conjCounter}.}
   \lor\;}l@{}}%
 }{%
 \end{array}%
 \@pop\pf@conj\pf@temp
  \setcounter{pf@conjCounter}{\pf@temp}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      ENUMERATED LISTS                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pfenum environment : In proofs, the enumerate environment 
%                      is redefined to be the pfenum environment
%
% enumerate* environment : Like pfenum, except with additional
%                          indentation.
%
% \enumindent :  The indentation for enumerate*
% pfenumdepth  : Depth of current pfenum list
% pfenum       : pfenum list counter
%
% Uses counters pfenumi, ... , pfenumiii just like the
% ordinary enumerate environment uses counters enumi, ... , enumiv.
% \pf@setEnumWidth{\cmd} : Sets \cmd to the width of the label of the
%                          item number 2 for the current enumeration level.
%
% \pf@enumLabel : prints the current pfenum label, using the
%                 pfenumi... counter.

\newcounter{pfenum}
\newcounter{pfenumdepth}
\newlength{\enumindent}
\setlength{\enumindent}{1em}

\@definecounter{pfenumi}
\@definecounter{pfenumii}
\@definecounter{pfenumiii}
%\@definecounter{pfenumiv}

\def\labelpfenumi{\thepfenumi.}    
\def\thepfenumi{\arabic{pfenumi}}     
 
\def\labelpfenumii{(\thepfenumii)}
\def\thepfenumii{\alph{pfenumii}}
\def\p@pfenumii{\thepfenumi}

\def\labelpfenumiii{\thepfenumiii.}
\def\thepfenumiii{\roman{pfenumiii}}
\def\p@pfenumiii{\thepfenumi\thepfenumii}

%\def\labelpfenumiv{\thepfenumiv.}
%\def\thepfenumiv{\Alph{pfenumiv}}     
%\def\p@pfenumiv{\p@pfenumiii\thepfenumiii}


\newcommand{\pf@setEnumWidth}[1]{%
  \settowidth{#1}{\setcounter{\@pfenumctr}{2}%
  \csname the\@pfenumctr\endcsname.%
  \setcounter{\@pfenumctr}{0}}}



\newcommand{\pf@enumLabel}{%
  \hfill\makebox[0pt][r]{\csname the\@pfenumctr\endcsname.}}

\newenvironment{pfenum}{%        % BEGIN
  \ifnum \value{pfenumdepth}>2%  %  IF pfenumdepth > 2
    \relax\@toodeep \else        %    THEN error
  \addtocounter{pfenumdepth}{1}% %    ELSE  pfenumdepth := pfenumdepth + 1
  \edef\@pfenumctr{pfenum%           %          @pfenumctr  := pfenumN
    \romannumeral\the            %            where N = Roman(pfenumdepth)
    \value{pfenumdepth}}%        %
   \fi                           %  FI
  \begin{pflist}%                  %   Begin list environment with
  {\pf@enumLabel}{%              %    Default label = pf@enumlabel
   \labelsep=                    %   \labelsep =
    \ifcase\value{pfenumdepth}   %     CASE OF pfenumdepth
      \labelsep                  %        
     \or .67\labelsep            %       1 -> .67\labelsep
     \or .67\labelsep            %       2 -> .67\labelsep
     \else \labelsep             %      >2 -> \labelsep
     \fi                         %
   \topsep=\z@                   %    \topsep     := 0
   \itemsep=\z@                  %    \itemsep    := 0
   \parsep=\z@                   %    \parsep     := 0
   \partopsep=\z@                %    \partopsep  := 0
   \pf@setEnumWidth\labelwidth   %    set \labelwidth with setEnumWidth
   \leftmargin=\labelwidth\relax %    \leftmargin := \labelwidth
   \advance\leftmargin\labelsep  %                   + \labelsep
   \relax
   \usecounter{\@pfenumctr}%       %    counter @pfenumctr
 }%
 }{%                             % END
   \end{pflist}%                   %   End list
   \addtocounter{pfenumdepth}{-1}%   pfenumdepth := pfenumdepth - 1
 }

\newenvironment{enumerate*}{%    % BEGIN
  \ifnum \value{pfenumdepth}>2%  %  IF pfenumdepth > 2
    \relax\@toodeep \else        %    THEN error
  \addtocounter{pfenumdepth}{1}% %    ELSE  pfenumdepth := pfenumdepth + 1
  \edef\@pfenumctr{pfenum%           %          @pfenumctr  := pfenumN
    \romannumeral\the            %            where N = Roman(pfenumdepth)
    \value{pfenumdepth}}%        %
   \fi                           %  FI
  \begin{pflist}%                  %   Begin list environment with
  {\pf@enumLabel}{%              %    Default label = pf@enumlabel
   \labelsep=                    %   \labelsep =
    \ifcase\value{pfenumdepth}   %     CASE OF pfenumdepth
      \labelsep                  %        
     \or .67\labelsep            %       1 -> .67\labelsep
     \or .67\labelsep            %       2 -> .67\labelsep
     \else \labelsep             %      >2 -> \labelsep
     \fi                         %
   \topsep=\z@                   %    \topsep     := 0
   \itemsep=\z@                  %    \itemsep    := 0
   \parsep=\z@                   %    \parsep     := 0
   \partopsep=\z@                %    \partopsep  := 0
   \pf@setEnumWidth\labelwidth   %    set \labelwidth with setEnumWidth
   \leftmargin=\labelwidth\relax %    \leftmargin := \labelwidth
   \advance\leftmargin\labelsep  %                   + \labelsep
   \advance\leftmargin\enumindent%                   + \enumindent
   \relax
   \usecounter{\@pfenumctr}%       %    counter @pfenumctr
 }%
 }{%                             % END
   \end{pflist}%                   %   End list
   \addtocounter{pfenumdepth}{-1}%   pfenumdepth := pfenumdepth - 1
 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                        FUNCTIONS                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% \makefcn{\FOO}{V0}{{V1}...{Vk}} :
%      Defines \FOO{n}  ==  CASE  n = 0    -> V0
%                                 n = 1    -> V1
%                                 ...
%                                 n \geq k -> Vk
%
%      Useful when Vi is a dimension applying to a depth-i environment

\def\makefcn#1#2#3{{\let\or\relax
     \gdef\fcn@temp{}%
     \gdef\fcn@tempb{#2}%
     \@tfor\foo:=#3\do{\xdef\fcn@temp{\fcn@temp\or\foo}\xdef\fcn@tempb{\foo}}%
     \let\ifcase\relax\let\else\relax\let\fi\relax
     \xdef#1##1{\ifcase ##1 #2\fcn@temp\else\fcn@tempb\fi}}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                        FUNCTIONS                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \pfif{A}{B}{C} :  if A then B    \pfIF{A}{B}{C} :  if A
%                        else C                        THEN B
%                                                      ELSE C

\newcommand{\pfmathdef}[1]{\relax\ifmmode #1\else $#1$\fi}
\newcommand{\pfif}[3]{{\pfmathdef{%
 \begin{array}[t]{@{}l@{\;\;}l@{\;\;}l@{}}
   {\bf if}\;\;#1&{\bf then}&#2\\
                 &{\bf else}&#3
   \end{array}}}}

\newcommand{\pfIF}[3]{{\pfmathdef{%
 \begin{array}[t]{@{}l@{\;\;}l@{}}
   {\bf if}\;\;#1\\ 
  \begin{array}[t]{@{\hspace{1em}}l@{\;\;}l@{}}
     {\bf then}&#2\\
     {\bf else}&#3
   \end{array}
  \end{array}}}}

%%%% end file pf.sty

\tla


% Redefine conj and disj to leave more space, and \pf to remove
% \/.

\renewenvironment{conj}{%
 \begin{array}[t]{@{\land\ }l@{}}%
 }{%
 \end{array}}

\renewenvironment{disj}{%
 \begin{array}[t]{@{\lor\ }l@{}}%
 }{%
 \end{array}}

\renewenvironment{conj*}{%
 \@push\pf@conj{\the\value{pf@conjCounter}}%
 \setcounter{pf@conjCounter}{0}%
 \begin{array}[t]{@{\addtocounter{pf@conjCounter}{1}%
   \mbox{\protect\small\protect\arabic{pf@conjCounter}.}
   \land\ }l@{}}%
 }{%
 \end{array}%
 \@pop\pf@conj\pf@temp
  \setcounter{pf@conjCounter}{\pf@temp}}

\renewenvironment{disj*}{%
 \@push\pf@conj{\the\value{pf@conjCounter}}%
 \setcounter{pf@conjCounter}{0}%
 \begin{array}[t]{@{\addtocounter{pf@conjCounter}{1}%
   \mbox{\protect\small\protect\alph{pf@conjCounter}.}
   \lor\ }l@{}}%
 }{%
 \end{array}%
 \@pop\pf@conj\pf@temp
  \setcounter{pf@conjCounter}{\pf@temp}}

\renewcommand{\pf}{{\kwfont Proof\@italcor}:}

%%%%%%%%%%%%% redefine some pf.sty commands with $ having its normal definition
\begingroup
\catcode`$3\relax

\gdef\pfstepnumber#1#2#3{%
   \ifnum \pfLevelCount < \pfshortNumberLevel
       #3%
     \else $\langle#1\rangle#2$%
   \fi}

\gdef\pflevelnumber#1#2{%
   \ifnum \pfLevelCount < \pfshortNumberLevel
       #2%
     \else $\langle#1\rangle$%
   \fi}

\gdef\pfSetName{%
  \edef\pfLongStep{%
    \ifnum\pfLevelCount>\@ne
      \pfLongLevel\pfdot\the\pfStepCount
     \else\the\pfStepCount\fi}%
  \edef\pfStepName{%
   \ifnum \pfLevelCount < \pfshortNumberLevel
    {\pfLongStep}{\pfLongStep}%
    \else
     {$\langle\the\pfLevelCount\rangle$}%
     {$\langle\the\pfLevelCount\rangle\the\pfStepCount$}%
   \fi}}
\endgroup

%% Redefine \step, \assume, \prove, \pflet, and \case  so their arguments
%% have characters made active.

\let\tla@stepy\step
\renewcommand{\step}[1]{\begingroup\if@tlamode\tlachars\fi\tla@stepx{#1}}
\newcommand{\tla@stepx}[2]{\endgroup\tla@stepy{#1}{#2}}
%% 27 Dec 95 -- changed \def to \newcommand

\let\tla@assumey\assume
\renewcommand{\assume}{\begingroup\if@tlamode\tlachars\fi\tla@assumex}
\newcommand{\tla@assumex}[1]{\endgroup\tla@assumey{#1}}

\let\tla@provey\prove
\renewcommand{\prove}{\begingroup\if@tlamode\tlachars\fi\tla@provex}
\newcommand{\tla@provex}[1]{\endgroup\tla@provey{#1}}

\let\tla@casey\case
\renewcommand{\case}{\begingroup\if@tlamode\tlachars\fi\tla@casex}
\newcommand{\tla@casex}[1]{\endgroup\tla@casey{#1}}

\let\tla@pflety\pflet
\renewcommand{\pflet}{\begingroup\if@tlamode\tlachars\fi\tla@pfletx}
\newcommand{\tla@pfletx}[1]{\endgroup\tla@pflety{#1}}


%%%%%%%%%%%%%%  Module formatting commands

%%%% noj, if/then/else %%%%%%%%%%%%%%%%%%
\def\IF#1{\begin{array}[t]{@{}l@{}l@{}l@{}}%
            \@ifnextchar{\\}%
              {\makebox[.6em][l]{{\bf if\, }$#1$}}{\mbox{{\bf if }$#1$ }}}
\def\THEN{&\mbox{\bf \,then }&\begin{array}[t]{@{}l@{}}}
\def\ELSE{\end{array}\\ &\mbox{\bf \,else }&\begin{array}[t]{@{}l@{}}}
\def\FI{\end{array}\end{array}}

\newenvironment{noj}{\begin{array}[t]{@{}l@{}}}{\end{array}}
\newenvironment{noj2}{\begin{array}[t]{@{}l@{\;\;}l@{}}}{\end{array}}
\newenvironment{noj3}{\begin{array}[t]{@{}l@{\;\;}l@{\;\;}l@{}}}{\end{array}}
\newenvironment{noj4}%
  {\begin{array}[t]{@{}l@{\;\;}l@{\;\;}l@{\;\;}l@{}}}{\end{array}}

%\newenvironment{noj}{\begin{array}[t]{@{}l@{}}}%
%                    {\end{array}}


%%%% let %%%%%%%%
\newcommand{\LET}{\begin{array}[t]{@{}l@{\;\;}l@{}} {\bf let}% 
                              &\begin{array}[t]{@{}l@{}}} 
\newcommand{\IN}{\end{array}\\{\bf in}&\begin{array}[t]{@{}l@{}}}
\newcommand{\NI}{\end{array}\end{array}}

%%%% case %%%
\newcommand{\CASE}{{\bf case\ }}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
%                  COMMANDS FROM spec92.sty                      %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
\newlength{\@charwidth}
\settowidth{\@charwidth}{{\small\tt M}}
\newlength{\boxrulewd}\setlength{\boxrulewd}{.4pt}
\newlength{\boxindent}\setlength{\boxindent}{22\@charwidth}
\newlength{\boxlineht}\setlength{\boxlineht}{.5\baselineskip}
\newcommand{\boxsep}{\@charwidth}
\newlength{\boxruleht}
\newlength{\boxruledp}
\newcommand{\@computerule}{%
  \setlength{\boxruleht}{.5ex}%
  \setlength{\boxruledp}{-\boxruleht}%
  \addtolength{\boxruledp}{\boxrulewd}}
\newcommand{\boxrule}{\leaders\hrule height \boxruleht depth \boxruledp
                      \hfill\mbox{}}

\newcommand{\@nmlineraise}{\if@botline -\boxrulewd
    \else-\boxlineht\fi}
\newcommand{\nameline}[1]{\hspace*{-\boxsep}%
    \raisebox{\@nmlineraise}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}%
    \boxrule
    #1\boxrule
    \raisebox{\@nmlineraise}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}\hspace{-\boxsep}\vspace{.5\baselineskip}}
\newif\if@botline

%%%%%%%%%%%%%%%%%%END COMMANDS FROM spec92.sty %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\topbar}[1]{\tlanameline{\ 
     {\bf module} {\it #1\@italcor} }\par}

\newenvironment{nomodule}{\begin{trivlist}\flushleft\@computerule
            \item[]\it
            \catcode`_=\active\relax
        }{\par\end{trivlist}}

\newenvironment{module}[1]{\begin{trivlist}\flushleft\@computerule
            \item[]\tlanameline{\ {\bf module} {\it #1\@italcor} }\par\it
            \catcode`_=\active\relax
        }{\par\bottombar\end{trivlist}}


\newenvironment{submodule}[1]{\par
        \vspace{-.5em}%%%%%%%%%%%  space at top of submodule
    \begin{list}{}{%
       \leftmargin=1em%
       \labelwidth=0pt%
       \labelsep=0pt%
       \parsep=0pt%
       \topsep=0pt%
       \partopsep=0pt%
       \itemsep=0pt}\flushleft\@computerule
            \item[]\tlanameline{\ {\bf module} {\it #1\@italcor} }\par
        }{\par\bottombar\end{list}}


\newcommand{\tlanameline}[1]{\hspace*{-\boxsep}%
    \raisebox{\@nmlineraise}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}%
    \boxrule
    #1\boxrule
    \raisebox{\@nmlineraise}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}\hspace{-\boxsep}%
          \vspace{.2em}%%% EXTRA SPACE BELOW TOP LINE OF MODULE
               }

%%%%% Fix to \midline and \botline from spec92

\newcommand{\midbar}{\par\hspace{-\boxsep}%
    \raisebox{-.5\boxlineht}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}%
     \boxrule
    \raisebox{-.5\boxlineht}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}\hspace{-\boxsep}%
         \vspace{-.2em}%%% SPACE BELOW \midbar
                \par}

\newcommand{\bottombar}{\hspace{-\boxsep}%
    \raisebox{-\boxrulewd}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}%
     \boxrule
    \raisebox{-\boxrulewd}[0pt][0pt]{\rule[.5ex]{\boxrulewd
               }{\boxlineht}}\hspace{-\boxsep}\vspace{0pt}}

\newcommand{\xtrivlist}{\begin{list}{}{%
       \leftmargin=1em%
       \labelwidth=0pt%
       \labelsep=0pt%
       \parsep=0pt%
       \topsep=0pt%     
       \partopsep=0pt%
       \itemsep=0pt}}
\def\endxtrivlist{\end{list}}

\let\@@startfield\@startfield
\let\@@stopfield\@stopfield

%% need to change \@tabcr because its look-ahead at the next
%  character causes that character to be prematurely cat-coded.
%
\def\tla@tabcr{\@stopline\@startline\ignorespaces}

\def\xtabbing{\lineskip \z@\let\>\@rtab\let\<\@ltab\let\=\@settab
     \def\@startfield{\@@startfield\(}
     \def\@stopfield{\)\@@stopfield}
     \let\+\@tabplus
     \let\-\@tabminus
     \let\`\@tabrj\let\'\@tablab
     \let\\=\tla@tabcr
     \global\@hightab\@firsttab
     \global\@nxttabmar\@firsttab
     \dimen\@firsttab\@totalleftmargin
     \global\@tabpush0 \global\@rjfieldfalse
     \xtrivlist \item[]\if@minipage\else\vskip\parskip\fi
     \setbox\@tabfbox\hbox{\rlap{\indent\hskip\@totalleftmargin
       \the\everypar}}\def\@itemfudge{\box\@tabfbox}\@startline\ignorespaces}

\def\endxtabbing{\@stopline\ifnum\@tabpush > 0 \@badpoptabs \fi\endxtrivlist}

\newenvironment{decls}[1]{\par
      \addvspace{.4em}%%%  EXTRA SPACE ABOVE decls ENVIRONMENT
{\bf #1}\begin{xtabbing}%
  \hspace{1em}\=\+\kill}{\end{xtabbing}}

\newenvironment{nodecls}{\par
      \addvspace{.4em}%%%  EXTRA SPACE ABOVE nodecls ENVIRONMENT
\begin{xtabbing}}{\end{xtabbing}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%% KEYWORDS %%%%%%%%%%%%%%%%%%
%
\newcommand{\tlacomment}{\begingroup\tlachars\@comment}
%\newcommand{\@tlacomment}[1]{\endgroup\mbox{\footnotesize\rm #1}}
\newcommand{\comment}{\begingroup\notlachars\@comment}
\newcommand{\@comment}[1]{\endgroup
    \raisebox{0pt}[0pt][0pt]{\footnotesize\rm %
       \begin{tabular}[t]{@{}l@{}}#1\end{tabular}}}
%\newcommand{\@comment}[1]{\endgroup
%    \mbox{\footnotesize\rm \raisebox{0pt}[0pt][0pt]{%
%       \begin{tabular}[t]{@{}l@{}}#1\end{tabular}}}}
\newcommand{\VARIABLE}{\mbox{\sc variable}}
\newcommand{\ACTION}{\mbox{\sc action}}
\newcommand{\STATEFCN}{\mbox{\sc state fcn}}
\newcommand{\IMPORT}{{\bf import }}
\newcommand{\EXPORT}{{\bf export }}
\newcommand{\INCLUDE}{{\bf include }}
\newcommand{\AS}{\,{\bf as }}
\newcommand{\WITH}{\,{\bf with }}
\newcommand{\CONSTANT}{\mbox{\sc constant}}
\newcommand{\BOOLEAN}{\mbox{\sc boolean}}
\newcommand{\UNION}{\mbox{\sc union }}
\newcommand{\TRUE}{\mbox{\sc true}}
\newcommand{\FALSE}{\mbox{\sc false}}
\newcommand{\UNCHANGED}{\mbox{\sc unchanged }}
\newcommand{\EXCEPT}{\mbox{\sc\ except }}
\newcommand{\CHOOSE}{\mbox{\sc choose }}
\newcommand{\ENABLED}{\mbox{\sc Enabled\s{.2}}}
\newcommand{\DOMAIN}{\mbox{\sc Domain\s{.2}}}
\newcommand{\SUBSET}{\mbox{\sc Subset\s{.2}}}
\newcommand{\WF}{\mbox{\rm WF}}
\newcommand{\SF}{\mbox{\rm SF}}

%%%%%%%%%%%%%%%%%%%%%%% SPACE COMMANDS %%%%%%%%%%%%%%%%%%%%%%
%
\newcommand{\s}{\begingroup\notlachars\tla@s}
\newcommand{\tla@s}[1]{\endgroup\hspace*{#1em}}
\newcommand{\vs}{\begingroup\notlachars\tla@vs}
\newcommand{\tla@vs}[1]{\endgroup\ifinner
                       \raisebox{-.34em}{\raisebox{-#1em}{\rule{0pt}{.1pt}}}
                      \else \vspace{#1em}\fi}
%%% 1 Mar 95 : Made \V work with negative argument.
\newcommand{\V}{\begingroup\notlachars\tla@V}
\def\tla@V#1{\endgroup\ifdim #1em<\z@\\[#1em]\else\vs{#1}\\\fi} 

%%% end file tla.sty
\makeatother

\title{Lazy Caching in TLA}
\author{Peter Ladkin 
\and Leslie Lamport 
\and Bryan Olivier
\and Denis Roegel}
\date{18 January 1996}

%% Cleared by Sam, 5 Dec 94

%% Changes from 11 July version:
%%  Re-inserted comma after "parameters, $cc$, $cin$, and $cout$,"

%% Changes in going from newgerth.tex -> gerth2.tex
%%
%%  * Move definitions of POp, OKOp, and InitDB from MemParams to 
%%    CacheCorrectness.
%%  * Move definition of Op to ACCache and ????
%%  * Move SeqDB1.Spec -> SeqDB2.Spec to a separate module, since it should
%%    be proved for an arbitrary OKOp, not just for the one defined by
%%    MemParams.
%%  * Corrected definition of Write in LazyCache to make out[i] a sequence
%%    of pairs instead of 4-tuples.

%% Changes to newgerth.tex
%% 15 Jan 96 - Revised for resubmission
%% 26 Apr 95 - "->" -> "|->" in def of Init in LazyCache module (p 24)
%% 25 Apr 95 - "Th" -> "th" (page 10)
%% 30 Jan 95 - Corrected definition of Write in CCache
%% 16 Jan 95 - Corrected definition of Proj in SeqDB2
%%  3 Jan 95 - Corrected nondefinition of Spec in SeqDB2.
%% Needed to fix bug/feature in LaTeX2e
\def\ensuremath#1{\relax\ifmmode #1\else $#1$\fi}
%\input{grid}


%&"&"#"&

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                 MODIFICATION DATE                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                 %
% Defines \moddate to expand to modification date such as         %
%                                                                 %
%    Mon  5 Aug 1991  [10:34]                                     %
%                                                                 %
% and \prdate to print it in a large box.  Assumes editor         %
% updates modification date in standard SRC Gnu Emacs style.      %
% (should work for any user name).                                %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\ypmd{%                                                       %
%                                                                 %
%                                                                 %
  endypmd}                                                        %
%                                                                 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\moddate}{\expandafter\xpmd\ypmd}                     %
\def\xpmd Last modified                                           %
on #1 #2 #3 #4:#5:#6 #7 #8 by #9 endypmd{#1 \ #3 #2 #8 \ [#4:#5]} %
\newcommand{\prdate}{\noindent\fbox{\Large\moddate}}              %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                    STYLE HACKING                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\renewcommand{\bottomfraction}{\topfraction}
\renewcommand{\topfraction}{1}
%\newcommand{\ns}{\kern-.175em}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                   MARGINAL NOTES                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\newif\iffirstmarginal \firstmarginaltrue

\newcommand{\marginalnote}[1]{\marginpar{\raggedright\small\it #1%
   \iffirstmarginal\typeout{****************************************}%
                   \typeout{******** MARGINAL NOTES IN TEXT ********}%
                   \typeout{****************************************}%
       \global\firstmarginalfalse\fi}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                THE describe ENVIRONMENT                %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \begin{describe}{FOO} Is like \begin{description} except
% that the indentation is adjusted as follows
%      LABEL              blah blah blah
%      <- width of foo -> blah blah blah
%                         blah blah blah
%
\newenvironment{describe}[1]%
   {\begin{list}{}{\settowidth{\labelwidth}{#1}%
            \setlength{\leftmargin}{\labelwidth}% 
            \addtolength{\leftmargin}{\labelsep}%
            \def\makelabel##1{\rm ##1\hfill}}}%
   {\end{list}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                THEOREM-LIKE ENVIRONMENTS               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\newtheorem{theorem}{Theorem}
\newtheorem{proposition}{Proposition}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                   STRUCTURED PROOFS                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\pfshortnumbers{99}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                  NOTATION FOR THIS DOCUMENT                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \o    ==  small circle operator (\circ)
% \?    ==  a long underscore
% \O{x} ==  the math formula x overlined
% \TLA+ ==  TLA+
% \M{F} ==  [[F]] (the meaning of formula F
% \dd   ==  ..  (m \dd n) == natural numbers from m to n
% \act{A} ==  Action A (A in \cal font)
% \minimal == minimal element of p.o. set
% \X, \Y, \AUX == tuples x, y, and a of variables
% \G{Op}  == Gerth notation for operation Op: {\sf Op}
% \subseq{sigma}{i}{j}  ==  <sigma[i], ... , sigma[j]>

%%%% kludge because the normal definition of \o is needed in
%%%% the bibliography
\let\realo=\o

\renewcommand{\o}{\circ}
\newcommand{\?}{\_\!\_\,}
\renewcommand{\O}[1]{\ensuremath{\overline{#1}}}
\newcommand{\TLA}[1]{TLA$^{+}\hspace*{-.1em}$}
\newcommand{\M}[1]{\ensuremath{[\![#1]\!]}}
\newcommand{\dd}{\ensuremath{\mathop{\ldotp\ldotp}}}
\newcommand{\act}[1]{\ensuremath{{\cal #1}}}
\newcommand{\minimal}{\ensuremath{\phi}}
\newcommand{\Y}{{\bf y}}
\newcommand{\Z}{{\bf z}}
\newcommand{\AUX}{{\bf a}}
\newcommand{\G}[1]{\mbox{\sf #1}}
\newcommand{\subseq}[3]{\ensuremath{#1_{#2}^{#3}}}

%% Commands for places where the tla style doesn't work.

\newcommand{\q}[1]{\mbox{\rm``{\sf #1}''}}

%% A colon for math formulas without so much space around it:
\newcommand{\midcolon}{\mskip -.5\thinmuskip:\mskip -.5\thinmuskip}


\begin{document}
%try
\maketitle
\thispagestyle{empty}
\begin{abstract}
We address the problem, proposed by Gerth, of verifying that a simplified
version of the lazy caching algorithm of Afek, Brown, and Merritt is
sequentially consistent.  We specify the algorithm and sequential
consistency in \TLA+, a formal specification language based on TLA
(the Temporal Logic of Actions).  We then describe a formal
correctness proof in TLA.
\end{abstract}

\newpage
\thispagestyle{empty}

\tableofcontents
\newpage
\setcounter{page}{1}
%try
\section{Introduction}

Assertional verification of concurrent algorithms began in 1975 with
Ash\-croft's seminal paper~\cite{ashcroft:proving}.  By the late
1980's, assertional methods had been developed for specifying
concurrent systems and proving that a lower-level specification
implements a higher-level one.  Our goal is to transform assertional
specification and verification from a scientific theory into an
engineering discipline.  

Engineering is the practical application of scientific principles.  An
engineering discipline comprises a well-defined collection of
intellectual tools that can be applied to a class of problems.  The
tools of our approach are the logic TLA (the Temporal Logic of
Actions)~\cite{lamport:newtla}, the specification language
\TLA+~\cite{lamport:hybrid}, and a hierarchical proof style for
writing rigorous proofs~\cite{lamport:howtoprove}.  The class of
problems we consider are the specification and verification of safety
and liveness properties of concurrent systems.

We demonstrate our approach on a problem suggested by
Gerth~\cite{gerth:intro-to-seq-consistency}: verifying that a
simplified version of the lazy caching algorithm of Afek, Brown, and
Merritt~\cite{afek:lazy-caching} is sequentially
consistent~\cite{lamport:howto}.  Although our exposition is
self-contained, it is about specification and verification, not about
lazy caching.  We formally specify the algorithm, but a formal
specification is no substitute for an intuitive explanation.  Readers
looking for such an explanation are referred
to~\cite{afek:lazy-caching}.

Published ``proofs'' of incorrect concurrent algorithms have taught us
the need for rigor.  We achieve rigor by using formal mathematics.
TLA is a formal logic, with precise proof rules; and \TLA+ has a
formal semantics.  Each step in a hierarchical proof is a mathematical
formula; English appears only in the proofs of the lowest-level steps.
Greater reliability is obtained by carrying out the proofs to lower
levels of detail.  Ultimately, one reaches a point where prose can be
eliminated and the proof checked by
computer~\cite{engberg:mechanical}.  However, reasonably reliable
proofs can be obtained without mechanical assistance.

We believe that proofs should be long and boring.  They should be long
because many details must be checked to ensure correctness.  They
should be boring because even the most interesting proof becomes
boring when carried out to the level of detail needed to avoid errors.
Conventional mathematical proofs try to be interesting and to avoid
boring details; as a result, a significant fraction of the theorems
published in mathematical journals are 
wrong~\cite{demillo:social,lamport:howtoprove}.  Discipline can be used
to eliminate careless mistakes when checking a long series of trivial
steps; discipline cannot help detect subtle errors in interesting
steps.

In assertional reasoning, insight is typically required to find an
invariant and construct a refinement mapping~\cite{abadi:existence}.
The proof itself is a tedious matter of checking the details.  For the
lazy caching algorithm, we give the invariant and refinement mapping,
and we describe the high-level structure of the proof.  The complete
proof is much too long and boring to include here.  Moreover, it is
too long to be read conveniently as a conventional paper document.  We
hope to provide a hypertext version of the proof on the World Wide
Web~\cite{ladkin:gerth-web-proof}.

To be useful, an engineering discipline should be applicable to a
reasonably broad class of problems.  There would be little point
developing a complete specification and proof method just for caching
algorithms.  TLA and \TLA+ have been applied to a number of diverse
domains, including hybrid systems~\cite{lamport:hybrid} and
distributed fault-tolerant algorithms~\cite{lamport:ftrtft94}.
Nothing new has been introduced for the lazy caching
example.\footnote{While not new, the TLA formulation of the rules for
introducing auxiliary variables appear in print here for the first
time.}

We are not interested in finding the simplest or most elegant possible
proof of the lazy caching algorithm.  Some formalisms might be better
suited for reasoning about caching algorithms.  Also, this kind of
short, subtle algorithm can sometimes be verified by a clever trick
that does not generalize to other applications.  We have no objection
to using cleverness to simplify a proof, we just do not want to depend
upon it.  We therefore obtain our proof by a straightforward
application of our method.  The most novel part of the proof is the
specification of sequential consistency, and it is a direct
application of an idea introduced in \cite{lamport:simple} for
specifying serializability.  As with any engineering discipline, it
takes practice to learn to write formal specifications and proofs with
TLA and \TLA+.  But, writing a specification and proof of a Byzantine
agreement algorithm teaches the skills needed to verify a caching
algorithm.  One does not need a new proof method for each problem
domain.

In Section~\ref{sec:TLA}, we introduce TLA and \TLA+ by writing a
formal specification of Gerth's version of the lazy caching algorithm.
Section~\ref{sec:sequential-consistency-sec} presents two specifications
of sequential consistency---the one we use, and an equivalent one in
the spirit of the original definition~\cite{lamport:howto}, as
adapted by Gerth~\cite{gerth:intro-to-seq-consistency}.  In
Section~\ref{sec:proof}, we describe the proof that the specification
of the lazy caching algorithm implements the specification of
sequential consistency.

%try

\section{Lazy Caching in \protect\TLA+} \label{sec:TLA}

\subsection{TLA and \protect\TLA+}

TLA is a temporal logic.  Temporal logic formulas contain {\em
flexible variables}, which represent quantities that change with time,
and {\em rigid variables}, which represent quantities that do not
change with time.  Flexible variables are usually just called {\em
variables\/}; rigid variables are sometimes called {\em constants}.
The meaning \M{S} of a TLA formula $S$ is a boolean function on
behaviors, where a behavior is an infinite sequence of states and a
state is an assignment of values to all flexible
variables.\footnote{One source of TLA's simplicity is that there is a
single state space, instead of a different set of states for each
specification.} A behavior $\sigma$ {\em satisfies\/} a formula $S$
iff $\M{S}(\sigma)$ equals \TRUE. A formula is {\em valid\/} iff it is
satisfied by all behaviors.  A specification $S$ is said to {\em
implement\/} a specification $T$ iff every behavior satisfying $S$
satisfies $T$, which is true iff the formula $S => T$ is valid.  When
we write ``$S$ implies $T$'', we usually mean that $S => T$ is valid.
The syntax and semantics of TLA are described
in~\cite{lamport:newtla}.

\TLA+ is a formal language based on TLA and Zermelo-Fraenkel set
theory.  We will explain its features as they are used.  Most of the
operators and constructs of \TLA+, including all the ones we use, are
summarized in Figures \ref{fig:TLA+operators} and \ref{fig:keywords}.
%
\begin{figure}
\centering
\begin{tabbing}
\hspace*{1em}\=\+\kill
\bf \hspace*{-1em}Logic\\
\TRUE \ \ \FALSE \ \ $\land$ \ \ $\lor$ 
  \ \ $\lnot$ 
  \ \ $=>$ \ \ $\equiv$ \\
$\forall\, x : p(x)$  \ \ \ \ $\exists\, x : p(x)$  \ \ \ \ 
$\forall\, x \in S : p(x)$  \ \ \ \ $\exists\, x \in S : p(x)$\\ 
% \ \ \ \ 
 \CHOOSE $x : p(x)$
%  \hspace{.5em} \small [Equals some $x$ satisfying $p$, if such an $x$ exists] 
   \hspace{.5em} \small 
     \begin{tabular}[t]{l@{}l}
       [ & Equals some $x$ satisfying $p$, or an arbitrary \\
         & value if no such $x$ exists] 
     \end{tabular}    
\\%[.375\baselineskip]
%
{\bf \hspace*{-1em}Sets}\\
$=$ \ \ $\neq$ \ \ $\in$ \ \ $\notin$ 
  \ \ $\cup$ \ \ $\cap$ \ \ $\subseteq$ \ \ 
  $:\:$ {\small [set difference]}\\
$\{e(x) : x \in S \}$  \hspace{.5em}\= \kill
%
$\{e_1, \ldots , e_n\}$     
  \> \small [Set consisting of elements $e_i$] \\
$\{x \in S : p(x)\}$       
  \> \small [Set of elements $x$ in $S$ satisfying $p(x)$] \\
$\{e(x) : x \in S \}$       
  \> \small [Set of elements $e(x)$ such that $x$ in $S$] \\
% \SUBSET $S$
%  \> \small [Set of subsets of $S$] \\
$\UNION S$
  \> \small [Union of all elements of $S$]\\[.375\baselineskip]
%
{\bf \hspace*{-1em}Functions}\\
{[}$f \EXCEPT ![e_{1}]\,=\,e_{2}$]
  \hspace{.5em}\= \kill
$f$[$e$] \>
  {\small [Function application]}\\
\DOMAIN $f$ \> \small [Domain of function $f$] \\
{[}$x \in S$~$\mapsto$\ $\!e(x)$]
  \> \small [Function $f$ such that $f[x]=e(x)$ for $x\in S$]\\
{[}$S$ $\rightarrow$ $T$]
  \> \small [Set of functions $f$ with $f[x]\in T$ for 
             $x\in S$]            \\
{[}$f \EXCEPT ![e_{1}]\,=\,e_{2}$]
  \> \small [Function $\widehat{f}$ equal to $f$ except 
             $\widehat{f}[e_{1}]=e_{2}$]\\
%{[}
$\{\![f \EXCEPT ![e] :in: S]\!\}$
  \> \small [Set of functions $\widehat{f}$ equal to $f$ except 
             $\widehat{f}[e]\in S$]\\[.375\baselineskip]
%
%{\bf \hspace*{-1em}Records}\\
%$[ x_1 \mapsto e_1, \ldots , x_n \mapsto e_n ]$
%  \hspace{.5em}\= \kill
% %
%$e.h$     
%\> \small [The $h$-component of record $h$] \\
% %
%$[ h_1 \mapsto e_1, \ldots , h_n \mapsto e_n ]$
%  \> \small [The record whose $h_i$ component is $e_i$]\\
% %
%$[ h_1 : S_1, \ldots , h_n : S_n ]$ 
% \> \small [Set of all records with $h_i$ component in $S_i$]\\
%$[ r \EXCEPT  !.h=e]$
%  \> \small [Record $\widehat{r}$ equal to $r$ except 
%             $\widehat{r}.h=e$]\\
%$\{\![ r \EXCEPT !.h  :in: S]\!\}$
%  \> \small [Set of records $\widehat{r}$ equal to $r$ except 
%             $\widehat{r}.h\in S$]\\[.375\baselineskip]
%
{\bf \hspace*{-1em}Tuples}\\
 $S_1 \X \ldots \X S_n$ 
 \hspace{.5em}\= \kill
%
$e[i]$  \>   \small [The $i^{\rm th}$ component of tuple $e$]\\
$<<e_1, \ldots , e_n>>$
  \> \small [The $n$-tuple whose $i^{\rm th}$ component is 
            $e_i$]\\
$S_1 \X \ldots \X S_n$
   \> \small [The set of all $n$-tuples with $i^{\rm th}$ component in $S_i$]
%
\\[.375\baselineskip]
{\bf \hspace*{-1em}Miscellaneous} \\
{\bf let} $x_{1}\deq e_{1}$ \ldots\ $x_{n}\deq e_{n}$ {\bf in} $e$
  \hspace{.5em}\= \kill
 %
$"c_1 \ldots\  c_n"$
   \> \small [A literal string of $n$ characters]   \\
 %
% {\sc String} 
%   \> \small [The set of all strings] \\
$d_{1}\ldots d_{n}$ 
   \> \small [Numbers]
\\
{\bf if} $p$ {\bf then} $e_1$ {\bf else} $e_2$
  \> \small [Equals $e_1$ if $p$ true, else $e_2$]\\
 %
{\bf let} $x_{1}\deq e_{1}$ \ldots\ $x_{n}\deq e_{n}$ {\bf in} $e$
  \> \small [Equals $e$ in the context of the definitions] 
%\\[.5\baselineskip]
\\[.375\baselineskip]
{\bf \hspace*{-1em}Nonconstant Operators} \\
$[A]_e$ \hspace{.5em}\= \small [$p$ with variables primed] 
  \hspace{3.5em}\= WF$_{e}(A)$ \hspace{.5em}\=  \kill
$p'$       \>   \small [$p$ with variables primed] 
 \> $[]F$    \> \small [$F$ is always true]\\
%  
$[A]_e$    \>    \small [$A \/ (e'=e)$] 
%
 \> $<>F$    \> \small  [Eventually: $~[]~F$] \\
%
%$\UNCHANGED e$ \hspace{.5em}\= \small [$p$ with variables primed] 
%  \hspace{1.5em}\= WF$_{e}(A)$ \hspace{.5em}\=  \kill
$<<A>>_e$ \> \small [$A /\ (e'#e)$]  
 \> WF$_{e}(A)$ \> \small [Weak fairness] \\
$\UNCHANGED e$ \hspace{.5em}\small [$e'=e$] 
 \>\> SF$_{e}(A)$ \> \small [Strong fairness] 
\\[.125\baselineskip]
$\ENABLED A$ \hspace{.5em}\small [$\exists$ values of primed variables
for which action $A$ is true]
%%  \>\> SF$_{e}(A)$ \> \small [Strong fairness]
\\[.125\baselineskip]
%
$:EE: x : F$ \ \ \ $:AA: x : F$ \hspace{.5em}\small [Temporal quantification.]
\end{tabbing}
%\rule{\textwidth}{1pt}
\vspace{-.5\baselineskip}
\caption[]{\TLA+ operators.}
\label{fig:TLA+operators}
\end{figure}%
%
\begin{figure}[t]
\begin{description}
\item[assumption\s{.25}]
  %\mbox{}\\
Asserts named assumptions about constant parameters.


\vspace{-.25\baselineskip}
  

\item[\BOOLEAN\s{.25}]
  %\mbox{}\\
  Specifies that a parameter is a boolean-valued constant.

\vspace{-.25\baselineskip}
  
\item[\CONSTANT\s{.25}]
  %\mbox{}\\
  Specifies that a parameter is a nonboolean constant.

\vspace{-.25\baselineskip}

\item[import $M$\s{.25}]   %\mbox{}\\
  Adds parameters, assumptions, definitions, and theorems from 
  module $M$.

\vspace{-.25\baselineskip}

\item[include $M$ as $N$\s{.25}]   %\mbox{}\\
  Adds definitions from module $M$ with parameters instantiated and
``$N.$'' appended to defined names.
If $N$ has the form 
 $P(x_{1}, \ldots, x_{n})$,
then the $x_{i}$ become additional formal parameters of each
included definition.

\vspace{-.25\baselineskip}

\item[module\s{.25}]    %\mbox{}\\
  Begins a module.

\vspace{-.25\baselineskip}

\item[parameters\s{.25}]   %\mbox{}\\
  Declares the free parameters of a module.

\vspace{-.25\baselineskip}

\item[theorem\s{.25}] %\mbox{}\\
  Asserts that named theorems are deducible from 
  the module's assumptions.

\vspace{-.25\baselineskip}

\item[\VARIABLE\s{.25}]
  %\mbox{}\\
  Specifies that a parameter is a flexible variable.

\vspace{-.25\baselineskip}

\item[$\deq$\s{.25}]
  %\mbox{}\\
  Defines an operator.

\item[{$f[x : S] \;\deq\; \ldots $}\s{.25}]
  %\mbox{}\\
  Defines $f$ to be a function with domain $S$.

\vspace{-.25\baselineskip}


\makeatletter
\item[%
{\makeatletter\@computerule\makebox[4.5em][l]{\s{.5}\midbar\s{1}}}]
  %\mbox{}\\
  A mostly meaningless decoration that ends the scope of an
  {\bf assumption} or {\bf theorem} section.

\vspace{-.25\baselineskip}

\item[{\makeatletter
    \@computerule\raisebox{-.5ex}{\makebox[4.5em]{\s{.5}\bottombar\s{1}}}}]%
  %\mbox{}\\
  Marks the end of a module.
\end{description}

\vspace{-.5\baselineskip}

\caption[]{Syntactic keywords and symbols of \TLA+.}
\label{fig:keywords}
\end{figure}%
%
We try to explain our specifications in enough detail that
readers unfamiliar with TLA and \TLA+ will be able to understand them.

We do not attempt to explain the choices made in \TLA+.  The rationale
for much of its notation is not apparent from this one example.  Also, why
we {\em don't\/} write certain things may be puzzling.  There are a
number of restrictions in \TLA+ that are needed to maintain its
simplicity.  Surprising complications can arise from features that
appear innocuous---for example, boolean-valued functions (also called
arrays of booleans)~\cite[pages 78--79]{lamport:hybrid}.  These
complications are often not apparent in semi-formal expositions such
as \cite{chandy:parallel} and~\cite{manna:temporal}.


%try
\subsection{The Lazy Caching Algorithm}

We introduce TLA and \TLA+ by first specifying Gerth's version of the
lazy caching algorithm.  Gerth described the algorithm informally with
the state machine of Figure~\ref{fig:Gerth-spec}.\footnote{Gerth
specified that only $\G{R}_{i}(d,a)$ and $\G{W}_{i}(d,a)$ events are
externally observable.  However, by observing only these events, there
is no way to tell that a memory system is using lazy caching and not
some other cache coherence algorithm.  We therefore also make
externally visible the events that change the queues and caches.}
%
%%%%% BEGIN: Taken from Gerth
\begin{figure}[t]

\notla
\begin{small}
\centering
\let\mc=\multicolumn
\def\RM{\ffont\rm}
\def\BF{\ffont\bf}
\def\IT{\ffont\it}
\def\SF{\ffont\sf}
\def\TT{\ffont\tt}
\def\CAL{\ffont\cal} 
\def\ffont#1#2{\defemb{#2}{{#1 #2}}}
\def\defemb#1#2{\expandafter\def\csname #1\endcsname
                              {\relax\ifmmode #2\else\hbox{$#2$}\fi}}
\IT{append}  \IT{tail} \IT{head} \BF t
\IT{In} \IT{Out} \IT{Comp} \SF{CI} \IT{update}
\SF{R} \IT{Mem} \SF{W} \SF{MW} \SF{MR} \SF{CU}
\def\STRUT#1{\vrule width 0pt height #1pt}

\begin{tabular}{l|l|l}
\mc1c{Event} & \mc1c{Allowed if} & \mc1c{Action} \\ \hline\hline
	\STRUT{15}
$\R_i(d,a)$ & $C_i(a)=d\land\Out_i=\{\}$ \\
& $\land$	no $*$-ed entries in $\In_i$ \\[5pt]
$\W_i(d,a)$ & & $\Out_i:=\append(\Out_i,(d,a))$ \\[5pt]
$\MW_i(d,a)$ & $\head(\Out_i)=(d,a)$ & $\Mem[a]:=d;$ \\
& & $\Out_i:=\tail(\Out_i);$ \\
& & $(\forall k\ne i~::~\In_k:=\append(\In_k,(d,a)));$ \\
& & $\In_i:= \append(\In_i,(d,a,*))$ \\[5pt]
$\MR_i(d,a)$ & $\Mem[a]=d$ & $\In_i:=\append(\In_i,(d,a))$ \\[5pt]
$\CU_i(d,a)$ & $\head(\In_i)$ is either\hskip1cm \\
& \hfill $(d,a)$ or $(d,a,*)$ & $\In_i:=\tail(\In_i);~
		C_i:=\update(C_i,d,a)$ \\[5pt]
$\CI_i$ & & $C_i:={\it restrict}(C_i)$ \\
\mc1l{\STRUT{15} Initially:} &
	\mc2l{$\forall a~~\Mem[a]=0$} \\
\mc1l{} & \mc2l{${}\land\forall i=1\ldots n~~C_i\subset\Mem \land \In_i=\{\}
	\land \Out_i=\{\}$} \\
\mc1l{Fairness:} & \mc2l{no action other than $\CI_i$ can be always enabled
	but never taken}
% \\
%\mc2l{\STRUT{17} $\MW$---memory write} &
%		\mc1l{$\MR$---memory read} \\
%\mc2l{$\CU$---cache update} & \mc1l{$\CI$---cache invalidate}
\end{tabular}\\
\begin{tabular}{l@{\hspace{30pt}}l@{\hspace{30pt}}l}
  \STRUT{17}$\W$---write & $\MW$---memory write & $\CU$---cache update\\
  $\R$---read  & $\MR$---memory read & $\CI$---cache invalidate
\end{tabular}
\par
\end{small}
\caption[]{Gerth's version of the lazy caching algorithm, from
Figure~4 of~\protect\cite{gerth:intro-to-seq-consistency}.}
\label{fig:Gerth-spec}
\end{figure}
Our specification is a fairly direct translation of this state machine
into \TLA+\@.  Had the state machine been specified formally, the
translation could have been performed by a straightforward algorithm.
However, Gerth's state machine would not have had so simple and
compact a description if it were written in a general-purpose formal
language for specifying state machines.

We represent an algorithm by a TLA formula.  As in ordinary
mathematics, hierarchical structure is obtained by defining complex
formulas in terms of simpler ones.  Our specification is a sequence of
definitions, culminating in the one that describes the lazy caching
algorithm.

\subsubsection{Some Preliminaries: Module {\it MemParams}}

\TLA+ specifications are structured using modules.  Parts of the lazy
caching specification are placed in the separate module $MemParams$ of
Figure~\ref{fig:MemParams} so they can be easily reused in later
specifications.

%
\begin{figure}[tb]
\vspace*{-1.25\baselineskip}
\begin{module}{MemParams}
\IMPORT Naturals, Sequences \\
\begin{nodecls}
{\bf parameters} \ \ \=
    ch : \VARIABLE \\
    \> Data, InitData, Addr, N : \CONSTANT 
\end{nodecls}
\midbar
  \begin{nodecls}
   {\bf assumption} \ \ 
    ValAssump == (InitData :subseteq: Data) /\ (N :in: Nat) /\ (N > 0)
  \end{nodecls}
\midbar
  \begin{nodecls}
    Proc == 1\dd N 
  \end{nodecls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{Parameters of the cache specifications.}
\label{fig:MemParams}
\end{figure}
%
The module first imports modules $Naturals$ and $Sequences$, meaning
that it adds the definitions from those modules to the $MemParams$
module.  (An equivalent specification can be obtained by replacing the
{\bf import} statement with the definitions from those two modules.)
The standard module $Naturals$ defines the set $Nat$ of natural
numbers, operators on natural numbers such as $+$ and $>$, and the
usual representation of natural numbers as Arabic numerals.  The
$Sequences$ module defines some operations on sequences; it also
defines the infix operator ``$\dd$'' so that, if $i$ and $j$ are
natural numbers, then $i\dd j$ is the set of natural numbers $n$ with
$i\leq n \leq j$.  This module and the operators it defines are
described in Section~\ref{sec:params-and-ops} below.

Module $MemParams$ next declares some parameters.  Parameters are the
free symbols of a specification.  By replacing all defined symbols
with their definitions, a \TLA+ specification can be reduced to a
formula containing only parameters and the operators of
Figure~\ref{fig:TLA+operators}.  The parameter $ch$ is a (flexible)
variable representing the communication channels between the
processors and the memory system.  We need such a variable because TLA
is based on states rather than events.  Gerth's $\G{W}_{i}(d,a)$ and
$\G{R}_{i}(d,a)$ events are represented in our specification by
changes to $ch[i]$, the channel joining process $i$ to the memory.
The other parameters, all constants, are: the set $Data$ of values
that can be stored in a memory location, the subset $InitData$ of
possible initial values, the set $Addr$ of memory addresses, and the
number $N$ of processes.

The description of the parameters in the preceding paragraph is an
informal comment.  The {\bf parameters} declaration tells us only that
$N$ is a constant, not that it is a number.  The {\bf assumption}
section asserts, and assigns the name $ValAssump$ to, the assumption
that $InitData$ is a subset of $Data$ and $N$ is a positive natural
number.  (It is unnecessary to assume that $Data$ and $InitData$ are
sets because \TLA+ is based on Zermelo-Fraenkel set theory, in which
every constant is a set.)

Module $MemParams$ ends by defining the constant $Proc$, the set
of processor names, to be the set $\{1, \ldots, N\}$ of natural
numbers.

\subsubsection{Parameters and Mathematical Operators} \label{sec:params-and-ops}

The specification of the lazy caching algorithm is contained in the
$LazyCache$ module of Figures \ref{fig:LazyCache1} and
\ref{fig:LazyCache2}.
\begin{figure}
\vspace*{-1.25\baselineskip}
\begin{nomodule}
\topbar{LazyCache}
\IMPORT MemParams, ChannelInterface, Sequences, Naturals \\
\midbar
 \begin{nodecls}
 {\bf parameters} \ \
   c, in, out, mem : \VARIABLE 
 \end{nodecls}

\midbar
    \begin{nodecls}
      :bot: == \CHOOSE i: i :notin: Data \\
      Restrict(f) == 
        \{ g :in: [Addr -> Data :cup: \{ :bot: \}] :
                        :A: a :in: Addr: g[a] :in: \{ f[a] , :bot: \} \} \V{.75}
%
      Init == \begin{conj}
                  mem :in: [Addr -> InitData] \\
                  c :in: [Proc -> Restrict(mem)] \\
                  in  = [i :in: Proc |-> <<>>]    \\
                  out = [i :in: Proc |-> <<>>]                  
                \end{conj} \\
%
      Read(i,d,a) ==  \begin{conj}
                       out[i] = <<>> \\
                       :A: j :in: 1 :dd: Len(in[i]): Len(in[i][j]) = 2 \\
                       c[i][a] = d \\
                       ChanOp(ch[i], <<i,"Rd",d,a>>) \\
                       :A: j :in: Proc :\: \{ i \} : \UNCHANGED ch[j]\\
                       \UNCHANGED << c, in, out, mem >> \vs{.2}
                     \end{conj}\\
%
      Write(i,d,a) == \begin{conj}
                        ChanOp(ch[i], <<i,"Wr",d,a>>) \\
                       out' = [out \EXCEPT ![i] =  
                                     out[i] \o << <<d,a>> >>] \\
                       :A: j :in: Proc :\: \{ i \} : \UNCHANGED ch[j]\\
                       \UNCHANGED <<c, in, mem>> \vs{.2} 
                     \end{conj} \\
      MemWrite(i) == \\
         ___\begin{conj}
              	   out[i] # <<>> \\
           out' = [out \EXCEPT ![i] = Tail(out[i])] \\
           in' = [j :in: Proc \;|-> \;
                    in[j] \,\circ\, \IF{j=i} 
                       \THEN <<Head(out[i]) \o <<"$*$">> >>\\
                       \ELSE <<Head(out[i])>> _____] \FI\\
              mem' = [mem \EXCEPT ![Head(out[i])[2]] = Head(out[i])[1]\,] \\
                       \UNCHANGED << c, ch >>  \vs{.2}
             \end{conj} 
\\
     CacheUpdate(i) ==    \begin{conj}
             in[i] # << >> \\
             in' = [in \EXCEPT ![i] = Tail(in[i])] \\
             c'  = [c \EXCEPT ![i][Head(in[i])[2]] = Head(in[i])[1]\,] \\
             \UNCHANGED << out, ch, mem >>
          \end{conj} 
\end{nodecls}
\end{nomodule}
\addvspace{-.5\baselineskip}
\caption[]{The lazy caching algorithm (beginning).}
\label{fig:LazyCache1}
\end{figure}%
%
%try
\begin{figure}[t]
\vspace*{-1.25\baselineskip}
\begin{nomodule}
\begin{nodecls}
      MemRead(i) == 
         \begin{conj}
             \begin{noj}
               :E: a :in: Addr :  \\
               __in' = [in \EXCEPT  ![i] = in[i] \o << << mem[a], a >> >>] 
             \end{noj}  \\
               \UNCHANGED <<out,c,mem, ch>> \vs{.2}
             \end{conj}\\
      CacheInval(i) == \begin{conj}
                         c' :in:  
                         \{\![c \EXCEPT ![i] :in: Restrict(c[i])]\!\} \\
                         \UNCHANGED << in, out, mem, ch >>\vs{.2}
                       \end{conj}\\
      Next(i) ==       \begin{disj}
                           :E: d :in: Data, a :in: Addr : 
                              Read(i,d,a) \/ Write(i,d,a) \\
                         \begin{noj}
                          MemWrite(i) 
                          \/ CacheUpdate(i)
                          \/ MemRead(i) \\ \s{1}\mbox{} 
                            \/ CacheInval(i) \vs{.2}
                         \end{noj}
                         \end{disj}\\
%
      vars == << c, in, out, mem, ch >> \V{.2}
%
   Spec   == \begin{conj}
               Init \\ [] [:E: i :in: Proc : Next(i)]_{vars} \\
               :A: i \in Proc : \begin{noj}
                       \WF_{vars}(CacheUpdate(i)) 
                        /\ \WF_{vars}(MemWrite(i)) 
                      \end{noj}
             \end{conj}
\end{nodecls}
\bottombar
\end{nomodule}
\addvspace{-\baselineskip}
\caption[]{The lazy caching algorithm (continued).}
\label{fig:LazyCache2}
\end{figure}%
%try
The module first imports four other modules.  Importing module
$MemParams$ imports its definitions, assumptions, and parameter
declarations.  The other modules contain only operator definitions.
We have already discussed the $Naturals$ and $Sequences$ modules.
Module $ChannelInterface$ defines the operator $ChanOp$ described
below; the module is given in Section~\ref{sec:ChannelInterface}.

Module $LazyCache$ next declares four variable parameters, which
correspond to the variables of Gerth's specification.  \TLA+ does not
use subscripted variables, and we prefer to use lower-case names for
variables and upper-case names for constants, so we write $c[i]$
instead of $C_{i}$, $in[i]$ instead of $In_{i}$, etc.  Processor $i$
maintains the queues $in[i]$ and $out[i]$ and the cache $c[i]$;
variable $mem$ represents the main memory.
Figure~\ref{fig:lazy-cache-state-machine} is a picture of the state
machine; it describes the flow of data in the algorithm and the
meanings of the variables.
%try
\begin{figure}[tb]
\centering
\begin{picture}(0,232.5)(0,5)
%\makegrid(-200,0)(400,300)
\put(-75,5){\framebox(150,25){\small$mem$}}
%
\thicklines
\put(20,60){\vector(0,-1){30}}
\put(-122.5,50){\line(1,0){94.5}}
\put(-28,30){\line(0,1){20}}
\put(-122.5,50){\vector(0,1){26.85}}
\put(-12,30){\line(0,1){20}}
\put(-12,50){\line(1,0){93.5}}
\put(81.5,50){\vector(0,1){26.85}}
\put(-20,40){\makebox(0,0){$\ldots$}}
%
\put(0,60){\setlength{\unitlength}{.85pt}%
\begin{picture}(0,200)
%\makegrid(-200,0)(400,250)
\thicklines
{\linethickness{2pt}%
\put(-155.5,-1){\line(1,0){306}}}
\put(-155,0){\vector(0,1){20}}
\put(-150,80){\vector(0,1){20}}
\put(-150,150){\vector(0,1){20}}
\put(-150,170){\line(1,0){60}}
\put(-90,20){\vector(0,-1){20}}
\put(-90,170){\vector(0,-1){90}}
\put(-120,170){\line(0,1){20}}
%
\put(85,0){\vector(0,1){20}}
\put(90,80){\vector(0,1){20}}
\put(90,150){\vector(0,1){20}}
\put(90,170){\line(1,0){60}}
\put(150,20){\vector(0,-1){20}}
\put(150,170){\vector(0,-1){90}}
\put(120,170){\line(0,1){20}}
\thinlines
\small
\put(-168,20){\framebox(36,60){\small$in[1]$}}
\put(-108,20){\framebox(36,60){\small$out[1]$}}
\put(-175,100){\framebox(50,50){$c[1]$}}
\put(-118,180){\makebox(0,0)[l]{$ch[1]$}}
%
\put(-120,200){\makebox(0,0)[b]{\normalsize Processor\ $1$}}
\put(120,200){\makebox(0,0)[b]{\normalsize Processor\ $N$}}
%
\put(72,20){\framebox(36,60){\small$in[N]$}}
\put(132,20){\framebox(36,60){\small$out[N]$}}
\put(65,100){\framebox(50,50){$c[N]$}}
\put(122,180){\makebox(0,0)[l]{$ch[N]$}}
%
\put(-10,85){\circle*{3}}
\put(0,85){\circle*{3}}
\put(10,85){\circle*{3}}
%\put(-15,85){\circle*{3}}
%\put(-5,85){\circle*{3}}
%\put(5,85){\circle*{3}}
\end{picture}}%
\end{picture}
\caption[]{The state machine describing the lazy caching algorithm,
where $c[i]$ is a cache, $out[i]$ is a queue of $\langle
data, address\rangle$ pairs for writes by processor $i$ that have not
yet been performed to memory, and $in[i]$ is a queue of $\langle data,
address\rangle$ pairs and $\langle data, address, \q{$*$}\rangle$
triples of pending writes to $c[i]$, a \q{$*$} indicating
that the write was issued by processor $i$.}
\label{fig:lazy-cache-state-machine}
\end{figure}
%try

When using a formal language, we must specify mathematical operations
that are usually taken for granted.  \TLA+ provides the predefined
operators for sets, functions, and tuples shown in
Figure~\ref{fig:TLA+operators}.  Its set notation is standard.
As in ordinary mathematics, a function has a domain, which is a set.
The set of all functions with domain $S$ and range a subset of $T$ is
written $[S -> T]$.  Function application is denoted by square
brackets.  The \TLA+ construct $[x \in S |-> e(x)]$ is a ``lambda
expression'' that represents the function $f$ with domain $S$ such
that $f[x]=e(x)$ for all $x$ in $S$.  For example, the squaring function
on natural numbers is $[n \in Nat |-> n*n]$.  Tuples are enclosed by
angle brackets.  An $n$-tuple is a function whose domain is the set
$\{1,\ldots,n\}$ of natural numbers, so
  $<<v_{1}, \ldots, v_{n}>>[i]$ (the function $<<v_{1}, \ldots, v_{n}>>$
applied to $i$) equals $v_{i}$, for $1 :leq: i :leq: n$.  


Mathematical operators not provided by \TLA+ must be defined.  Our
specifications use operators on finite sequences, including $Head$, $Tail$,
$:o:$ (concatenation), and $Len$ (length) that are defined in the
$Sequences$ module of Figure~\ref{fig:Sequences}.
%
\begin{figure}
\vspace*{-1.25\baselineskip}
\small
\begin{module}{Sequences}
\IMPORT Naturals
\midbar
\begin{nodecls}
Head(s) \= \kill
 %
m :dd: n \>== \{ i :in: Nat : (m :leq: i) /\ (i :leq: n)\}\\
 %
Len(s) \>== \CHOOSE n : (n :in: Nat) /\ ((\DOMAIN s) = (1 :dd: n))\\
 %
Head(s) \>== s[1]\\
 %
Tail(s) \>== [i :in: 1 :dd: (Len(s)-1) |-> s[i+1]]\\
 %
s :o: t \>== [i :in: 1 :dd: (Len(s)+Len(t)) |->
                 \IF{i :leq: Len(s)} \THEN s[i] \\
                                      \ELSE t[i - Len(s)] ] \FI\\
 %
Seq(S)  \>==  \UNION \{[(1 :dd: n) -> S] : n :in: Nat\} \\
 %
SelectSeq(s, test(:?:)) == 
    \LET F[\,t : Seq(\{ s[i] : i :in: 1 :dd: Len(s)\})\,] ==  \\
             ___\IF{t=<<>>} 
                  \THEN <<>>\\
                  \ELSE \IF{test(Head(t))} \\
                           \THEN <<Head(t)>> :o: F[Tail(t)] \\
                           \ELSE F[Tail(t)] \FI \FI \\
       \IN F[s] \NI \\
 %
SubSeq(s, m, n) == [i :in: 1 :dd: (1+n-m) |-> s[i+m-1]]
\end{nodecls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{Module $Sequences$}
\label{fig:Sequences}
\end{figure}
%
Finite sequences are represented as tuples, so $<<v, w>>$ equals $<<v>> :o:
<<w>>$, and $<< >>$ is the empty sequence.  Other
operators defined by the $Sequences$ module are explained later.  The
reader interested in how ordinary mathematics is formalized in \TLA+
can work out the details of the definitions in
module $Sequences$ with the aid of
Figures \ref{fig:TLA+operators} and~\ref{fig:keywords}.

A memory assigns data values to addresses, so its contents 
are represented by a function in $[Addr -> Data]$.  A cache assigns
data values to some addresses.  We could represent the
contents of a cache by a function whose domain is a subset of
$Addr$.  However, we find it more convenient to choose some value
$\bot$ not in $Data$ and represent a cache's contents by a function
$f$ in
 $[Addr -> Data \cup \{\bot\}]$,
where $f[a]=\bot$ means that the cache does not contain a data value
for address $a$.  The first definition in module $LazyCache$ is of the
constant $\bot$.

``Restricting'' the contents of a cache means removing data values
from it.  The operator $Restrict$ is defined so that $Restrict(f)$ is
the set of restrictions of $f$, for any cache contents $f$.  Formally,
$Restrict(f)$ is the set of all functions $g$ in 
 $[Addr -> Data \cup \{\bot\}]$ 
such that $g[a]$ equals $f[a]$ or $\bot$, for all $a$ in $Addr$.

%try
\subsubsection{The Initial Condition and Actions}

Module $LazyCache$ next defines seven formulas that are formal
statements of the initial condition and the six event descriptions of
Figure~\ref{fig:Gerth-spec}.


\paragraph{\it Init}

The predicate $Init$ describes the initial values of the variables
$c$, $in$, $out$, and $mem$.  (As we will see from module
$ChannelInterface$, the initial value of $ch$ doesn't matter.)  The
predicate has four conjuncts.\footnote{\TLA+ uses the notation that a
list of expressions bulleted by $\land$ denotes their conjunction, and
a list of expressions bulleted by $\lor$ denotes their disjunction.
Indentation is used to eliminate
parentheses~\cite{lamport:howtowrite}.  (We also continue to use $\land$ and
$\lor$ as infix operators.)} The first asserts that
$mem$ is the contents of a memory that assigns to each address an
element of $InitData$.  The second conjunct asserts that $c$ is a
function with domain $Proc$, the set of processor names, and that
$c[i]$ (the contents of processor $i$'s cache) is a restriction of
$mem$, for each processor $i$.  The last two conjuncts assert that
$in$ and $out$ are functions with domain $Proc$ such that $in[i]$ and
$out[i]$ are the empty sequence, for each processor $i$.  

\paragraph{\it Read} 

The operator $Read$ is defined so that the 
action $Read(i,d,a)$ corresponds to the description of the event
$\G{R}_{i}(d,a)$ in Gerth's state machine.
 An {\em action\/} is a boolean-valued expression that
may contain primed and unprimed variables.  It specifies a {\em
step\/}, which is a pair of states.  Unprimed variables refer to the
variables' values in the first state of the step; primed variables
refer to their values in the second state.  A step satisfying
$Read(i,d,a)$ represents an $\G{R}_{i}(d,a)$ event in Gerth's
specification.

Action $Read(i,d,a)$ is the conjunction of six formulas.  The first
asserts that the queue $out[i]$ is empty.  The second asserts that
there is no $"$*$"$ entry in the queue $in[i]$.  More precisely, it
asserts that for each positive natural $j$ less than or equal to the
length of $in[i]$, the $j$th element $in[i][j]$ of $in[i]$ is of
length~2.  The third conjunct asserts that cache $c[i]$ assigns $d$ to
address $a$.  These three conjuncts contain no primed variables, so
they are conditions on the first state of the step.  They correspond
to the ``allowed if'' condition for $\G{R}_{i}(d,a)$ in
Figure~\ref{fig:Gerth-spec}.

The fourth conjunct of $Read(i,d,a)$ uses the operator $ChanOp$
imported from module $ChannelInterface$.  For any variable $x$ and
value $v$, formula $ChanOp(x,v)$ asserts that the values of $x$ and
$x'$ describe a step that represents the sending of $v$ over channel
$x$.\footnote{There is no notion of a sender or a receiver, so it
might be better to say that the step represents a $v$ event on channel
$x$.} Thus, this conjunct asserts that the tuple $<<i,"Rd",d,a>>$,
indicating a read of value $d$ from address $a$ by processor $i$, is
sent over $ch[i]$.  The precise definition of $ChanOp$, which is given
later, does not matter.  However, we should check that it defines a
$ChanOp(x,v)$ step to be a reasonable representation of the event of
sending $v$ on channel $x$.  For example, this would not be the case
if a step could satisfy both $ChanOp(x,v)$ and $ChanOp(x,w)$, for $w\neq
v$.

The fifth and sixth conjuncts assert what doesn't change.  The formula
$\UNCHANGED e$ means $e'=e$, so the fifth conjunct asserts that the step
does not change any other channel---hence nothing is sent on the other
channels.  The sixth conjunct asserts that the tuple 
 $<<c, in, out, mem >>$ 
does not change---hence $c$, $in$, $out$, and $mem$ are left
unchanged.  (In Figure~\ref{fig:Gerth-spec}, an event whose action
does not mention a variable leaves the variable unchanged.  In a TLA
specification, an action that does not specify the new value of a
variable allows the variable to assume any value.)



\paragraph{\it Write} 

Action $Write(i,d,a)$ corresponds to the description of the state
machine event $\G{W}_{i}(d,a)$.  The \TLA+ construct $[f \EXCEPT ![x]
= e]$ denotes a function $g$ that is the same as $f$ except with
$g[x]$ equal to $e$.  Thus, the second conjunct asserts that the
element $<<d, a>>$ is appended to $out[i]$, and $out[j]$ is unchanged
for $j$ in the set $Proc :\: \{i\}$ of other processors.

\paragraph{\it MemWrite} 

Action $MemWrite(i)$ corresponds to the state machine event
$\G{MW}_{i}(d,a)$ when $<<d,a>>$ is the head of $out[i]$, which is the
only case in which that event is allowed.  Letting $d$ be
$Head(out[i])[1]$ and $a$ be $Head(out[i][2])$ (so $<<d,a>>$ is the
head of $out[i]$), the action asserts that $out[i]$ is nonempty, its
head is removed, the triple $<<d,a,"$*$">>$ is appended to $in[i]$,
the pair $<<d,a>>$ is appended to all the other queues $in[j]$, and
$mem[a]$ is set to $d$.

\paragraph{\it CacheUpdate}

Action $CacheUpdate(i)$ similarly corresponds to state machine event
$\G{CU}_{i}(d,a)$ when the head of $in[i]$ is $<<d,a>>$ or
$<<d,a,"$*$">>$, the only case in which the event is allowed.  The
tuple is removed from the head of $in[i]$ and the cache $c[i]$ is
updated accordingly.

\paragraph{\it MemRead}

A step allowed by action $MemRead(i)$ corresponds to a state machine
event $\G{MR}_{i}(d,a)$ for some $d$ and $a$.  This event is allowed
only when $a$ is an address and $d$ equals $mem[a]$.  It appends the
pair $<<mem[a],a>>$ to $in[i]$ and leaves everything else unchanged.

\paragraph{\it CacheInval}

A step allowed by action $CacheInval(i)$ corresponds to a
$\G{CI}_{i}$ state machine event.  It sets $c[i]$ to some restriction
of its original value.  The expression  
 $\{\![c \EXCEPT ![i] :in: Restrict(c[i])]\!\}$
is the set of all functions $f$ that are the same as $c$ except that
$f[i]$ is any element of $Restrict(c[i])$.


\subsubsection{The Complete Specification}

The definitions described thus far capture all the information
explicit in Figure~\ref{fig:Gerth-spec} except for the fairness
condition.  To write the complete TLA specification, we must also
express what is implicit in that figure---the range of $i$, $d$, $a$
and the fact that those six events are the only ones allowed.

The TLA specification corresponding to a state machine has the {\em
canonical\/} form
 $I /\ [][N]_v /\ L$,
where $I$ is the initial predicate, $N$ is the next-state action, $v$
is the tuple of all relevant variables, and $L$ is a fairness
condition.  A behavior satisfies this formula iff $I$ holds in the
initial state, every successive pair of states is a step that either
satisfies $N$ or else leaves $v$ unchanged, and the fairness condition
$L$ is satisfied.  (The reason for allowing ``stuttering steps'' that
do not change $v$ is explained
in~\cite{lamport:what-good}.)  For the lazy caching algorithm, $I$ is
the initial predicate $Init$.  We next describe the next-state action
$N$, which describes all possible events of the state machine---that
is all steps that change $v$.

We first describe all possible processor $i$ events---ones subscripted
by $i$ in Figure~\ref{fig:Gerth-spec}.  These events correspond to
steps of action $Next(i)$ of module $LazyCache$.  A step satisfies
this action iff it satisfies $Read(i,d,a)$ or $Write(i,d,a)$ for some
$d$ in $Data$ and $a$ in $Addr$, or satisfies $CacheUpdate(i)$,
$MemWrite(i)$, $MemRead(i)$, or $CacheInval(i)$.  Our specification
should assert that every nonstuttering step is a $Next(i)$ step, for
some processor $i$.  Thus, it equals
 \( Init /\ [] [:E: i :in: Proc \midcolon Next(i)]_{vars} /\ L
 \),
where $vars$ is the tuple of relevant variables and $L$ expresses the
desired fairness conditions.  We now describe~$L$.

Gerth required that all the events in Figure~\ref{fig:Gerth-spec}
except $\G{CI}_{i}$ satisfy a {\em weak fairness condition\/}---that
is, if the event is continuously enabled, then it must eventually
occur.  Weak fairness is expressed in TLA with the formula
$\WF_{v}(A)$, which asserts that if an $A$ action that changes $v$ is
continuously enabled, then a step satisfying that action must
eventually occur.  We find it unnatural to require processors to keep
executing operations forever, so we place no fairness requirements on
the $Read$ and $Write$ actions.  Because of the simplifications Gerth
made to the algorithm, fairness of $\G{MR}$ events is not needed to
prove its correctness.  We therefore place no fairness requirement on
$MemRead$ actions.  We require weak fairness of only the actions
$CacheUpdate(i)$ and $MemWrite(i)$, for every processor
$i$.\footnote{Gerth has separate fairness requirements on
$\G{CU}_{i}(d,a)$ and $\G{MW}_{i}(d,a)$ for each $d$ and $a$, but we
find it more convenient just to require fairness of $CacheUpdate(i)$
and $MemWrite(i)$.  It is not hard to show that the two sets of
conditions are equivalent.}

The complete specification of the lazy caching algorithm is given by
formula $Spec$ of module $LazyCache$.

Observe that there are no type declarations in \TLA+.  Type
correctness of our specification $Spec$ is expressed by the following
theorem, which asserts that the variables $c$, $in$, $out$, and $mem$
are always elements of the proper set.  (Module $Sequences$ defines
$Seq(S)$ to be the set of all finite sequences of elements in $S$, and $[]$
is the usual ``always'' operator of temporal
logic~\cite{manna:temporal}.)
 \[ Spec => 
    []\,(\, \begin{conj}
        mem \in [Addr -> Data] \\
        c \in [Proc -> [Addr -> Data \cup \{\bot\}] ] \\
        in \in [Proc -> Seq((Data \X Addr)\cup (Data \X Addr \X \{ "$*$"\}))] \\
        out \in [Proc -> Seq(Data \X Addr)] \;\;)
      \end{conj}
 \]
This theorem is easy to prove; the proof steps are similar to the ones
performed in conventional type checking.  However, the theorem is
stronger than the assurances provided by conventional type checkers.
For example, the definition of $Tail$ leaves $Tail(<<>>)$
unspecified,\footnote{The ``$-$'' operator in the $Sequences$ module is
the one imported from module $Naturals$, which specifies the value of
$m-n$ only for natural numbers $m$ and $n$ with $m \geq n$.} 
%
so one could not prove the theorem if the algorithm could ever try to
compute the tail of $<<>>$.  Hence, the theorem guarantees that the
algorithm never computes the tail of the empty sequence.


%try
\section{Sequential Consistency} \label{sec:sequential-consistency-sec}

We now specify sequential consistency for an arbitrary database.  (A
memory is a database in which the only operations are reading and
writing.)  We specify a serial database in
Section~\ref{sec:serial-database} and use that specification in
Section~\ref{sec:sequential-consistency} to specify a sequentially
consistent database.  In
Section~\ref{sec:Gerth-like-sequential-consistency}, we give an
equivalent specification in the spirit of
Gerth's.



\subsection{A Serial Database} \label{sec:serial-database}

Module $SerialDB$ of Figure~\ref{fig:SerialDB} specifies a serial
database that communicates with its environment by means of a
communication channel.
%
\begin{figure}
\vspace*{-1.25\baselineskip}
\begin{module}{SerialDB}
  \IMPORT ChannelInterface
  \begin{nodecls}
  {\bf parameters} \ \ \=
    dch : \VARIABLE     \\ 
    \> Op, \, InitDB : \CONSTANT   \\ 
    \> OKOp(:?:, :?:, :?: : \CONSTANT) : \BOOLEAN 
  \end{nodecls}
\midbar
  \begin{nodecls}
   INext(mem) \= == :E: o :in: Op : ChanOp(dch, o) /\ OKOp(o, mem, mem') \V{.2}
   ISpec(mem) \> == (mem :in: InitDB) \, /\ \, [][INext(mem)]_{<<mem,\, dch>>} \V{.2}
   Spec == :EE: mem : ISpec(mem)
  \end{nodecls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{Module $SerialDB$.}
\label{fig:SerialDB}
\end{figure}
%
The module first imports module $ChannelInterface$, where the operator
$ChanOp$ is defined.  It then declares the following parameters:
 %
a variable $dch$ that represents the communication channel;
 %
a constant $Op$ that represents the set of possible database operations;
 %
a constant $InitDB$ that represents the set of legal initial values
of the database;
 %
and an operator $OKOp$ that describes the legal database operations.
We interpret $OKOp(o,old,new)$ equal to \TRUE\ to mean that operation
$o$ is a legal operation when the value of the database before the
operation is $old$ and the value after the operation is~$new$.  Module
$CacheCorrectness$ in Figure~\ref{fig:CacheCorrectness}
(Section~\ref{sec:module-CacheCorrectness}) defines $OKOp$ for a
memory.

The module next defines $ISpec(mem)$ to be a formula in the canonical
form $I /\ [][N]_v$ that specifies a serial database whose state is
represented by the variable $mem$.  (Since database operations need
never occur, there is no fairness requirement.)  Action 
 $OKOp(o, mem,mem')$ 
asserts that operation $o$ is allowed to change the database from the
old value $mem$ to the new value~$mem'$.  The next-state action $INext(mem)$
therefore asserts that some operation $o$ in $Op$ is sent on channel
$dch$ and makes a legal change to the database value $mem$.

Formula $ISpec(mem)$ contains the free variable $mem$.  The
specification of our database should describe only the sequence of
operations sent on channel $dch$; it should not mention any other
variable.  Hence, $dch$ is the only variable parameter of module
$SerialDB$, which is why we had to introduce $mem$ as a formal
parameter of $ISpec$.  Our specification of the serial database is
formula $ISpec(mem)$ with the variable $mem$ hidden.  In TLA,
variables are hidden with the temporal existential quantifier $\EE$.
Formula $Spec$ of module $SerialDB$ therefore specifies a serial
database with channel $dch$ described by the constant parameters $Op$,
$InitDB$, and $OKOp$.


\subsection{Our Specification of Sequential Consistency}
\label{sec:sequential-consistency}

\subsubsection{Common Parameters}
We put declarations and definitions that are common to both
specifications of sequential consistency into module $SeqDBParams$,
shown in Figure~\ref{fig:SeqDBParams}.  The parameters $InitDB$ and
$OKOp$ have the same interpretation as in module $SerialDB$.  Module
$SeqDBParams$'s other parameters are:
 %
a variable $ch$ that represents an array of channels, where processor
$i$ communicates with the database over channel $ch[i]$;
 %
a constant $N$ that represents the number of processors;
 %
and a constant $POp$ representing an array of sets, where $POp[i]$ is the set of
operations that can be performed by processor $i$.
 %
 %
\begin{figure}
\vspace*{-1.25\baselineskip}
\begin{module}{SeqDBParams}
\IMPORT Naturals, Sequences \\
  \begin{nodecls}
   {\bf parameters} \ \ \=
    ch : \VARIABLE  \\
    \> N, \, POp, \, InitDB : \CONSTANT \\
    \> OKOp(:?:, :?:, :?: : \CONSTANT) : \BOOLEAN 
  \end{nodecls}
\midbar
  \begin{decls}{assumptions} 
    NAssump == (N \in Nat) /\ (N > 0) \\
    OpsDisjoint == 
       :A: i, j :in: Proc : (i # j) => (POp[i] :cap: POp[j] = \{\})
  \end{decls}
\midbar
  \begin{nodecls}
    Proc == 1 \dd N \\
    Op == \UNION \{POp[i] : i :in: Proc\}
  \end{nodecls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{Parameters for the specifications of a 
           sequentially consistent database.}
\label{fig:SeqDBParams}
\end{figure}
%

The module asserts, as assumption $NAssump$, that $N$ is a positive
natural.  For convenience, we assume that the operations sent by
different processors are different.  Formally, this means that
$POp[i]$ and $POp[j]$ are disjoint sets of operations, if $i$ and $j$
are different processors.  Module $SeqDBParams$ asserts, and assigns
the name $OpsDisjoint$ to, this assumption.\footnote{Assumption
$OpsDisjoint$ mentions $Proc$, which is defined later.  An assumption
may use symbols defined anywhere in the module;  its
name may not be used within the module.  (An 
assumption is assumed equivalent to \TRUE, so
there is no reason to use its name.)}

Finally, the module defines $Proc$ to be the set of processors and
$Op$ to be the set of all operations---that is, the union of the sets
$POp[i]$, for all processors $i$.  The set $Op$ plays the role of the
parameter of the same name in module $SerialDB$.  


\subsubsection{Sequential Consistency}

Intuitively, sequential consistency means that there is some
interleaving of the operations sent on channels $ch[1]$, \ldots,
$ch[N]$ that forms a correct sequence of operations for a serial
database.  The idea behind our specification is illustrated by
Figure~\ref{fig:seq-corr-db}.
%
\begin{figure}
\centering
\begin{picture}(0,135)(0,-30)
%\makegrid(-100,0)(200,100)
\thicklines
\put(0,25){\vector(0,-1){25}}
\put(2,12.5){\makebox(0,0)[l]{$dch$}}
\put(-100,25){\line(1,0){200}}
\put(-100,40){\vector(0,-1){15}}
\put(-112,40){\thinlines\framebox(24,40){$q[1]$}}
\put(-100,105){\vector(0,-1){25}}
\put(-98,92.5){\makebox(0,0)[l]{$ch[1]$}}
\put(-55,40){\vector(0,-1){15}}
\put(-67,40){\thinlines\framebox(24,40){$q[2]$}}
\put(-55,105){\vector(0,-1){25}}
\put(-53,92.5){\makebox(0,0)[l]{$ch[2]$}}
%
%\put(22.5,40){\makebox(20,40){$\cdots$}}
\put(12.5,60){\circle*{3}}
\put(22.5,60){\circle*{3}}
\put(32.5,60){\circle*{3}}
\put(100,40){\vector(0,-1){15}}
\put(88,40){\thinlines\framebox(24,40){$q[N]$}}
\put(100,105){\vector(0,-1){25}}
\put(102,92.5){\makebox(0,0)[l]{$ch[N]$}}
\put(-60,-30){\framebox(120,30){Serial Database}}
\end{picture}
\caption[]{A state machine for specifying sequential consistency.}
\label{fig:seq-corr-db}
\end{figure}
%
Consider a state machine that performs the following operations, for
each processor $i$: 
\begin{description}
\item[\it Enq] Send an operation from $POp[i]$ on channel
    $ch[i]$ and append that operation to the tail of queue $q[i]$.
\item[\it Deq] Remove the operation from the head of $q[i]$ and send it on
channel $dch$.
\end{description}
Let the state machine satisfy weak fairness of the $Deq$ action for
each $i$, which implies that every operation that is put into a queue
by an $Enq$ operation is eventually removed by a $Deq$.  It is clear
that the operations sent on the channels $ch[i]$ are sequentially
consistent if the sequence of operations sent on channel $dch$
satisfies the specification of a serial database.  Moreover, for any
sequentially consistent operations sent on the $ch[i]$, there is some
way of performing the $Deq$ operations that makes the operations sent
on $dch$ form a correct execution of the serial database.  In other
words, the operations on the $ch[i]$ are sequentially consistent iff
there is some sequence of values assumed by the queues $q[i]$ and the
channel $dch$ that is a correct execution of the state machine and
satisfies the specification of the serial database.  Let $QSpec$ be
the TLA formula describing the state machine, and let $Spec$ be the
specification of the serial database from module $SerialDB$.  The
operations on the $ch[i]$ are sequentially consistent iff the formula
 \(\EE dch, q \midcolon  QSpec \,/\ \, Spec\)
is satisfied.  This formula is the TLA specification of sequential
consistency.

The \TLA+ version of the specification appears in module
$SeqDB1$ of Figure~\ref{fig:SeqDB1}.
%
\begin{figure}[tb]
\vspace*{-1.25\baselineskip}
\begin{module}{SeqDB1}
\IMPORT SeqDBParams, ChannelInterface, Sequences
\midbar
    \INCLUDE SerialDB \AS $SDB(dch)$ % \WITH dch $<-$ c   
    \begin{nodecls}
      Enq(i, dch, q) == 
         \= :E: o :in: POp[i] : \\
         \> ___\begin{conj}
                 ChanOp(ch[i], o) \\
                 q[i]' = q[i] :o: <<o>>\\
                 \UNCHANGED dch \\
                 :A: j :in: Proc :\: \{i\} : \UNCHANGED <<q[j], ch[j]>>
               \end{conj} \\
      Deq(i, dch, q) == 
        \begin{conj}
          q[i] # <<>>           \\
          ChanOp(dch, Head(q[i])) \\
          q[i]' = Tail(q[i])    \\
          \UNCHANGED ch[i]   \\
          :A: j :in: Proc :\: \{i\} : \UNCHANGED <<q[j], ch[j]>>
        \end{conj}
    \end{nodecls}
    \begin{nodecls}
      QSpec(dch, q) == 
      \begin{conj}
         :A: i :in: Proc : q[i] = << >> \\
         [][:E: i :in: Proc : Enq(i, dch, q) \/ Deq(i, dch, q)
           ]_{<<ch, dch, q>>}\\
         :A: i :in: Proc : \WF_{<<ch, dch, q>>}(Deq(i, dch, q))             
      \end{conj} \\
  Spec == :EE: dch, q : QSpec(dch, q) /\ SDB(dch).Spec
\end{nodecls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{A specification of sequential consistency.}
\label{fig:SeqDB1}
\end{figure}
%
The module imports $SeqDBParams$, which contains the specification's
parameters, the assumption $OpsDisjoint$, and the definition of $Op$.
It also imports modules $ChannelInterface$ (for the definition of
$ChanOp$) and $Sequences$ (for the definitions of operations on
sequences).

Our specification uses the specification of a serial database, which
appears in module $SerialDB$.   Simply importing that module would import
its parameters $dch$ and $Op$, which should not be parameters of
$SeqDB1$. (Channel $dch$ is an internal variable of the
sequentially consistent database; the set $Op$ is defined in terms of
 $POp$, so it is not a parameter.)
Instead, we want to include the definitions from $SerialDB$ with the
module's parameters instan\-tiat\-ed as follows: $Op$ instantiated with
the set of the same name defined in the imported module $SeqDBParams$;
$InitDB$ and $OKOp$ instantiated with the parameters of the same name
imported from $SeqDBParams$; and $dch$ replaced by an explicit formal
parameter.  The statement
 \[ \INCLUDE\ SerialDB \AS\ SDB(dch) \]
includes the definitions from module $SerialDB$, with the names of all
defined operators prefixed by ``$SDB(dch)$.'', and with the
aforementioned instan\-tia\-tions.\footnote{In the absence of explicit
 instantiation, a parameter is instantiated by the symbol of the same 
 name.  We have chosen our names to avoid having to introduce
 the \TLA+ construct for explicit instantiation of parameters.}
% Thus, $SDB(dch).Spec$ is $\EE mem \!: \! SDB(dch).ISpec(mem)$.
For example,  $SDB(d).INext(m)$
equals
 \[ :E: o :in: Op : SDB(d).ChanOp(d, o) /\ OKOp(o, m, m') 
  \]
for any expressions $d$ and $m$, where $SDB(d).ChanOp$ equals the
operator $ChanOp$ (imported by module $SerialDB$) from module
$ChannelInterface$.  The symbols $Op$ and $OKOp$ are not prefixed by
``$SDB(\ldots).$'' because they are parameters, not defined operators.

Module $SeqDB1$ next defines the TLA formula that specifies the state
machine pictured in Figure~\ref{fig:seq-corr-db}, excluding the box
labeled ``Serial Database''.  Since the variables $dch$ and $q$ are
not parameters of the module, they must be explicit parameters of the
definition.  Formula $QSpec(dch, q)$ is the canonical-form TLA formula
that describes the state machine.

Finally, formula $Spec$ is the complete specification of sequential
consistency.  More precisely, it specifies the sequentially consistent
system with array $ch$ of channels described by the parameters $Proc$,
$POp$, $InitDB$, and $OKOp$.


\subsubsection{A Closer Look at the Specification} \label{sec:closer}

Our specification $Spec$ of module $SeqDB1$ looks deceptively
simple.  However, we shall now show that it cannot be written as a
conventional state machine.

Expanding the definition of $SDB(dch).Spec$ shows that $Spec$ equals
 \[ \EE dch, q : (QSpec(dch, q) \, /\ \, \EE mem : SDB(dch).ISpec(mem))\]
Since $mem$ does not occur in $QSpec(dch, q)$, this is equivalent to
 \[ \EE dch, q, mem : (QSpec(dch, q) /\ SDB(dch).ISpec(mem)) \]
Formulas $QSpec(dch, q)$ and $SDB(dch).ISpec(mem)$ are both in
canonical form.  Since $[]$ distributes over conjunction, a straightforward
calculation allows us to rewrite
 \( QSpec(dch, q) /\ SDB(dch).ISpec(mem)\)
in the canonical form $I /\ [][N]_v /\ L$, where the next-state action
$N$ is 
 \[ \E i \in Proc : \begin{disj}
                      Enq(i, dch, q) /\ (mem'=mem)  \\
                      Deq(i, dch, q) /\ SDB(dch).INext(mem)
                    \end{disj}
 \]
$v$ is the tuple $<<ch, dch, q, mem>>$,
and $L$ is the conjunction of weak fairness conditions on $Deq(i, dch, q)$
actions.  

Formula $I /\ [][N]_v$ is the TLA representation of the state
machine of Figure~\ref{fig:seq-corr-db}, including the ``Serial
Database'' box.  However, $L$ does not correspond to any conventional
fairness condition on state machines.  The next-state action $N$
allows a $Deq$ action to occur only when it is also an
$SDB(dch).INext(mem)$ action.  In other words, a $Deq$ step can occur
only if it sends a correct serial database operation on $dch$.
However, weak fairness on $Deq(i, dch, q)$ requires that this
operation must eventually be performed if $q[i]$ is nonempty,
regardless of whether or not doing so would violate the serial database
specification for $dch$.  This requirement is not a conventional
state-machine fairness condition.  TLA formulas are more expressive
than state machines.


Viewed as a machine, our specification is bizarre.  The machine is
allowed to perform any arbitrary operation on $ch[i]$, regardless of
its legality.  However, when the operation reaches the head of $q[i]$,
it must eventually be a correct operation for the serial database.  In
the case of a sequentially consistent memory, a read of address $a$ on
$ch[i]$ may return any arbitrary value $d$.  However, at some time
after the read operation reaches the head of $q[i]$, the value of
$mem[a]$ must equal $d$.  That value could have been written by an
operation on another channel $ch[j]$ that occurred after the read.


In the terminology of~\cite{abadi:existence}, our specification is not
machine closed.  Conventional state-machine specifications are always
machine closed.  Machine closure is a necessary condition for a
specification to be executable in practice.  The description of an
algorithm should be machine closed, but a high-level specification
need not be.

%try
\subsection{A Gerth-Like Specification of Sequential Consistency}
\label{sec:Gerth-like-sequential-consistency}

\subsubsection{Channels}

Gerth specified sequential consistency directly in terms of the
sequence of values transmitted over a channel.  TLA formulas are
written in terms of variables that describe the current state.  To
express Gerth's specification in TLA, we must introduce a {\em
history\/} variable for each channel to record the sequence of values
that have been sent over the channel.  This is done in module
$ChannelInterface$ of Figure~\ref{fig:ChannelInterface}, which defines
the following two operators.

\label{sec:ChannelInterface}%%%  
%%% A reference to the section containing the module.
\begin{figure}
\vspace*{-1.25\baselineskip}
\small
\begin{module}{ChannelInterface}
\IMPORT Sequences, Naturals
\midbar
   \begin{nodecls}
%     ChanOp(c, v) == c' = <<v, \IF{c[2] = "a"} \THEN "b"\\
%                                                  \ELSE "a"  >> \FI \\
     ChanHist(c, h) \= == \=\kill
     ChanOp(c, v) \> == \> c' = <<v,\ {\bf if}\ {c[2] = "a"}\ {\bf then}\ "b"
                            \ {\bf else}\ "a"  >> \\
%        ___\comment{Represents sending $v$ on channel $c$.}\\
     ChanHist(c, h) \> == 
          \> \begin{conj}
               h = << >> \\
               [][\,h' \,=\, {\bf if}\ c'#c\ 
                               {\bf then}\ h :o: <<c'[1]>> \
                               {\bf else}\ h\,]_{<<h, c>>}
             \end{conj}
%     \\___\comment{Asserts that $h$ is a history variable for channel $c$.}
    \end{nodecls}
%   \begin{decls}{theorem}
%     ChanopProperties == \begin{conj}
%                           :A: v : ChanOp(c, v) => (c' # c) \\
%                           :A: v,w : ChanOp(c, v) /\ ChanOp(c, w) => (v=w)
%                         \end{conj}
%   \end{decls}
\end{module}
\vspace{-\baselineskip}
\caption[]{Module $ChannelInterface$}
\label{fig:ChannelInterface}
\end{figure}

\paragraph{\it ChanOp } A step satisfying action $ChanOp(c,v)$ must represent
the event of sending the value $v$ on a channel represented by the
variable $c$.  The obvious way to represent this event is by setting the
value of $c$ to $v$.  However, this won't work because sending the same
value $v$ again would result in no change to $c$, and no change to $c$ must
represent nothing being sent on the channel.  We therefore define
$ChanOp(c,v)$ to set $c$ to a pair $<<v, \ldots>>$, where the second
component is chosen to ensure that the new value of $c$ does not equal
its old value.  There are any number of ways to do this.  In module
$ChannelInterface$, we let $ChanOp(c,v)$ set the second component
alternately to $"a"$ and $"b"$.  More precisely, $ChanOp(c,v)$ asserts
that $c'$ equals $<<v, "a">>$ unless the second component of $c$
equals $"a"$, in which case $c'$ equals $<<v, "b">>$.\footnote{In
\TLA+, $c[2]$ is some value---even if $2$ is not in the domain of $c$.
Hence, a specification need not specify any initial value for the
channel.}

%try
\paragraph{\it ChanHist}
The temporal formula $ChanHist(c,h)$ 
asserts that the value of $h$ always equals the sequence of values
that have been sent over $c$.  Two alternative definitions are
%  \[ \begin{noj}
%    (h = <<>>) 
%      /\ [][\E v \midcolon ChanOp(c,v) /\ (h' = h \o <<v>>)]_{<<h,c>>} \V{.2}
%    (h = <<>>) /\ [][\A v\midcolon ChanOp(c,v) => (h' = h \o <<v>>)]_{<<h,c>>} 
%     \end{noj}
%  \]
  \[ \begin{noj}
       (h = <<>>) 
      /\ [][\E v \midcolon ChanOp(c,v) /\ (h' = h \o <<v>>)]_{<<h,c>>} \V{.6}
       (h = <<>>) 
      /\ [] {\notla  
              \left[ \begin{array}{@{\land\;}l@{}}
                       \tla \A v\midcolon ChanOp(c,v) => (h' = h \o <<v>>) \\
                       \tla (c'=c) => (h'=h)
                      \end{array}
              \right]_{\tla<<h,c>>}}
            \end{noj}
  \]
Using the TLA proof rules~\cite[Figure~5]{lamport:newtla}, it is
easy to show that the formula 
 $[][\E v \midcolon ChanOp(c,v)]_{c}$, which
asserts that every change to $c$ is a $ChanOp$ event,
implies that all three definitions are equivalent.
%try


\paragraph{Representing Channels}

Our method of representing channels is artificial; the use of pairs
and the values $"a"$ and $"b"$ were completely arbitrary.  The
definition of $ChanOp$ is artificial because the interface itself does
not correspond to any real form of communication.  Asynchronous
communication requires two separate events---the sending of a value
and its acknowledgement.  In a real memory, a read operation consists
of a processor request (which may cause the cache to be updated)
followed by the memory's response.  The more realistic interface has a
more natural representation.  Gerth chose the artificial interface to
simplify the problem.  The simpler interface makes it impossible to
specify some correctness properties of a real memory---in particular,
the property that every request is eventually followed by a reply.

A more elegant description of a channel can be obtained by writing
axioms for $ChanOp$ instead of defining it explicitly.  However, lists
of axioms are notoriously difficult to understand.  It is easy to
write an incomplete specification by omitting axioms.  Few people
would think of including the axiom
 $ChanOp(c,v) => (c'\neq c)$ when specifying $ChanOp$.
We believe that a clear, inelegant definition is better than an
obscure, elegant list of axioms.


\subsubsection{The Gerth-Like Specification}

Gerth's specification of a sequentially consistent database with array
$ch$ of channels essentially asserts that there exists a serial
database with channel $dch$ such that, for each processor $i$, the
sequence of operations sent on $ch[i]$ equals the sequence of
operations from processor $i$ sent on $dch$.  Since $ChanHist(c,h)$
asserts that $h$ is the history of operations sent on channel $c$, if
$SDB(dch).Spec$ is the specification of a serial database with channel
$dch$, then Gerth's specification is\footnote{Universal 
 quantification over flexible variables is defined
 by $\AA x \midcolon F \,\deq\, \lnot \EE x \midcolon \lnot F$.}
 \[ :EE: dch : \begin{conj}
                 SDB(dch).Spec \\
                \begin{noj}
                   :A: i :in: Proc : :AA: hch, hdch : \\
                     __\begin{noj}
                        ChanHist(dch, hdch) /\ ChanHist(ch[i], hch) => 
                          G
                     \end{noj}
                   \end{noj}
              \end{conj}
 \]
where $G$ asserts the appropriate relation between the history
variable $hch$ for $ch[i]$ and the history variable $hdch$ for $dch$.
Our problem is writing $G$ in temporal logic.


Since channel $dch$ is internal, it doesn't matter when the operations
appear there.  Without loss of generality, we can let $G$ require that
operations not appear on $dch$ before they appear on $ch[i]$.  Gerth's
specification is then obtained by requiring that the sequence of
operations sent at any time on channel $ch[i]$ eventually equals
the sequence of operations by processor $i$ that have been sent on
$dch$.  This assertion can be written
 \[ :A: os : []((hch = os) => <>(os = Proj(i, hdch))) \]
where $Proj(i, \sigma)$ is the subsequence of operations in $\sigma$
sent by processor $i$, and $<>$ is the usual temporal operator meaning
{\em eventually}~\cite{manna:temporal}.  The complete specification
appears as formula $Spec$ of module $SeqDB2$ in
Figure~\ref{fig:SeqDB2}.  It uses the operator $SelectSeq$, which is
defined in module $Sequences$ so that $SelectSeq(s,Test)$ is the
subsequence of $s$ consisting of all elements $e$ with $Test(e)$ equal
to \TRUE.

\begin{figure}
\vspace*{-1\baselineskip}
\begin{module}{SeqDB2}
\IMPORT SeqDBParams, Sequences, ChannelInterface, Naturals
\midbar
  \INCLUDE SerialDB \AS $SDB(dch)$ % \WITH dch $<-$ dch               \\
  \begin{nodecls}
  Proj(i, s) == 
  {\bf let}\ Test(e) \;:deq:\; e :in: POp[i] \ 
             {\bf in}\ SelectSeq(s, Test)\V{.2}
%
  Spec == :EE: dch : 
             \begin{conj}
               SDB(dch).Spec \\
                \begin{noj}
                   :A: i :in: Proc : :AA: hch, hdch :  \\
                     __\begin{noj}
                        ChanHist(dch, hdch) /\ ChanHist(ch[i], hch) => \\
                       __:A: os : []((hch = os) =>
                              <>(os = Proj(i, hdch)))
                     \end{noj}
                   \end{noj}
              \end{conj}
%  Spec == ISpec(dch)
  \end{nodecls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{A history-based specification of sequential consistency.}
\label{fig:SeqDB2}
\end{figure}

\subsubsection{Relating the two Specifications}

We hope it is intuitively clear that the two specifications of
sequential consistency, formulas $Spec$ of modules $SeqDB1$ and
$SeqDB2$, both allow the same sets of behaviors for the array $ch$ of
channels.  Formally, this means that the two formulas are equivalent.
Their equivalence is expressed in \TLA+ by the theorem named $Thm$ of
module~$DB1equivDB2$ in Figure~\ref{fig:DB1equivDB2}.
%
\begin{figure}
\vspace*{-1\baselineskip}
\begin{module}{DB1equivDB2}
\IMPORT SeqDBParams
\midbar
  \INCLUDE SeqDB1 \AS $DB1$ \\
  \INCLUDE SeqDB2 \AS $DB2$
  \begin{decls}{theorem}
     Thm  == DB1.Spec \equiv DB2.Spec
  \end{decls}
\end{module}
\addvspace{-\baselineskip} 
\caption[]{The two specifications of sequential consistency are
equivalent.} \label{fig:DB1equivDB2}
\end{figure}

We will prove that the lazy caching algorithm implements our
specification of sequential consistency.  Formally, this means proving
that formula $Spec$ of module $LazyCache$ implies formula $Spec$ of
module $SeqDB1$.  To prove that the algorithm also implements the
Gerth-like specification, it suffices to prove that formula $Spec$ of
module $SeqDB1$ implies formula $Spec$ of module $SeqDB2$, which is
half of the theorem in module $DB1equivDB2$.  

%try
\section{The Proof} \label{sec:proof}


Our goal here is not to convince the reader that the lazy caching
algorithm is correct, but to indicate how a convincing proof is
obtained.  Naive readers may be convinced by a nonrigorous proof, but
published ``proofs'' of incorrect concurrent algorithms have
demonstrated the need for rigor.  Rigorous proofs are long, detailed,
and tedious.  They are difficult to present on paper and are best
suited to hypertext.  We will therefore give the complete proof
elsewhere~\cite{ladkin:gerth-web-proof}; here, we just describe how
the proof is obtained.  Section~\ref{sec:theorems-statement} states
our result formally and describes the outline of the proof.
Sections~\ref{sec:complete-cache}--\ref{sec:proof-sketch} specify two
intermediate algorithms and sketch the more interesting parts of the
proof.


%try
\subsection{Outline of the Proof} \label{sec:theorems-statement}

We might expect sequential consistency to mean that the algorithm's
specification, formula $Spec$ of module $LazyCache$, implies formula
$Spec$ of module $SeqDB1$, which is our specification of sequential
consistency.  However, those two formulas have different parameters.
The algorithm's memory is described by the parameters $Data$,
$InitData$, and $Addr$, while sequential consistency is defined in
terms of a more general database specified by the parameters $POp$,
$InitDB$, and $OKOp$.  Module $CacheCorrectness$ in
Figure~\ref{fig:CacheCorrectness}
%
\begin{figure}
\vspace*{-1.25\baselineskip}
\begin{module}{CacheCorrectness}
\IMPORT MemParams
 \begin{nodecls}
 {\bf parameters} \ \
   c, in, out, mem : \VARIABLE 
 \end{nodecls}
\midbar
\INCLUDE LazyCache \AS $LC$
\begin{nodecls}
    POp == [i :in: Proc |-> \{i\} :X: \{"Rd", "Wr"\} :X: Data :X: Addr] \\
%
    OKOp(o, old, new) == 
     \begin{disj}
         \begin{conj}
           o[2] = "Rd" \\ o[3] = old[o[4]] \\ new = old
         \end{conj}\\
         \begin{conj}
           o[2] = "Wr" \\
           new = [old \EXCEPT ![o[4]] = o[3]\,]
         \end{conj}
       \end{disj} \\
    InitDB == [Addr -> InitData] \vs{.2}
\end{nodecls}
\INCLUDE SeqDB1 \AS DB1 \\
{\bf theorem}\ \ $LCimpliesDB1 == LC.Spec => DB1.Spec$
%
\midbar
%
\INCLUDE CCache \AS $CC(cc, cin, cout)$ \vs{-.4}
\begin{decls}{theorems}
%DB1impliesDB2 == DB1.Spec => DB2.Spec\\
LCimpliesCC  == 
 LC.Spec => (:EE: cc, cin, cout : CC(cc, cin, cout).Spec) \\
CCimpliesDB1 == \AA cc, cin, cout :  CC(cc, cin, cout).Spec => DB1.Spec
\end{decls}
%
\midbar
%
\INCLUDE ACCache \AS $ACC(cc, cin, cout, vcq, vrq, vdch)$ \vs{-.4}
\begin{decls}{theorems}
 CCequivACC  ==\\
  \s{1} \AA cc, cin, cout:  CC(cc, cin, cout).Spec \; \equiv \\
  \s{2} (:EE: vcq, vrq, vdch : 
      ACC(cc, cin, cout, vcq, vrq, vdch).ASpec)
\\
ACCimpliesDB1 == \\
  \s{1}\AA cc, cin, cout, vcq, vrq, vdch  :  \\
   \s{2}   ACC(cc, cin, cout, vcq, vrq, vdch).ASpec => DB1.Spec
\end{decls}
\end{module}
\addvspace{-\baselineskip}
\caption[]{The theorems constituting the correctness proof.}
\label{fig:CacheCorrectness}
\end{figure}%
\label{sec:module-CacheCorrectness}%
%
imports and declares the same parameters as the $LazyCache$ module,
and then includes module $LazyCache$ as $LC$.  It next defines the
constants $POp$, $OKOp$, and $InitDB$ and includes $SeqDB1$ as $DB1$,
implicitly substituting these three constants for the parameters of
the same name in $SeqDB1$.  The module then asserts theorem
$LCimpliesDB1$, which expresses formally the sequential consistency of
the lazy caching algorithm.

We split the proof of theorem $LCimpliesDB1$ into two parts by
introducing an intermediate algorithm, called the complete cache.  
The complete cache is specified by formula
$Spec$ of module $CCache$, which appears in
Section~\ref{sec:complete-cache} below.  The $CacheCorrectness$ module
includes this module and then asserts that the lazy caching algorithm
implements the complete cache (theorem $LCimpliesCC$) and that the
complete cache is sequentially consistent (theorem $CCimpliesDB1$).
The complete cache specification has three additional variable
parameters, $cc$, $cin$, and $cout$, that are instantiated by
parameters and are quantified in the statements of the theorems.
As with ordinary first-order quantification, the formula $\AA x \midcolon F$
is valid iff $F$ is.  (The $\AA$ is needed in theorem $CCimpliesDB1$
because module parameters are the only free variables allowed by \TLA+
in a theorem.)  By simple logic, theorems $LCimpliesCC$ and
$CCimpliesDB1$ imply theorem $LCimpliesDB1$.

We sketch the proof of the more interesting of these two theorems,
$CCimpliesDB1$.  The temporal existential quantifiers in the
definition of $DB1.Spec$ mean that the proof requires a refinement
mapping~\cite{abadi:existence}.  To define the refinement mapping, we
add to the complete cache three auxiliary variables, $vcq$, $vrq$, and
$vdch$.  The complete cache with auxiliary variables is specified by
formula $ASpec$ of module $ACCache$, which appears in
Section~\ref{sec:ACCache}.  The $CacheCorrectness$ module includes
this module and then asserts two theorems.  The first, $CCequivACC$,
states that formula $ASpec$ with the auxiliary variables hidden is
equivalent to the complete cache specification.  This is what it means
for $vcq$, $vrq$, and $vdch$ to be auxiliary variables.  The second
theorem states the sequential consistency of the complete cache with
auxiliary variables.  These two theorems imply $CCimpliesDB1$.

To prove that the lazy caching algorithm is sequentially consistent,
we must prove theorems $LCimpliesCC$, $CCequivACC$, and
$ACCimpliesDB1$ of module $CacheCorrectness$.  Proving this for a
Gerth-like definition of sequential consistency requires also proving
the implication
 $DB1.Spec => DB2.Spec$ 
of $Thm$ in module $DB1equivDB2$ (Figure~\ref{fig:DB1equivDB2}).
Complete proofs of these four results will be given
elsewhere~\cite{ladkin:gerth-web-proof}.  The equivalence of the two
specifications of sequential correctness, while interesting, has
nothing to do with caching algorithms.  For reasons discussed below,
the implementation of the complete cache by the lazy caching algorithm
is not as interesting as the sequential consistency of the complete
cache.  We will therefore consider here only the proofs of
$CCequivACC$ and $ACCimpliesDB1$.



%try
\subsection{The Complete Cache} \label{sec:complete-cache}

The subtle aspect of the lazy caching algorithm is its handling of
read and write requests.  The invalidation and refreshing of cache
entries (actions $CacheInval(i)$ and $MemRead(i)$) are standard.  We
construct the {\em complete cache\/} algorithm that describes the
execution of read and write requests, but not the invalidation and
refreshing of cache entries.  We can then prove that the complete
cache is implemented by the lazy caching algorithm (theorem
$LCimpliesCC$) and implements the specification of sequential
consistency (theorem $CCimpliesDB1$).

In the complete cache algorithm, each cache is a complete memory (a
total function from locations to data values); there is no shared
memory and no cache invalidation or refresh action.  The algorithm is
pictured as a state machine in Figure~\ref{fig:complete-cache}.  
%
\begin{figure}[b]
\centering
%\fbox{%
\begin{picture}(0,182.5)(0,60)
%\makegrid(-200,0)(400,300)
%\put(-75,5){\framebox(150,25){\small$mem$}}
%
\thicklines
%\put(20,60){\vector(0,-1){30}}
%\put(-122.5,50){\line(1,0){94.5}}
%\put(-28,30){\line(0,1){20}}
%\put(-122.5,50){\vector(0,1){26.85}}
%\put(-12,30){\line(0,1){20}}
%\put(-12,50){\line(1,0){93.5}}
%\put(81.5,50){\vector(0,1){26.85}}
%\put(-20,40){\makebox(0,0){$\ldots$}}
%
\put(0,60){\setlength{\unitlength}{.85pt}%
\begin{picture}(0,200)
%\makegrid(-200,0)(400,250)
\thicklines
{\linethickness{2pt}%
\put(-150.5,-1){\line(1,0){301}}}
\put(-150,0){\vector(0,1){20}}
\put(-150,80){\vector(0,1){20}}
\put(-150,150){\vector(0,1){20}}
\put(-150,170){\line(1,0){60}}
\put(-90,20){\vector(0,-1){20}}
\put(-90,170){\vector(0,-1){90}}
\put(-120,170){\line(0,1){20}}
%
\put(90,0){\vector(0,1){20}}
\put(90,80){\vector(0,1){20}}
\put(90,150){\vector(0,1){20}}
\put(90,170){\line(1,0){60}}
\put(150,20){\vector(0,-1){20}}
\put(150,170){\vector(0,-1){90}}
\put(120,170){\line(0,1){20}}
\thinlines
\small
\put(-170,20){\framebox(40,60){\small$cin[1]$}}
\put(-110,20){\framebox(40,60){\small$cout[1]$}}
\put(-175,100){\framebox(50,50){$cc[1]$}}
\put(-118,180){\makebox(0,0)[l]{$ch[1]$}}
%
\put(-120,200){\makebox(0,0)[b]{\normalsize Processor\ $1$}}
\put(120,200){\makebox(0,0)[b]{\normalsize Processor\ $N$}}
%
\put(70,20){\framebox(40,60){\small$cin[N]$}}
\put(130,20){\framebox(40,60){\small$cout[N]$}}
\put(65,100){\framebox(50,50){$cc[N]$}}
\put(122,180){\makebox(0,0)[l]{$ch[N]$}}
%
\put(-10,85){\circle*{3}}
\put(0,85){\circle*{3}}
\put(10,85){\circle*{3}}
%\put(-15,85){\circle*{3}}
%\put(-5,85){\circle*{3}}
%\put(5,85){\circle*{3}}
\end{picture}}%
\end{picture}%
%%%}
\caption[]{The state machine $CCache$ describing the complete cache algorithm,
where $cc[i]$ is a complete cache, and $cout[i]$ and $cin[i]$ are
queues of 
 $\langle processor, operation, data, address\rangle$ 
tuples.}
\label{fig:complete-cache}
\end{figure}
%
To simplify the proof, we replace the queues $out[i]$ and $in[i]$ of
the lazy caching algorithm with queues $cout[i]$ and $cin[i]$
containing complete operations
 $<<i, op, d, a>>$, 
where $i$ is the processor that issued the operation, $op$ is the
operation ($"Rd"$ or $"Wr"$), $d$, is the data value, and $a$ is the
address.  A $*$-ed entry in $c[i]$ becomes an operation in $cin[i]$
whose first component equals~$i$.  Some of these components are
redundant---in particular, the queues contain only write operations,
and $cout[i]$ contains only operations of processor $i$.  All the
caches $cc[i]$ have the same initial memory contents, and the $cin$
and $cout$ queues are initially empty.  The \TLA+ specification of
this state machine appears in module $CCache$ of
Figure~\ref{fig:CCache}.
%
\begin{figure}
\vspace*{-1.25\baselineskip}
\begin{module}{CCache}
\IMPORT MemParams, ChannelInterface, Sequences, Naturals \V{.4}
%\midbar
{\bf parameters} \ 
%  \begin{decls}{parameters}
    cc,  cin, cout : \VARIABLE 
%  \end{decls}
\midbar
    \begin{nodecls}
      Init == \begin{conj}
                 cc :in: [Proc -> [Addr -> InitData] ] \\
                 :A: i,j :in: Proc : cc[i] = cc[j] \\
                 cin = [i :in: Proc |-> <<>>] \\    
                 cout = [i :in: Proc |-> <<>>] \vs{.2}
               \end{conj} \\
%
      Read(i,d,a) == \begin{conj}
                       cout[i] = <<>> \\
                       :A: j :in: (1 :dd: Len(cin[i])): cin[i][j][1]#i \\
                       cc[i][a] = d \\
                       ChanOp(ch[i], <<i,"Rd",d,a>>) \\
                       :A: j :in: Proc :\: \{ i \} : \UNCHANGED ch[j]\\
                       \UNCHANGED <<cc, cin, cout>> \vs{.2}
                     \end{conj} \\
      Write(i,d,a) == \begin{conj}
                       ChanOp(ch[i], <<i,"Wr",d,a>>) \\
                       cout' = [cout \EXCEPT ![i] =  
                                     cout[i] \o << <<i,"Wr",d,a>> >>] \\
                       :A: j :in: Proc :\: \{ i \} : \UNCHANGED ch[j]\\
                       \UNCHANGED << cc, cin >> \vs{.2}
                      \end{conj} \\
      MemWrite(i) == 
       \begin{conj}
	   cout[i] # << >> \\
           cout' = [cout \EXCEPT ![i] = Tail(cout[i])] \\
           cin' = [j :in: Proc |-> cin[j] :o: <<Head(cout[i])>>] \\
           \UNCHANGED << cc, ch >> \vs{.2}
         \end{conj} \\
      CacheUpdate(i) == \\
       ___\begin{conj}
             cin[i] # << >> \\
             cin' = [cin \EXCEPT ![i] = Tail(cin[i])] \\
             cc'  = [cc \EXCEPT ![i][Head(cin[i])[4]] = Head(cin[i])[3]] \\
             \UNCHANGED << cout, ch >> \vs{.4}
          \end{conj} \\
      Next(i) == \begin{disj}
                       :E: d :in: Data ,a :in: Addr :  
                          Read(i,d,a) \/ Write(i,d,a) \\
                           MemWrite(i) \/ CacheUpdate(i) %\vs{.2}
                         \end{disj} \\
%
      vars == << cc, cin, cout, ch >> \V{.2}
%
   Spec   == \begin{conj}
               Init \\ [] [:E: i :in: Proc : Next(i)]_{vars} \\
               :A: i :in: Proc : \WF_{vars}(CacheUpdate(i)) 
                  /\ \WF_{vars}(MemWrite(i)) 
             \end{conj}
\end{nodecls}
\end{module}
\addvspace{-1.4\baselineskip}
\caption[]{The complete cache algorithm.}
\label{fig:CCache}
\end{figure}
%

Theorem $LCimpliesCC$ of module $CacheCorrectness$, which asserts that
the lazy caching algorithm implements the complete cache, essentially
proves the correctness of the algorithm's cache invalidation and
refreshing operations.  Since these operations are standard, the proof
of the theorem does not reveal anything interesting about the lazy
caching algorithm.  Here, we consider only the proof of theorem
$CCimpliesDB1$, which asserts the sequential consistency of the
complete cache.

%try
\subsection{The Complete Cache with Auxiliary Variables}
\label{sec:ACCache}

We now describe how to prove theorem $CCimpliesDB1$.  
As we observed in Section~\ref{sec:closer},
$DB1.Spec$ is equivalent to
 \[ \EE dch, q, mem : DB1.QSpec(dch, q) /\ DB1.SDB(dch).ISpec(mem) \]
One proves a theorem of the form $\AA x \midcolon F$ by simply proving
$F$.  Therefore, the proof of $CCimpliesDB1$ is reduced to proving
a theorem of the form
\begin{equation} \label{eq:form-of-CCimpliesDB1-2}
   S1 \, => \,  \EE dch, q, mem : S2
\end{equation}
In first-order logic, one proves an existentially quantified formula
by finding instantiations for the quantified variables.  For temporal
existential quantification, the instantiations are called a
 {\em refinement mapping}~\cite{abadi:existence}.
We prove (\ref{eq:form-of-CCimpliesDB1-2}) by defining state functions
\O{dch}, \O{q}, and \O{mem} in terms of the variables that appear in
$S1$ and proving $S1 => \O{S2}$, where \O{F} is the formula obtained
by substituting \O{dch} for $dch$, \O{q} for $q$, and \O{mem} for
$mem$ in $F$, for any formula~$F$.

Intuitively, $S1 => \O{S2}$ means that if $ch$, $cc$, $cin$, and
$cout$ change the way $S1$ allows them to, then \O{dch}, \O{q}, and
\O{mem} change the way $S2$ allows $dch$, $q$, and $mem$ to change.
In other words, changes to the variables allowed by $S1$ cause changes
to the barred variables that simulate the changes to the unbarred
variables allowed by $S2$.  We construct the refinement mapping by
deciding which events allowed by $S1$ simulate the events allowed by
$S2$.

To define $\O{mem}$, we choose an event in the complete cache state
machine to simulate the sequential consistency state machine's event
of dequeuing a write operation and updating the database.  We let the
dequeue event happen when the last copy of a write is removed from the
$cin$ queues.  Writes are performed in the same order to all the
caches $cc[i]$.  Hence, simulating the dequeue when the write is
performed to the last cache means that $\O{mem}$ will equal a cache
$cc[i]$ to which the fewest writes have been performed.  (There may be
several such caches, in which case they will all be equal.)  Fewer
writes have been performed to cache $cc[i]$ than to cache $cc[j]$ iff
the queue $cin[i]$ is longer than the queue $cin[j]$.  Letting $pMax$
be some processor such that the length of $cin[pMax]$ is greater than
or equal to the length of $cin[j]$ for any other processor $j$, we
define \O{mem} to equal $cc[pMax]$.

Having defined \O{mem}, we quickly see that it is impossible to define
\O{dch} and \O{q}.  The complete cache state machine does not contain
the information needed to construct the queues $\O{q}[i]$ because it
does not remember read operations.  It does not contain the
information needed to define \O{dch} because the write operation that
changes \O{mem}, which must appear in \O{dch}, is immediately
forgotten.

To finish constructing our refinement mapping, we must add {\em
auxiliary variables\/}~\cite{abadi:existence} to the complete cache.
Adding an auxiliary variable $a$ to a specification $S$ means finding
a formula $S^{a}$ such that $\EE a \midcolon S^{a}$ is equivalent to
$S$.  In our example, we need two types of auxiliary variables: history
variables and stuttering variables.  A history variable records what
happened in the past, but doesn't affect how other variables change.
A stuttering variable forces stuttering steps---ones in which the
other variables are left unchanged.  

To define \O{q}, we want to add a queue $vq$ such that $\O{q}[i]$
equals
 $Proj(i, vq) \o cout[i]$, for each processor $i$.  (Recall
that $Proj(i, vq)$ is the subsequence of operations in $vq$ issued by
processor $i$.)  A write is appended to the tail of $vq$ when it is
moved to the $cin$ queues by a $MemWrite$ action.  It is removed from
$vq$, and hence from the appropriate queue $\O{q}[i]$, when $\O{mem}$
is updated---which is when the last copy of that write is removed from
the $cin$ queues.  It follows that the sequence of writes in $vq$
will always equal $cin[pMax]$.

% A read is inserted into $vq$ when it is issued by a $Read$ action.
% The trick is to insert the read in the right place.  Since a read by
% processor $i$ returns the value currently in $cc[i]$, the read should
% be put into $vq$ immediately before the first write that has not yet
% been performed to $cc[i]$---or at the end of $vq$ if there is no such
% write.  There will be exactly $Len(cin[i])$ writes in $vq$ that have
% not been performed to $cc[i]$, so the read is put before the
% $Len(cin[i])$'th write from the end of $vq$---or at the end of $vq$,
% if $Len(cin[i])$ equals zero.  Since the sequence of writes in $vq$
% equals $cin[pMax]$, the read is put immediately before the
% $(Len(cin[pMax])-Len(cin[i])+1)${\em st\/} write from the front of
% $vq$---or at the end if $Len(cin[i])$ equals zero.


A read is inserted into $vq$ when it is issued by a $Read$ action; the
trick is to insert it in the right place.  A read by processor $i$
returns the value currently in $cc[i]$, so it should be inserted into
$vq$ behind all writes already performed to $cc[i]$, and in front of
all writes not yet performed to $cc[i]$.  Operations by processor $i$
must appear in $vq$ in the order in which they were issued.  A $Read$
action is enabled only when all writes by $i$ have already been
performed to $cc[i]$; we ensure that the read is placed behind any
preceding reads by processor $i$ by placing it immediately in front of
the first write that has not yet been performed to $cc[i]$---or at the
end of $vq$ if there is no such write.  There will be exactly
$Len(cin[i])$ writes in $vq$ that have not been performed to $cc[i]$,
so the read is put in front of the $Len(cin[i])$'th write from the end
of $vq$---or at the end of $vq$, if $Len(cin[i])$ equals zero.  Since
the sequence of writes in $vq$ equals $cin[pMax]$, the read is put
immediately in front of the $(Len(cin[pMax])-Len(cin[i])+1)${\em st\/}
write in $vq$---or at the end of $vq$ if $Len(cin[i])$ equals
zero.



A write is removed from the head of $vq$, and hence from the head of
some $\O{q}[i]$, by a $CacheUpdate$ step.  However, there is no action
of the complete cache that can be used to remove a read from $vq$.  It
must be removed by a stuttering step---one that does not change $cc$,
$cin$, $cout$, or $ch$.  We represent $vq$ as $vrq \o vcq$,
where $vrq$ is a possibly empty sequence of reads, and, if $vcq$ is
nonempty, then the head of $vcq$ is a write.  We first add $vcq$ as a
history variable, then add $vrq$ as a stuttering variable.

Finally, we add a channel $vdch$ as a history variable and let
$\O{dch}$ equal $vdch$.  The complete cache algorithm with these
auxiliary variables is described by formula $ASpec$ of module
$ACCache$ in Figures \ref{fig:ACCache1} and \ref{fig:ACCache2}.
\begin{figure}
\vspace*{-1.25\baselineskip}
\begin{nomodule}
\topbar{ACCache}
 \IMPORT CCache, MemParams, ChannelInterface, Sequences, Naturals
%
 \begin{nodecls}
 {\bf parameters} \ \ vcq, vrq, vdch : \VARIABLE 
 \end{nodecls}
\midbar
\begin{nodecls}
%
    Op == Proc :X: \{"Rd", "Wr"\} :X: Data :X: Addr \\
%
  AInit == 
% Init /\ (vcq = <<>>) /\ (vrq = <<>>) \\
  \begin{conj}
   Init \\ vcq = <<>> \\ vrq = <<>> \vs{.2}
  \end{conj} \\
%
  pMax == \CHOOSE i :in: Proc : 
               :A: j :in: Proc : Len(cin[j]) :leq: Len(cin[i]) \V{.2}
  ARead(i,d,a) ==  \\
   ___\LET Insert[k : Nat,  s : Seq(Op)] == \\
          __\IF {(s = <<>>) \/ ((k=0) /\ (Head(s)[2] = "Wr"))} \\
             \THEN <<i, "Rd", d, a>> :o: s \\
             \ELSE \IF {Head(s)[2] = "Rd"} \\
                      \THEN << Head(s) >> :o: Insert[k, Tail(s)] \\
                      \ELSE << Head(s) >> :o: Insert[k-1, Tail(s)] 
          \FI      \FI
%
     \IN \begin{conj}
           vrq = <<>> \\
           Read(i,d,a) \\
           \begin{disj}
             \begin{conj}
               Len(cin[pMax])=Len(cin[i]) \\
               vrq' = << <<i,"Rd",d,a>> >> \\
               \UNCHANGED vcq
              \end{conj} \\
              \begin{conj}
                 Len(cin[pMax])#Len(cin[i]) \\
                 vcq'=Insert[Len(cin[pMax])-Len(cin[i]),\,vcq] \\
                 \UNCHANGED vrq
             \end{conj}
          \end{disj} \\
          \UNCHANGED vdch \vs{.2}
        \end{conj} \NI \\
%
  AWrite(i,d,a) == 
  \begin{conj}
        Write(i,d,a) \\
        vrq = <<>> \\
        \UNCHANGED <<vcq, vrq, vdch>> \vs{.2}
      \end{conj} \\
%
  AMemWrite(i) == 
   \begin{conj}
        MemWrite(i) \\
        vrq = <<>> \\
   vcq' = vcq:o:<<Head(cout[i])>> \\
        \UNCHANGED <<vrq,vdch>> \\
      \end{conj}
\end{nodecls}
\end{nomodule}
\caption[]{The complete cache with auxiliary variables (beginning).}
\label{fig:ACCache1}
\end{figure}%
%
\begin{figure}[tb]
\vspace*{-1.25\baselineskip}
\begin{nomodule}
\begin{nodecls}
  ACacheUpdate(i) == \\
    ___ \LET vWr== 
%               \begin{conj}
                 % (i = pMax) /\ (
                :A: j :in: Proc :\: \{i\} 
                    : Len(cin[j]) < Len(cin[i]) %)
%               \end{conj} \\
\\
             nRds[s : Seq(Op)] ==  
              \IF{(s = <<>>) \/ (Head(s)[2] = "Wr")} \\
                 \THEN 0 \\
                 \ELSE 1 + nRds[Tail(s)]  \FI                                   
        \IN \begin{conj}
               vrq = <<>> \\
               CacheUpdate(i) \\
               \begin{disj}
                 \begin{conj}
                    vWr\\
                    ChanOp(vdch,Head(cin[i])) \\
                    vrq' = SubSeq(Tail(vcq), 1, nRds[Tail(vcq)]) \\
                    vcq' = SubSeq(Tail(vcq), 
                                  nRds[Tail(vcq)] +1, 
                                  Len(Tail(vcq))) 
                 \end{conj}\\
                 \begin{conj}
                   ~vWr\\
                   \UNCHANGED <<vcq,vrq,vdch>> \vs{.2}
                 \end{conj}
               \end{disj} 
            \end{conj}
        \NI \\
%
    VRead == \begin{conj}
               vrq # <<>> \\
               ChanOp(vdch,Head(vrq)) \\
               vrq' = Tail(vrq) \\
               \UNCHANGED <<cc,cout,cin,ch,vcq>> \vs{.2}
             \end{conj} \\
%
  ANext == \\
          __ \begin{disj}
                :E: i:in:Proc : 
                  \begin{disj}
                   :E: d:in:Data, a:in:Addr : ARead(i,d,a) \/ AWrite(i,d,a) \\
                   AMemWrite(i) \/ ACacheUpdate(i) 
                  \end{disj}\\
                VRead  \vs{.2}
              \end{disj}\\
%
 ASpec \= \kill
  avars \> == <<vars, vcq, vrq, vdch>>\V{.2}
%
  AFair \> == \begin{conj}
             :A: i:in: Proc : \WF_{vars}(CacheUpdate(i)) 
                       /\ \WF_{vars}(MemWrite(i)) \\
                   \WF_{avars}(VRead) \vs{.2}
           \end{conj}\\
%
   ASpec \> == AInit /\ [] [ANext]_{avars} /\ AFair
\end{nodecls}
\bottombar
\end{nomodule}
\addvspace{-\baselineskip}
\caption[]{The complete cache with auxiliary variables (continued).}
\label{fig:ACCache2}
\end{figure}%
%
Corres\-pond\-ing to the four ``elementary'' actions $Read(i, d, a)$,
\ldots, $CacheUpdate(i)$ of module $CCache$, module $ACCache$ defines
the actions $ARead(i, d, a)$, \ldots, $ACacheUpdate(i)$.  Each of
these actions equals the corresponding action of $CCache$ conjoined
with (i)~an enabling condition asserting that $vrq$ is empty and
(ii)~formulas describing the new values of $vcq$, $vrq$, and $vdch$.
The next-state action of $ASpec$ is the disjunction of the $A\ldots$
actions with a new action $VRead$, which removes a read operation from
the head of $vrq$ and sends it on the $vdch$ channel.  This is the
action that adds the requisite stuttering steps to the complete cache.

Module $ACCache$ uses the \TLA+ {\bf let} construct for making
definitions local to an expression, and the construct
 \( f[x \midcolon S] \,\deq\, e(x) \)
for recursively defining a function $f$ with domain $S$.

We prove theorem $CCimpliesDB1$ of module $CacheCorrectness$ by
proving theorem $CCequivACC$, which asserts that $vcq$, $vrq$, and
$vdch$ are auxiliary variables, and theorem $ACCimpliesDB1$, which
asserts the sequential consistency of the complete cache with
auxiliary variables.

To prove $CCequivACC$, we use the propositions of
Figure~\ref{fig:auxiliary-variables}.  These propositions provide
practical rules for adding history and stuttering variables; they can be
derived from simpler results~\cite{abadi:refining}.
% try
\begin{figure}[t]

\begin{proposition}[History Variable] \label{prop:history}
If $h$ and $h'$ do not occur in $Init$, $\act{A}_{i}$, or f, and $h'$
does not occur in $g_{i}$, for all $i\in I$, then
   \[ \begin{noj}\;
        Init \; /\ \; [][:E: i :in: I : \act{A}_{i}]_{v} 
         \; \equiv \; :EE: h : 
              \begin{conj}
                 Init /\ (h = f) \\
                 [][:E: i :in: I : \act{A}_{i} /\ (h'=g_{i})]_{<<h,v>>}  
              \end{conj}   
      \end{noj} \]
\end{proposition}

\begin{proposition}[Stuttering Variable] \label{prop:stuttering}
If 
\begin{enumerate}
  \item $s$ and $s'$ do not occur in $Init$, $Inv$, $\act{A}_{i}$,
       $f$, or $g_{i}$, and $s'$ does not occur in $h$,
       for all $i\in I$.
  \item There is a partially ordered set $D$ with (unique) minimum element
        \minimal\ and well-founded partial order $\prec$ such that:
        \begin{enumerate}
          \item $Init => (f :in: D)$
          \item $Inv /\ Inv' /\ \act{A}_{i} => (g_{i} :in: D)$
          \item $Inv /\ (s :in: D) /\ (s # \minimal) => 
                       (h :in: D) /\ (h \prec s)$
        \end{enumerate}
\end{enumerate}
then\\  \(\s{1}[]Inv \;=>\;
   \begin{noj}
      (Init \; /\ \; [][:E: i :in: I : \act{A}_{i}]_{v} \\
     ___\equiv\; 
        :EE: s : \begin{conj}
          Init /\ (s = f) \\
          []\notla\left[\tla
                \begin{array}{@{\lor\;}l@{}} 
                    (s = \minimal) /\ (:E: i :in: I : 
                      (s' = g_{i}) /\ \act{A}_{i}) \\
                      (s # \minimal) /\ (s' = h) /\ (v'=v) 
              \end{array}\right]_{\langle s, v\rangle}  \\
             \WF_{<<s,v>>}((s # \minimal) /\ (s' = h) /\ (v'=v))\,\,)
        \end{conj}
   \end{noj}\)
\end{proposition}
\caption{Rules for adding history and stuttering variables.}
\label{fig:auxiliary-variables}
\end{figure}
% try
Theorem $CCequivACC$ is proved by adding to the complete cache the
history variable $vcq$, then the stuttering variable $vrq$, and then
the history variable $vdch$.  Adding an auxiliary variable $a$
to a specification $S$ means writing a formula $S^{a}$ such that 
 $\EE a \midcolon S^{a}$ 
is equivalent to $S$, so we prove $CCequivACC$ by finding two formulas
$BSpec$ and $CSpec$ such that
 \[ Spec \s{.5}
   \begin{noj3}
     \equiv & \EE vcq : CSpec & \comment{by Proposition \ref{prop:history}}\\
     \equiv & \EE vcq : \EE vrq : BSpec 
               & \comment{by Proposition \ref{prop:stuttering}}\\
     \equiv & \EE vcq : \EE vrq : \EE vdch : ASpec 
               & \comment{by Proposition \ref{prop:history}}
   \end{noj3}
 \]
The complete proof will appear
in~\cite{ladkin:gerth-web-proof}.  We next describe the proof of
$ACCimpliesDB1$.

%try

\subsection{The Proof of Theorem {\it ACCimpliesDB1}} \label{sec:proof-sketch}

It is argued elsewhere that the way to avoid mistakes in proofs is to
structure them hierarchically~\cite{lamport:howtoprove}.  This is
especially true for correctness proofs of computer systems, where the
social process for detecting errors is largely missing.  A
hierarchical proof is a sequence of statements and their proofs, each
of which is either a sequence of statements or else an ordinary
paragraph-style proof.  A deeper hierarchy implies a more rigorous
proof.  One can obtain any desired degree of rigor---from informal,
intuitive reasoning to a completely rigorous, formal proof---by
choosing the depth appropriately.  We describe our proof of theorem
$ACCimpliesDB1$ of module $CacheCorrectness$ by showing how its
hierarchical structure is obtained.


\subsubsection{The High Level Outline}

To prove  theorem $ACCimpliesDB1$, we must prove 
 \[ ACC(cc, cin, cout, vcq, vrq, vdch).ASpec => DB1.Spec \]
We now drop the prefixes 
 ``$ACC(cc, cin, cout, vcq, vrq, vdch).$''
and ``$DB1.$'', so the theorem to be proved is 
 $ASpec => Spec$.\footnote{The only ambiguous name is $Spec$, which
will mean $DB1.Spec$ rather than the formula of the same name imported
by $ACCache$ from module $CCache$.} As we observed in
Section~\ref{sec:ACCache}, this theorem is equivalent to
 \[ ASpec => \EE dch, q, mem : QSpec(dch, q) /\ SDB(dch).ISpec(mem)
 \]
which we prove by proving
\begin{equation} \label{eq:ASpecImpliesConj}
  ASpec => \O{QSpec(dch, q)} /\ \O{SDB(dch).ISpec(mem)}
\end{equation}
where \O{F} is obtained by substituting \O{dch}, \O{q},  \O{mem}
for $dch$, $q$, $mem$ in formula $F$, and
 \[ \begin{noj3}
       \O{q} & \;\deq\;  & [i \in Proc |-> Proj(i, vrq :o: vcq) :o: cout[i]\,]\\
     \O{mem} & \;\deq\; & cc[pMax]\\
     \O{dch} & \;\deq\; & vdch
    \end{noj3}
 \]

When reasoning in a formal logic, the structure of the formula
indicates the structure of the proof.  Propositional logic tells us
that to prove (\ref{eq:ASpecImpliesConj}), we must prove
 $ASpec => \O{QSpec}$ and $ASpec => \O{SDB(dch).ISpec(mem)}$.  
Both of these formulas have the form
 \[
  AInit /\ [][ANext]_{avars} /\ AFair
   \; => \;
  \O{Init} /\ [][\O{Next}]_{\O{v}} /\ \O{L}
 \]
where $L$ is a fairness condition. (For
\O{SDB(dch).ISpec(mem)}, formula $\O{L}$ is just \TRUE.)
The standard TLA proof of such a formula has the following structure,
where $Inv$ is a suitable predicate called the {\em invariant}.
% (This hierarchical proof style is explained in
% \cite{lamport:howtoprove}.)
\pfshortnumbers{99} 
\begin{proof}
\step{1}{$AInit /\ [][ANext]_{avars} => []Inv$}
\begin{proof}
 \step{1.1}{$AInit => Inv$}
 \step{1.2}{$Inv /\ [ANext]_{avars} => Inv'$}
 \qedstep
 \begin{proof}
   \pf\ \stepref{1.1}, \stepref{1.2}, and rule INV1 of \cite{lamport:newtla}.
 \end{proof}
\end{proof}

\step{2}{$AInit => \O{Init}$}

\step{3}{$[]Inv /\ [][ANext]_{avars} => [][\O{Next}]_{\O{v}}$}
\begin{proof}
  \step{3.1}{$[Inv /\ Inv' /\ ANext]_{avars} => [\O{Next}]_{\O{v}}$}
  \qedstep
  \begin{proof}
    \pf\ Rules TLA2 and INV2 of \cite{lamport:newtla}.
  \end{proof}
\end{proof}

\step{4}{$[]Inv /\ [][ANext]_{avars} /\ AFair =>  \O{L}$}
\qedstep
\begin{proof}
\pf\ \stepref{1}--\stepref{4} and propositional logic.
\end{proof}
\end{proof}
\noindent
We
combine the proofs for 
 $ASpec => \O{QSpec}$ and $ASpec => \O{SDB(dch).Spec}$,
%
%and dropping the ``$SDB(dch).$'' from $SDB(dch).INext(mem)$,
%
using the fact that barring distributes over all the \TLA+ operators
of Figure~\ref{fig:TLA+operators} except $\WF$, $\SF$, and {\sc
Enabled}, to get the following structure for the proof of
(\ref{eq:ASpecImpliesConj}).  (Remember that \O{dch} equals $vdch$.)
%
\begin{proof}
\step{1}{$AInit /\ [][ANext]_{avars} => []Inv$}
\begin{proof}
 \step{1.1}{$AInit => Inv$}
 \step{1.2}{$Inv /\ [ANext]_{avars} => Inv'$}
 \qedstep
 \begin{proof}
   \pf\ \stepref{1.1}, \stepref{1.2}, and rule INV1.
 \end{proof}
\end{proof}

\step{2}{$AInit => (:A: i :in: Proc : \O{q}[i] = << >>) 
                       /\ (\O{mem} :in: InitDB)$}

\step{3}{$[]Inv /\ [][ANext]_{avars} => \\
           \s{1}\begin{conj}
              [][:E: i :in: Proc : Enq(i, vdch, \O{q}) \/ Deq(i, vdch, \O{q})
                     ]_{<<ch, vdch, \O{q}>>} \\
              [][SDB(vdch).INext(\O{mem})]_{<<\O{mem},\, vdch>>}
           \end{conj}$}
\begin{proof}
  \step{3.1}{$[Inv /\ Inv' /\ ANext]_{avars} => \\ 
     \s{1}\begin{conj}
             [:E: i :in: Proc : Enq(i, vdch, \O{q}) \/ Deq(i, vdch, \O{q})
                     ]_{<<ch, vdch, \O{q}>>} \\
             [SDB(vdch).INext(\O{mem})]_{<<\O{mem},\, vdch>>}
          \end{conj}$}
  \qedstep
  \begin{proof}
    \pf\ Rules TLA2 and INV2 of \cite{lamport:newtla}.
  \end{proof}
\end{proof}

\step{4}{$[]Inv /\ [][ANext]_{avars} /\ AFair => \\ 
  \s{1} :A: i :in: Proc : \O{\WF_{<<ch, dch, q>>}(Deq(i, dch, q))}
$}
\qedstep
\begin{proof}
\pf\ \stepref{1}--\stepref{4} and propositional logic.
\end{proof}
\end{proof}
 \noindent
Step~2 asserts that the initial state of the complete cache machine
implements a correct initial state of the sequential consistency
machine.  Its proof is easy.  We now consider the other steps that
need to be proved: the two substeps of step~1, step~3.1, and step~4.

\subsubsection{Step 1: The Invariance Proof}

As in all assertional reasoning, finding a suitable invariant $Inv$ is the
key to the proof.  One first guesses a definition of $Inv$ and then
iteratively refines it---usually making it stronger---until steps 1.2
and 3.1 are both provable.  With experience, one gets fairly good at
guessing the invariant, and few iterations are needed.

Our predicate $Inv$ is the conjunction of five assertions with the
following intuitive meanings.
\begin{enumerate}
\item Variables have the type of values we expect them to.
   (Such a ``type correctness'' assertion is a standard part of an invariant.)

\item For every processor $i$, the queue $cin[i]$ is a suffix of
$cin[pMax]$, and $cc[i]$ equals the memory obtained by applying the
first $Len(cin[pMax]) - Len(cin[i])$ operations in $cin[pMax]$ to
$cc[pMax]$.

\item The sequence of writes in $vcq$ equals $cin[pMax]$.

\item For any read operation $<<i, "Rd", d, a>>$ in 
$vrq :o: vcq$, if $\sigma$ is the sequence of write operations that
precede it in $vrq :o: vcq$, and $m$ is the memory obtained by
updating $cc[pMax]$ with the sequence $\sigma$ of writes, then 
$d= m[a]$.

\item There are no reads by processor $i$ in $vcq$ after the
$(Len(cin[pMax]) - Len(cin[i])+1)${\em st\/} write.
\end{enumerate}
Conjunct 4 is the key to why the algorithm works.  It states that
$vrq\o vcq$ is a correct sequence of operations for a serial memory
whose contents are \O{mem} (which equals $cc[pMax]$).  This sequence
is the serialization of all operations that have not yet been
performed to \O{mem} and are not still in the $cout$ queues.  Thus,
the serialization order of writes is determined by the order in which 
$MemWrite$ events move writes from the $cout$ queues to the $cin$
queues.


The precise definition of $Inv$ is in
Figure~\ref{fig:ccache-inv}.
%
\begin{figure}
\(\begin{noj}
   WriteSel(s) == \LET test(e) == e[2] = "Wr"
                  \IN SelectSeq(s, test) \NI\\
%
   ApplyOps[s : Seq(Op), m : [Addr -> Data]] == \\
      __\IF{s= <<>>}\\
        \THEN m \\
        \ELSE ApplyOps[\,Tail(s), \,[m \EXCEPT ![Head(s)[4]] = Head(s)[3]]\,]
       \FI \\
%
   InsertPos[k : Nat,  s : Seq(Op)] == \\
   __ \IF {(s = <<>>) \/ ((k=0) /\ (Head(s)[2] = "Wr"))} \\
             \THEN 1 
             \ELSE \IF {Head(s)[2] = "Rd"} \\
                      \THEN  1+InsertPos[k, Tail(s)] \\
                      \ELSE  1+ InsertPos[k-1, Tail(s)] 
          \FI      \FI
\\
   Inv == \\
   __\begin{conj*}
 \begin{conj}
       cc :in: [Proc -> [Addr -> Data]] \\
       cin :in:  [Proc ->  Seq(Proc :X: \{"Wr"\} :X: Data :X: Addr)]\\
       \begin{conj}
           cout :in: [Proc ->  Seq(Proc :X: \{"Wr"\} :X: Data :X: Addr)]\\
           :A: i :in: Proc : :A: j :in: 1\dd Len(cout[i]):
             cout[i][j][1] = i 
       \end{conj}\\
       vcq :in:  \{ s :in: Seq(Op) : 
                         (s#<<>>) => (Head(s)[2] = "Wr")\,\} \\
       vrq :in:  Seq(Proc :X: \{"Rd"\} :X: Data :X: Addr)
     \end{conj} \\
%     TInv\\
%
     \begin{noj}
     :A: i :in: Proc : \\
     __\begin{conj}
          cin[i] = SubSeq(\begin{noj}
                            cin[pMax],                        \,
                            1 + Len(cin[pMax]) - Len(cin[i]), \, \\
                            Len(cin[pMax])) \\
                          \end{noj} \\
          cc[i] = ApplyOps[\begin{noj}
                          SubSeq(cin[pMax],1,\\
                           Len(cin[pMax]) - Len(cin[i])), \, 
                          cc[pMax]\,]
                          \end{noj}
       \end{conj} 
     \end{noj}\\
%
     WriteSel(vcq) = cin[pMax]\\
%
     \LET s == vrq :o: vcq
     \IN :A: n :in: 1\dd Len(s) : \\
          __(s[n][2] = "Rd") => \\
          ___(s[n][3] = 
               ApplyOps[\begin{noj}
                         WriteSel(SubSeq(s, 1, n-1)), \\
                         cc[pMax]\,]\,[s[n][4]]\,)\,
                        \end{noj}
      \NI\\
%
      \begin{noj}
        :A: i :in: Proc: \\
          __:A: j :in: InsertPos[Len(cin[pMax])-Len(cin[i]),\,vcq] 
             \dd Len(vcq) : \\
          ____ (vcq[j][1] = i) => (vcq[j][2] = "Wr")
      \end{noj}
   \end{conj*}
  \end{noj}\)
\caption[]{The invariant for the correctness proof of the complete cache.}
\label{fig:ccache-inv}
\end{figure}%
%
It uses the following operators: $WriteSel(s)$ is the subsequence of write
operations in $s$, $ApplyOps[s,m]$ is the memory contents obtained by
applying the sequence $s$ of writes to a memory with contents $m$, and
$InsertPos[k,s]$ is the index of the $(k+1)${\em st\/} write in $s$,
or equals $Len(s)+1$ if there are at most $k$ writes in $s$.
%

Having defined $Inv$, we can now continue our proof.  Step 1.1 ($AInit
=> Inv$) is straightforward.  The structure of $Inv$ 
%as  $Inv.1 /\ \ldots /\ Inv.5$ 
leads us to prove 1.2 as follows:
\begin{proof}
\nostep{1}
\begin{noproof}
\nostep{1.1}
\step{1.2}{$Inv /\ [ANext]_{avars} => Inv'$}
\begin{proof}
\step{1.2.1}{$Inv /\ [ANext]_{avars} => Inv.1'$}
\s{1}$\vdots$
\nostep{1.2.2}
\nostep{1.2.3}
\nostep{1.2.4}
\step{1.2.5}{$Inv /\ [ANext]_{avars} => Inv.5'$}
\qedstep
\begin{proof}
\pf\ \stepref{1.2.1}--\stepref{1.2.5}, 
 since $Inv$ equals $Inv.1 /\ \ldots /\ Inv.5$.
\end{proof}
\end{proof}
\end{noproof}
\end{proof}
\noindent Next, the structure of $[ANext]_{avars}$ tells us how to
structure the proofs of 1.2.1--1.2.5.  For example, the proof of 1.2.4 is:
\begin{proof}
\nostep{1}
\begin{noproof}
\nostep{1.1}
\nostep{1.2}
\begin{noproof}
\nostep{1.2.1}
\nostep{1.2.2}
\nostep{1.2.3}
\step{1.2.4}{$Inv /\ [ANext]_{avars} => Inv.4'$}
\begin{proof}
\step{1.2.4.1}{%
$Inv /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ ARead(i,d,a) \\
 \s{1}\;=>\; Inv.4'$}
%
\step{1.2.4.2}{%
$Inv /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ AWrite(i,d,a) \\
 \s{1 }\;=>\; Inv.4'$}
%
\step{1.2.4.3}{%
$Inv /\ (i\in Proc)  /\ AMemWrite(i) \;=>\;
Inv.4'$}
%
\step{1.2.4.4}{%
$Inv /\ (i\in Proc) /\ ACacheUpdate(i) \;=>\;
Inv.4'$}
%
\step{1.2.4.5}{%
$Inv /\ VRead \;=>\;
Inv.4'$}
%
\step{1.2.4.6}{%
$Inv /\ (avars'=avars) \;=>\;
Inv.4'$}
\qedstep
\begin{proof}
\pf\ \stepref{1.2.4.1}--\stepref{1.2.4.6}, the definition of
$ANext$, and simple predicate logic, since $[A]_{v}\,\deq\,A \/ (v'=v)$,
for any $A$ and $v$.
\end{proof}
\end{proof}
\end{noproof}
\end{noproof}
\end{proof}
\noindent The proof of all steps 1.2.$*$.6 are trivial, since the
tuple $avars$ contains all the variables that appear in $Inv$.  The
other 25 steps are the standard ones for an invariance proof.
They show that, starting in a state with the invariant true, 
executing one step of the algorithm produces a state in which each
conjunct of the invariant is true.  The quadratic number of
steps---the number of disjuncts in the next-state relation times the
number of conjuncts of the invariant---is characteristic of approaches
based on invariance, such as the Owicki-Gries
method~\cite{owicki:axiomatic}.


Some of the 25 remaining steps in the proof of 1.2 are trivial---for
example, 1.2.3.2 holds because $AWrite(i,d,a)$ leaves $vcq$ and $cin$
unchanged, which implies that $pMax$ is unchanged, and thus $Inv.3$
remains true.  Some steps are routine---for example, the substeps of
1.2.1 require the kind of simple reasoning performed by a type
checker.  Some steps go to the heart of why the algorithm works.  We
consider one such step: 1.2.4.1.  This step asserts that an $ARead$
event leaves the crucial conjunct $Inv.4$ true.  Its proof essentially
shows that read operations are serializable.  Here is an informal
proof, based on the informal statement of $Inv$ given above:
\begin{proof}
\nostep{1}
\begin{noproof}
\nostep{1.1}
\nostep{1.2}
\begin{noproof}
\nostep{1.2.1}
\nostep{1.2.2}
\nostep{1.2.3}
\nostep{1.2.4}
\begin{noproof}
\step{1.2.4.1}{%
$Inv /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ ARead(i,d,a) \\
 \s{1}\;=>\; Inv.4'$}
\begin{proof}
\pf\ $ARead(i,d,a)$ implies $vrq$ is empty, so an $ARead(i,d,a)$ step
inserts a read of $d$ from address $a$ just before the
$(Len(cin[pMax])-Len(cin[i])+1)${\em st\/} write in $vcq$, or at the
end if $Len(cin[i])$ equals zero, and hence after the first
$Len(cin[pMax])-Len(cin[i])$ writes.  Since $Inv.4$ holds before the
step, it holds after the step if $d=m[a]$, where $m$ is the memory
obtained by updating $cc[pMax]$ with the first
$Len(cin[pMax])-Len(cin[i])$ writes in $vcq$.  By $Inv.2$, $m$ equals
$cc[i]$.  Since $ARead(i,d,a)$ implies $Read(i,d,a)$, which implies
$d=cc[i][a]$, we deduce $d=m[a]$.
\end{proof}
\end{noproof}
\end{noproof}
\end{noproof}
\end{proof}
 \noindent 
This informal reasoning is useful for understanding the algorithm, but
it is not reliable.  An off-by-one error in where the read is inserted
could easily pass unnoticed.  The proof implicitly assumes that $cc$
and $cin$ are left unchanged by an $ARead$ step, and incorrect
assumptions are hard to detect if they are not made explicit.  Step
1.2.4.1 is a precisely defined mathematical formula; it can be proved
by rigorous mathematical reasoning.  The hierarchical proof structure
allows such proofs to be carried down to as fine a level of detail as
necessary to reach any desired degree of reliability.

\subsubsection{Step 3.1: Step Simulation}

The form of step 3.1 immediately leads to this proof outline:
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\begin{noproof}
\step{3.1}{$[Inv /\ Inv' /\ ANext]_{avars} => \\ 
     \s{1}\begin{conj}
             [:E: i :in: Proc : Enq(i, vdch, \O{q}) \/ Deq(i, vdch, \O{q})
                     ]_{<<ch, vdch, \O{q}>>} \\
             [SDB(vdch).INext(\O{mem})]_{<<\O{mem},\, vdch>>}
          \end{conj}$}
\begin{proof}
 \step{3.1.1}{$[Inv /\ Inv' /\ ANext]_{avars} => \\
              \s{1}[:E: i :in: Proc : Enq(i, vdch, \O{q}) \/ Deq(i, vdch, \O{q})
                     ]_{<<ch, vdch, \O{q}>>}$}
 \step{3.1.2}{$[Inv /\ Inv' /\ ANext]_{avars} =>
             [SDB(vdch).INext(\O{mem})]_{<<\O{mem},\, vdch>>}$}
 \qedstep
 \begin{proof}
   \pf\ \stepref{3.1.1} and \stepref{3.1.2}.
 \end{proof}
\end{proof}
\end{noproof}
\end{proof}
\noindent The structure of the left-hand side of these implications
leads to the same sort of decomposition as for steps 1.2.1--1.2.5.
This would lead to steps such as 
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\begin{noproof}
\nostep{3.1}
\begin{noproof}
\nostep{3.1.1}
\begin{noproof}
\step{3.1.1.1}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ ARead(i,d,a) \\
    \s{1}\;=>\; [:E: i :in: Proc : Enq(i, vdch, \O{q}) \/ Deq(i, vdch, \O{q})
                        ]_{<<ch, vdch, \O{q}>>}$}
\end{noproof}
\end{noproof}
\end{noproof}
\end{proof}
\noindent
However, we actually prove the stronger result that the left-hand
side implies $Enq(i, vdch, \O{q})$.  The decomposition with
the stronger results is:
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\begin{noproof}
\nostep{3.1}
\begin{noproof}
\step{3.1.1}{$[Inv /\ Inv' /\ ANext]_{avars} => \\
              \s{1}[:E: i :in: Proc : Enq(i, vdch, \O{q}) \/ Deq(i, vdch, \O{q})
                     ]_{<<ch, vdch, \O{q}>>}$}
   \begin{proof}
   \step{3.1.1.1}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ ARead(i,d,a) \\
    \s{1}\;=>\; Enq(i, vdch, \O{q}) $}
   %
   \step{3.1.1.2}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ AWrite(i,d,a) \\
    \s{1}\;=>\; Enq(i, vdch, \O{q})$}
   %
   \step{3.1.1.3}{%
   $Inv /\ Inv' /\ (i\in Proc)  /\ AMemWrite(i) \\ \s{1} \;=>\; 
      \UNCHANGED <<ch, vdch, \O{q}>>$}
   %
   \step{3.1.1.4}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ ACacheUpdate(i) \\ \s{1} \;=>\; 
   Deq(i, vdch, \O{q}) \/ \UNCHANGED <<ch, vdch, \O{q}>>$}
   %
   \step{3.1.1.5}{%
   $Inv /\ Inv' /\ VRead \;=>\; Deq(i, vdch, \O{q})$}
   %
   \step{3.1.1.6}{%
   $(avars'=avars) \;=>\; \UNCHANGED <<ch, vdch, \O{q}>>$}
   \qedstep
      \begin{proof}
      \pf\ \stepref{3.1.1.1}--\stepref{3.1.1.6}, the definitions of
      $ANext$ and $[\ldots]_{avars}$, and simple predicate logic.
      \end{proof}
  \end{proof}
\step{3.1.2}{$[Inv /\ Inv' /\ ANext]_{avars} =>
             [SDB(vdch).INext(\O{mem})]_{<<\O{mem},\, vdch>>}$}
   \begin{proof}
   \step{3.1.2.1}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ ARead(i,d,a) \\
    \s{1}\;=>\; \UNCHANGED <<\O{mem},\, vdch>> $}
   %
   \step{3.1.2.2}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ AWrite(i,d,a) \\
    \s{1 }\;=>\; \UNCHANGED <<\O{mem},\, vdch>>$}
   %
   \step{3.1.2.3}{%
   $Inv /\ Inv' /\ (i\in Proc)  /\ AMemWrite(i) \\ \s{1} \;=>\; 
      \UNCHANGED <<\O{mem},\, vdch>>$}
   %
   \step{3.1.2.4}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ ACacheUpdate(i) \\ \s{1} \;=>\; 
    SDB(vdch).INext(\O{mem}) \/ \UNCHANGED <<\O{mem},\, vdch>>$}
   %
   \step{3.1.2.5}{%
   $Inv /\ Inv' /\ VRead  \;=>\; SDB(vdch).INext(\O{mem}) $}
   %
   \step{3.1.2.6}{%
   $(avars'=avars) \;=>\; \UNCHANGED <<\O{mem},\, vdch>>$}
   \qedstep
      \begin{proof}
      \pf\ \stepref{3.1.2.1}--\stepref{3.1.2.6}, the definitions of
      $ANext$ and $[\ldots]_{avars}$, and simple predicate logic.
      \end{proof}
  \end{proof}
\end{noproof}
\end{noproof}
\end{proof} 
 \noindent 
The proofs of steps 3.1.1.6 and 3.1.2.6 are trivial, since the tuple
$avars$ contains all the variables that appear in our formulas.  To
understand the other ten steps, remember that the state machine
specifying sequential consistency is the composition of two machines:
a queue machine with variables $ch$, $dch$, and $q$ that moves
operations into and out of the queues, and a serial database machine
with variables $dch$ and $mem$.  Steps 3.1.1.1--3.1.1.5 assert that
every event of the complete cache either simulates a step of the queue
machine or else leaves that machine's variables unchanged.  Steps
3.1.2.1--3.1.2.5 make the analogous assertions for the serial database
machine.  These steps correspond to the step simulation part of a
traditional proof that one state machine simulates
another~\cite{lam:protocol,lynch:distributed}.  As usual, some of the
proofs are trivial and some give further insight into the algorithm.
An example of the latter is step 3.1.1.1, which asserts that an
$ARead$ event simulates a queue machine $Enq$ event.  The structure of
$Enq(i, vdch, \O{q})$ suggests the following proof outline.
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\begin{noproof}
\nostep{3.1}
\begin{noproof}
\nostep{3.1.1}
\begin{noproof}
\step{3.1.1.1}{%
   $Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) /\ (a:in:Addr) /\ ARead(i,d,a) \\
    \s{1}\;=>\; Enq(i, vdch, \O{q}) $}
\begin{proof}
\assume{$Inv /\ Inv' /\ (i\in Proc) /\ (d:in:Data) 
         /\ (a:in:Addr) /\ ARead(i,d,a)$}
\prove{$Enq(i, vdch, \O{q})$}
\step{3.1.1.1.1}{$ChanOp(ch[i], <<i, \q{Rd}, d, a >>)$}
\step{3.1.1.1.2}{$\O{q}[i]' = \O{q}[i] :o: << <<i, \q{Rd}, d, a >> >>$}
\step{3.1.1.1.3}{$\UNCHANGED vdch$}
\step{3.1.1.1.4}{$\A j\in Proc :\: \{i\} : \UNCHANGED <<\O{q}[j], ch[j]>>$}
\qedstep
 \begin{proof}
  \pf\ \stepref{3.1.1.1.1}--\stepref{3.1.1.1.4}, the definitions of $POp$
  and $Enq$, 
  and predicate logic.
 \end{proof}
\end{proof}
\end{noproof}
\end{noproof}
\end{noproof}
\end{proof}
 \noindent
Here is an informal proof of 3.1.1.1.2.
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\begin{noproof}
\nostep{3.1}
\begin{noproof}
\nostep{3.1.1}
\begin{noproof}
\nostep{3.1.1.1}
\begin{noproof}
\nostep{3.1.1.1.1}
\step{3.1.1.1.2}{$\O{q}[i]' = \O{q}[i] :o: << <<i, \q{Rd}, d, a >> >>$}
\begin{proof}
\pf\ An $ARead(i,d,a)$ event inserts $<<i, \q{Rd}, d, a >>$ into
either $vrq$ or $vcq$, and hence into $\O{q}[i]$.  We just have to
show that it inserts the operation at the end of $\O{q}[i]$.  The
operation is inserted into $vrq \o vcq$ just before the
$(Len(cin[pMax])-Len(cin[i])+1)${\em st\/} write in $vcq$, or at the
end if $Len(cin[i])$ equals zero.  By $Inv.2$ and $Inv.3$, all the
writes that follow it in $vrq\o vcq$ are in $cin[i]$.  Since
$ARead(i,d,a)$ implies $Read(i,d,a)$, which implies there are no
writes by $i$ in $cin[i]$, no writes by $i$ follow the newly inserted
operation in $vrq\o vcq$.  By $Inv.5$, no reads by $i$ follow it.  By
definition of $\O{q}[i]$, this implies that the operation is inserted
at the end of~$\O{q}[i]$.
\end{proof}
\end{noproof}
\end{noproof}
\end{noproof}
\end{noproof}
\end{proof}

%try
\subsubsection{Step 4: Fairness}

To prove step 4, we must prove 
 $\O{\WF_{<<ch, dch, q>>}(Deq(i, dch, q))}$ 
for each processor $i$.  This suggests using rule WF2
of~\cite{lamport:newtla}.  With that rule, one infers $\O{\WF_{w}(B)}$
from $\WF_{v}(A)$, where $A$ is the action that implements \O{B}.
However, as we saw in the proof of 3.1.1, \O{Deq(i, dch, q)} is
implemented by the two separate actions $ACacheUpdate(i)$ and $VRead$.
This gives us two ways to prove step~4: (i)~prove that the
complete cache specification implies weak fairness of
 $ACacheUpdate(i) \/ VRead$
and apply WF2, or (ii)~expand the definition of $\WF$ in the
conclusion and apply temporal logic reasoning directly.
Either one works; we use the second.  


The formula $\WF_{v}(A)$ is defined to equal $[]<>~\ENABLED <<A>>_{v}
\/ []<><<A>>_{v}$, for any action $A$, where 
 $<<A>>_{v}$ is defined to equal $A /\ (v'#v)$ 
and the predicate $\ENABLED <<A>>_{v}$ asserts that there is some
possible step starting in the current state that satisfies
$<<A>>_{v}$.

Proofs of fairness are typically by contradiction, deducing $F => G$
from $F /\ ~G => G$.  Expanding the definition of $\WF$ leads to the
following proof.
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\step{4}{$[]Inv /\ [][ANext]_{avars} /\ AFair => \\ 
  \s{1} :A: i :in: Proc : \O{\WF_{<<ch, dch, q>>}(Deq(i, dch, q))}$}
\begin{proof}
 \pf\ By predicate logic, it suffices to:
 \assume{$i \in Proc$}
 \prove{$[]Inv /\ [][ANext]_{avars} /\ AFair 
          => \O{\WF_{<<ch, dch, q>>}(Deq(i, dch, q))}$}
 \pflet{$B == Deq(i, dch, q)$\\
        $w == <<ch, dch, q>>$}
 \step{4.1}{$[]Inv /\ [][ANext]_{avars} /\ AFair 
              /\ []\O{\ENABLED <<B>>_{w}} /\ [][~\O{B}]_{\O{w}}
              \\ \s{1} => []<><<\O{B}>>_{\O{w}} $}
 \step{4.2}{$ []Inv /\ [][ANext]_{avars} /\ AFair 
              /\ <>[]\O{\ENABLED <<B>>_{w}} /\ <>[][~\O{B}]_{\O{w}}
              \\ \s{1} => []<><<\O{B}>>_{\O{w}}$}
 \begin{proof}
   \step{4.2.1}{$AFair \equiv []AFair$}
   \begin{proof}
     \pf\ Definition of $AFair$,
     since $[]\WF \equiv \WF$ and
     $[]$ distributes over $\land$ and $\forall$.
   \end{proof}
   \step{4.2.2}{$[]Inv /\ [][ANext]_{avars} /\ [] AFair 
              /\ []\O{\ENABLED <<B>>_{w}} /\ [][~\O{B}]_{\O{w}}
              \\ \s{1} => []<><<\O{B}>>_{\O{w}} $}
   \begin{proof}
     \pf\ \stepref{4.1} and \stepref{4.2.1}.
   \end{proof}
   \step{4.2.3}{$<>[]Inv /\ <>[][ANext]_{avars} /\ <>[] AFair 
              /\ <>[]\O{\ENABLED <<B>>_{w}} \\ 
              \s{1} /\ <>[][~\O{B}]_{\O{w}}
               \; => \;  <>[]<><<\O{B}>>_{\O{w}}$}
   \begin{proof}
    \pf\ 4.2.2, since $F_{1} => F_{2}$ implies $<>F_{1} => <>F_{2}$ and
     $<>([]F_{1} /\ \ldots /\ []F_{n}) \equiv 
          (<>[]F_{1} /\ \ldots /\ <>[]F_{n})$, for any formulas $F_{i}$.
   \end{proof}
   \qedstep
   \begin{proof}
     \pf\ 4.2.3, since $[]F => <>[]F$ and $<>[]<>F \equiv []<>F$,  for
     any $F$.
   \end{proof}
 \end{proof}
 \qedstep
 \begin{proof}
  \pf\ 4.2 and propositional logic, since 
  $\O{\WF_{<<ch, dch, q>>}(Deq(i, dch, q))}$
  is defined to equal 
 $\O{[]<>~\ENABLED <<B>>_{w}
                    \/ []<> <<B>>_{w}}$, which is equivalent to
  $[]<>~\O{\ENABLED <<B>>_{w}}
                    \/ []<> <<\O{B}>>_{\O{w}}$ because
  barring distributes over all operators except $\WF$ and $\ENABLED$,
  and 
    \[ \begin{noj}
         ~([]<>~\O{\ENABLED <<B>>_{w}}
                    \/ []<> <<\O{B}>>_{\O{w}}) \\
         \s{1}\begin{noj2}
           \equiv\; <>[]\O{\ENABLED <<B>>_{w}} /\ <>[]~<<\O{B}>>_{\O{w}}
                   \s{1}   & \tlacomment{[$<> \,\deq\, ~[]~$]} \\
           \equiv\; <>[]\O{\ENABLED <<B>>_{w}} /\ <>[][~\O{B}]_{\O{w}}
                      & \tlacomment{[$~<<A>>_{v}\equiv [~A]_{v}$,
                                     for any $A$ and $v$]}
          \end{noj2}
       \end{noj}
    \]
 so 4.2 shows that 
  $[]Inv /\ [][ANext]_{avars} /\ AFair /\ ~\O{\WF_{\ldots}(\ldots)}$
implies $\O{\WF_{\ldots}(\ldots)}$.
 \end{proof}
\end{proof}
\end{proof}
 \noindent
The proof of 4.1 has the following structure.
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\nostep{4}
\begin{noproof}
\step{4.1}{$[]Inv /\ [][ANext]_{avars} /\ AFair 
              /\ []\O{\ENABLED <<B>>_{w}} /\ [][~\O{B}]_{\O{w}}
              \\ \s{1} => []<><<\O{B}>>_{\O{w}} $}
\begin{proof}
 \pflet{$     \begin{noj3} 
             AA & \deq & []Inv /\ [][ANext]_{avars} /\ AFair
                      /\ []\O{\ENABLED <<B>>_{w}} \\
               & & \s{1} \mbox{} 
                  /\ [][~\O{B}]_{\O{w}}\\
           Qrd & \deq & (vrq # <<>>) /\ (Head(vrq)[1]=i) \\
            Qwr & \deq & (vrq = <<>>) /\ (Head(vcq)[1]=i)
          \end{noj3}$}
 \step{4.1.1}{$AA => <>(Qrd \/ Qwr)$}
 \step{4.1.2}{$AA /\ Qrd  => []<><<\O{B}>>_{\O{w}}$}
 \step{4.1.3}{$AA /\ Qwr => []<><<\O{B}>>_{\O{w}}$}
 \qedstep
 \begin{proof}
  \pf\ \stepref{4.1.1}--\stepref{4.1.3} and simple temporal reasoning,
  since $AA \equiv []AA$.
 \end{proof}
 \end{proof}
\end{noproof}
\end{proof}
 \noindent
Steps 4.1.1 and 4.1.2 are proved informally as follows.
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\nostep{4}
\begin{noproof}
\nostep{4.1}
\begin{noproof}
 \step{4.1.1}{$AA => <>(Qrd \/ Qwr)$}
 \begin{proof}
   \step{4.1.1.1}{$\O{\ENABLED <<B>>_{w}} \equiv
                     (cout[i] # << >>) \/ 
                     (Proj(i, vrq :o: vcq) # << >>)$}
  \begin{proof}
   \pf\   $\ENABLED <<B>>_{w}$ equals $q[i] # << >>$, and
   $\O{q}[i]$ is defined to equal $Proj(i, vrq :o: vcq) \o cout[i]$.
  \end{proof}
  \step{4.1.1.2}{$AA /\ (cout[i] # << >>) => <> (Proj(i, vrq :o: vcq) # << >>)$}
    \begin{proof}
    \pf\ Weak fairness of $MemWrite(i)$ implies that if $cout[i]$ is non\-empty,
    then its head (which by $Inv.1$ is an operation of processor $i$)
    must eventually be removed and appended to $vcq$.
    \end{proof}

  \step{4.1.1.3}{$AA /\ (Proj(i, vrq :o: vcq) # << >>) => <>(Qrd \/ Qwr)$}
    \begin{proof}
    \pf\ Weak fairness of $VRead$ implies that any operation in $vrq$
    (which by $Inv.1$ must be a read) eventually reaches the head of
    $vrq$ and is then removed from $vrq$.
     By $Inv.3$, a write is in $vcq$ iff it is in $cin[pMax]$.
     Weak fairness of the $CacheUpdate(j)$ actions and of $VRead$
     therefore implies that any write in $vcq$ eventually reaches
     the head of $vcq$ and is then removed from $vcq$.  Therefore,
     a read by processor $i$ in $vrq \o vcq$ eventually
    reaches $vrq$ and thus eventually reaches the head of $vrq$, making 
    $Qrd$ true.
    A write by $i$ in $vrq \o vcq$ is in $vcq$ (by $Inv.1)$ and
    eventually reaches the head of $vcq$, making $Qwr$ true.
    \end{proof}                 
  \qedstep
  \begin{proof}
  \pf\ \stepref{4.1.1.1}--\stepref{4.1.1.3} and temporal logic reasoning,
  since $AA$ implies $\O{\ENABLED <<B>>_{w}}$.
  \end{proof}
 \end{proof}
\end{noproof}
\end{noproof}
\end{proof}
%
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\nostep{4}
\begin{noproof}
\nostep{4.1}
\begin{noproof}
 \nostep{4.1.1}
 \step{4.1.2}{$AA /\ Qrd  => []<><<\O{B}>>_{\O{w}}$}
 \begin{proof}
    \step{4.1.2.1}{$AA /\ Qrd  => []Qrd$}
    \begin{proof}
     \pf\ $Qrd$ can be made false only by removing a read by processor
     $i$ from the head of $vrq$, which  is a nonstuttering $\O{B}$ step, 
    and the conjunct $[][~\O{B}]_{\O{w}}$ of $AA$ asserts that such a step 
    never occurs.
    \end{proof}
    \step{4.1.2.2}{$AA /\ []Qrd => []<><<\O{B}>>_{\O{w}}$}
    \begin{proof}
     \pf\ $Qrd$ implies that $VRead$ is enabled and that a $VRead$ step
     is a $<<\O{B}>>_{\O{w}}$ step.  Thus, $[]Qrd$ and weak fairness
     of $VRead$ imply that infinitely many such steps occur, 
     proving $[]<><<\O{B}>>_{\O{w}}$.
    \end{proof}
    \qedstep
    \begin{proof}
     \pf\ \stepref{4.1.2.1} and \stepref{4.1.2.2}.
    \end{proof}
 \end{proof}
\end{noproof}
\end{noproof}
\end{proof}
%
 \noindent 
The proof of 4.1.3 has the following outline.  Informal proofs of the
substeps are similar to the ones above and are left to the reader.
%
\begin{proof}
\nostep{1}
\nostep{2}
\nostep{3}
\nostep{4}
\begin{noproof}
\nostep{4.1}
\begin{noproof}
 \nostep{4.1.1}
 \nostep{4.1.2}
 \step{4.1.3}{$AA /\ Qwr  => []<><<\O{B}>>_{\O{w}}$}
 \begin{proof}
    \pflet{$Qun == \A j \in Proc :\: \{pMax\} : Len(cin[j]) < Len(cin[pMax])$}
    \step{4.1.3.1}{$AA /\ Qwr  => <>(Qun /\ Qwr)$}
    \step{4.1.3.2}{$AA /\ (Qun /\ Qwr) => [](Qun /\ Qwr)$}
    \step{4.1.3.3}{$AA /\ [](Qun /\ Qwr)  => []<><<\O{B}>>_{\O{w}}$}
    \qedstep
    \begin{proof}
     \pf\ \stepref{4.1.3.1}--\stepref{4.1.3.3} and temporal reasoning.
    \end{proof}
 \end{proof}
\end{noproof}
\end{noproof}
\end{proof}
%
 \noindent 
Each of our informal proofs can be replaced by hierarchical ones,
which can be carried down to the point where each step is justified
by predicate logic and TLA proof rules.

%try
\subsubsection{Discussion of the Proof}

The key to managing any kind of complexity, including the complexity
inherent in a nontrivial proof, is hierarchical structure.  When
reasoning in a formal logic such as TLA, the proof rules and the
structure of the formulas determine the structure of the proof.  For
example, the first three levels in the proofs of steps 1 and 3 were
determined completely syntactically; they could be generated
mechanically.  Most of the next level is also determined
syntactically---for example, the fact that $Inv.2$ has the form
$\forall i \in S \midcolon F(i) /\ G(i)$ determines the high level
outline of the proofs of~1.2.2.1--1.2.2.5.

Because TLA is a formal logic, every step in the proof hierarchy is a
precisely defined mathematical formula.  Prose appears only in the
lowest-level proof.  We can obtain a more reliable proof by replacing
a prose proof with one that is hierarchically structured.  Ultimately,
we would arrive at a proof in which every step is purely syntactic,
justified by the direct application of a single proof rule---either of
TLA or of predicate logic.  However, before that level of detail were
reached, we could replace the prose by instructions to a mechanical
theorem prover~\cite{engberg:mechanical}.

Steps 1--3 prove a safety property of the complete cache.  They
consist of action reasoning, with essentially no temporal logic.
These steps are the TLA version of the standard invariance and
step-simulation proofs of methods based on toy programming
languages~\cite{owicki:axiomatic} and
automata~\cite{lam:protocol,lynch:distributed}.  However, our proofs
are completely formal.  

The proof of fairness in step~4 uses nontrivial temporal logic
reasoning.  We know of no better formalism than temporal logic for
writing rigorous proofs of fairness properties.  Had we done the proof
in more detail, we would have relied heavily on the TLA rules WF1 and
WF2, which use action reasoning to derive temporal logic formulas.
(Rule WF1 is the TLA version of Manna and Pnueli's ``single-step''
rule for ``just'' transitions~\cite{manna:completing}.  Because their
method is not hierarchical, Manna and Pnueli have no analog of rule
WF2.)  Even for fairness properties, action reasoning forms the bulk
of a detailed TLA proof.

When we fill in more levels of detail in our proof, we discover that
certain facts about actions are used in several places.  For example,
a closer examination of our informal proof of step 4.1.2.1 reveals
that it implicitly uses step 3.1.1.5.  Our hierarchical proof style
allows the proof of 4.1.2.1 to invoke step 3, but not any of its
substeps~\cite{lamport:howtoprove}.  Results that are used in several
steps must either be moved to a higher level in the proof, or else
proved in separate lemmas.  We prefer to restructure a proof rather
than adding an array of external lemmas, so the structure of the
detailed proof in~\cite{ladkin:gerth-web-proof} will differ from that
of the proof presented here.



%try

\let\o=\realo
\renewcommand{\!}{\discretionary{}{}{}}
\bibliographystyle{plain}
%\bibliography{mybib}
\begin{thebibliography}{10}

\bibitem{abadi:existence}
Mart\'{\i}n Abadi and Leslie Lamport.
\newblock The existence of refinement mappings.
\newblock {\em Theoretical Computer Science}, 82(2):253--284, May 1991.

\bibitem{abadi:refining}
Mart\'{\i}n Abadi, Leslie Lamport, and Stephan Merz.
\newblock Refining specifications.
\newblock To appear.

\bibitem{afek:lazy-caching}
Yehuda Afek, Geoffrey Brown, and Michael Merritt.
\newblock Lazy caching.
\newblock {\em ACM Transactions on Programming Languages and Systems},
  15(1):182--205, January 1993.

\bibitem{ashcroft:proving}
E.~A. Ashcroft.
\newblock Proving assertions about parallel programs.
\newblock {\em Journal of Computer and System Sciences}, 10:110--135, February
  1975.

\bibitem{chandy:parallel}
K.~Mani Chandy and Jayadev Misra.
\newblock {\em Parallel Program Design}.
\newblock Addison-Wesley, Reading, Massachusetts, 1988.

\bibitem{demillo:social}
Richard~A. {De Millo}, Richard~J. Lipton, and Alan~J. Perlis.
\newblock Social processes and proofs of theorems and programs.
\newblock {\em Communications of the ACM}, 22(5):271--280, May 1979.

\bibitem{engberg:mechanical}
Urban Engberg, Peter Gr\o{}nning, and Leslie Lamport.
\newblock Mechanical verification of concurrent systems with {TLA}.
\newblock In G.~v.~Bochmann and D.~K. Probst, editors, {\em Proceedings of the
  Fourth International Conference on Computer Aided Verification}, volume 663
  of {\em Lecture Notes in Computer Science}, pages 44--55, Berlin, June 1992.
  Springer-Verlag.
\newblock Proceedings of the Fourth International Conference, CAV'92.

\bibitem{gerth:intro-to-seq-consistency}
Rob Gerth.
\newblock Introduction to sequential consistency and the lazy caching
  algorithm.
\newblock {\em Distributed Computing}, 1995.

\bibitem{ladkin:gerth-web-proof}
Peter Ladkin, Leslie Lamport, Bryan Olivier, and Denis Roegel.
\newblock A lazy caching proof in tla.
\newblock At URL {\tt
  http:\!//www.\!research.\!digital.\!com\!/SRC\!/tla\!/lazy.\!html} on the
  World Wide Web. It can also be found by searching the Web for the 31-letter
  string formed by concatenating {\tt uid} and \mbox{\tt
  ladlamoliroelazycachingproof}.

\bibitem{lam:protocol}
Simon~S. Lam and A.~Udaya Shankar.
\newblock Protocol verification via projections.
\newblock {\em IEEE Transactions on Software Engineering}, SE-10(4):325--342,
  July 1984.

\bibitem{lamport:howto}
Leslie Lamport.
\newblock How to make a multiprocessor computer that correctly executes
  multiprocess programs.
\newblock {\em IEEE Transactions on Computers}, C-28(9):690--691, September
  1979.

\bibitem{lamport:what-good}
Leslie Lamport.
\newblock What good is temporal logic?
\newblock In R.~E.~A. Mason, editor, {\em Information Processing 83:
  Proceedings of the IFIP 9th World Congress}, pages 657--668, Paris, September
  1983. IFIP, North-Holland.

\bibitem{lamport:simple}
Leslie Lamport.
\newblock A simple approach to specifying concurrent systems.
\newblock {\em Communications of the ACM}, 32(1):32--45, January 1989.

\bibitem{lamport:howtoprove}
Leslie Lamport.
\newblock How to write a proof.
\newblock {\em American Mathematical Monthly}, 102(7):600--608,
  August-September 1993.

\bibitem{lamport:hybrid}
Leslie Lamport.
\newblock Hybrid systems in {TLA}$^{+}$.
\newblock In Robert~L. Grossman, Anil Nerode, Anders~P. Ravn, and Hans Rischel,
  editors, {\em Hybrid Systems}, volume 736 of {\em Lecture Notes in Computer
  Science}, pages 77--102, Berlin, Heidelberg, 1993. Springer-Verlag.

\bibitem{lamport:howtowrite}
Leslie Lamport.
\newblock How to write a long formula.
\newblock {\em Formal Aspects of Computing}, 6:580--584, 1994.
\newblock First appeared as Research Report 119, Digital Equipment Corporation,
  Systems Research Center.

\bibitem{lamport:newtla}
Leslie Lamport.
\newblock The temporal logic of actions.
\newblock {\em ACM Transactions on Programming Languages and Systems},
  16(3):872--923, May 1994.

\bibitem{lamport:ftrtft94}
Leslie Lamport and Stephan Merz.
\newblock Specifying and verifying fault-tolerant systems.
\newblock In H.~Langmaack, W.-P. de~Roever, and J.~Vytopil, editors, {\em
  Formal Techniques in Real-Time and Fault-Tolerant Systems}, volume 863 of
  {\em Lecture Notes in Computer Science}, pages 41--76. Springer-Verlag,
  September 1994.

\bibitem{lynch:distributed}
Nancy~A. Lynch.
\newblock {\em Distributed Algorithms}.
\newblock Morgan Kaufmann, San Mateo, California, 1995.

\bibitem{manna:completing}
Zohar Manna and Amir Pnueli.
\newblock Completing the temporal picture.
\newblock {\em Theoretical Computer Science}, 83(1):97--130, 1991.

\bibitem{manna:temporal}
Zohar Manna and Amir Pnueli.
\newblock {\em The Temporal Logic of Reactive and Concurrent Systems}.
\newblock Springer-Verlag, New York, 1991.

\bibitem{owicki:axiomatic}
S.~Owicki and D.~Gries.
\newblock An axiomatic proof technique for parallel programs {I}.
\newblock {\em Acta Informatica}, 6(4):319--340, 1976.

\end{thebibliography}


\end{document}
%try
\end{document}
