libtlafmt 0.4.1

A formatter library for TLA+ specs, core of tlafmt
Documentation
--------------------------- MODULE ReplicatedLog ----------------------------
EXTENDS Naturals, Sequences

CONSTANTS Node, Transaction

VARIABLES log, executed

vars == <<log, executed>>

TypeOK ==
  /\ log \in Seq(Transaction)
  /\ executed \in [Node -> Nat]

Convergence == []<>(\A n \in Node : executed[n] = Len(log))

Safety ==
    \A n \in Node : executed[n] <= Len(log)

Init ==
  /\ log = <<>>
  /\ executed = [n \in Node |-> 0]

WriteTx(n, tx) ==
  /\ executed[n] = Len(log)
  /\ log' = Append(log, tx)
  /\ executed' = [executed EXCEPT ![n] = @ + 1]

ExecuteTx(n) ==
  /\ executed[n] < Len(log)
  /\ executed' = [executed EXCEPT ![n] = @ + 1]
  /\ UNCHANGED log

\* Why does WriteTx also increment executed?
\* It increments executed[n] for one of the nodes n.
\* ExecuteTx catches up the other nodes.
\* With a single node, ExecuteTx is a no-op because
\* t is never enabled.

Next ==
  \/ \E n \in Node : \E tx \in Transaction: WriteTx(n, tx)
  \/ \E n \in Node : ExecuteTx(n)

Spec ==
  /\ Init
  /\ [][Next]_vars

THEOREM Spec => []Safety
THEOREM Spec => []TypeOK

ExecFairSpec ==
  /\ Spec
  /\ \A n \in Node : WF_vars(ExecuteTx(n))
  \* The following conjunct causes the spec to not be machine
  \* closed. This is orthogonal to the Finite Monotonic
  \* approach.
  /\ \A n \in Node : <>[][ExecuteTx(n)]_vars

WriteFairSpec ==
  /\ Spec
  /\ \A n \in Node : \A tx \in Transaction: WF_vars(WriteTx(n, tx))
  \* The following conjunct causes the spec to not be machine
  \* closed. This is orthogonal to the Finite Monotonic
  \* approach.
  /\ \A n \in Node : \A tx \in Transaction: <>[][WriteTx(n, tx)]_vars

\* ExecFairSpec and WriteFairSpec both work because every suffix with
\* infinitely many WriteTx implies Convergence to WriteTx's enablement
\* condition.  Likewise, every suffix with infinitely many ExecuteTx
\* implies Convergence.
THEOREM ExecFairSpec => Convergence
THEOREM WriteFairSpec => Convergence

-----------------------------------------------------------------------------

InsufficientlyFairSpecA ==
    /\ Spec
    /\ WF_vars(Next)

InsufficientlyFairSpecB ==
    /\ Spec
    /\ \A n \in Node : \A tx \in Transaction: WF_vars(WriteTx(n, tx))

InsufficientlyFairSpecC ==
    /\ Spec
    /\ \A n \in Node : \A tx \in Transaction : WF_vars(ExecuteTx(n))

-----------------------------------------------------------------------------

EffectivelyFalseSpecA ==
    /\ Spec
    /\ \A n \in Node : \A tx \in Transaction : WF_vars(ExecuteTx(n))
    /\ \A n \in Node : \A tx \in Transaction: <>[][WriteTx(n, tx)]_vars

EffectivelyFalseSpecB ==
    /\ Spec
    /\ \A n \in Node : \A tx \in Transaction: WF_vars(WriteTx(n, tx))
    /\ \A n \in Node : <>[][ExecuteTx(n)]_vars

=============================================================================