| title | author | contributors | date |
|---|---|---|---|
MoXI — A Model Checking Intermediate Language. (Draft) |
Cesare Tinelli |
Rohit Dureja, Ahmed Irfan, Christopher Johannsen, Shankar Natarajan, Karthik Nukala, Kristin Rozier, Moshe Vardi |
2024-03-16 |
MoXI, which stands for Model Exchange Interlingua, is an intermediate language meant to be a common input and output standard for model checkers for finite- and infinite-state systems, with an initial focus is on finite-state ones.
MoXI has been designed to be general enough to be an intermediate target language for a variety of user-facing specification languages for model checking. At the same time, MoXI is meant to be simple enough to be easily compilable to lower level languages or be directly supported by model checking tools based on SAT/SMT technology.
For being an intermediate language, models expressed in MoXI are meant to be produced and processed by tools, hence it was designed to have
- simple, easily (machine) parsable syntax;
- a rich set of data types;
- minimal syntactic sugar, at least initially;
- well-understood formal semantics;
- a small but comprehensive set of commands;
- simple translations to lower level modeling languages such as Btor2.
Based on these principles, MoXI provides no direct support for many of the features offered by current hardware modeling languages such as VHDL and Verilog or more general purpose system modeling languages such as SMV, TLA+, PROMELA, Simulink, SCADE, Lustre. However, it strives to offer enough capability so that problems expressed in those languages can be reduced to problems in MoXI.
MoXI is an extension of the SMT-LIB language with new commands to define and verify systems. It allows the definition of multi-component synchronous or asynchronous reactive systems. It also allows the specification and checking of reachability conditions (or, indirectly, state and transition invariants) and deadlocks, possibly under fairness conditions on input values.
MoXI assumes a discrete and linear notion of time and hence has a standard trace-based semantics.
Each system definition:
- defines a transition system via the use of SMT formulas, imposing minimal syntactic restrictions on those formulas;
- is parametrized by a state signature, a sequence of typed variables;
- partitions state variables into input, output and local variables;
- can be expressed as the synchronous or asynchronous composition of other systems.
The current focus on finite-state systems. However, the language has been designed to support the specification of infinite-state system as well.
The base logic of MoXI is the same as that of SMT-LIB: many-sorted first-order logic with equality and let binders. We refer to this logic simply as FOL. When we say formula, with no further qualifications, we refer to an arbitrary formula of FOL (possibly with quantifiers and let binders). When we say variable we mean a sorted variable, that is, one associated with sort (or a type, in type theory terminology).
We say that a formula is quantifier-free if it contains no occurrences
of the quantifiers
The scope of binders and the notion of free and bound (occurrences of) variables in a formula are defined as usual, that is, the scope is lexical. Following SMT-LIB's convention, local variables in an expression shadow global variables with the same name, but not function symbols defined in the background theory.
If
A formula may contain uninterpreted constant and function symbols, that is, symbols with no constraints on their interpretation. For most purposes, we treat uninterpreted constant and function symbols as free (rigid) variables, respectively of first and second order.
Formally, a transition system
where
-
$\boldsymbol i$ and$\boldsymbol{i'}$ are two tuples of input variables with the same length and type; -
$\boldsymbol o$ and$\boldsymbol{o'}$ are two tuples of output variables with the same length and type; -
$\boldsymbol l$ and$\boldsymbol{l'}$ are two tuples of local variables with the same length and type; -
$I_S$ is the system's initial state condition, expressed as a formula with no (free) variables from$\boldsymbol{i'}$ ,$\boldsymbol{o'}$ , and$\boldsymbol{l'}$ ; -
$T_S$ is the system's transition condition, expressed as a formula over the variables$\boldsymbol{i}$ ,$\boldsymbol{o}$ ,$\boldsymbol{l}$ ,$\boldsymbol{i'}$ ,$\boldsymbol{o'}$ , and$\boldsymbol{l'}$ .
Note
For convenience, but differently from other formalizations, a (full) state
of system
Note
Similarly to Mealy machines, the initial state condition is also supposed to specify the initial system's output, based on the initial state and input. Correspondingly, the transition relation is also supposed to specify the system's output in every later state of the computation.
Note
The input and output values corresponding to the transition
to the new state are those in the variables
MoXI focuses on reactive transition systems, that is, transition systems where every state as a successor. This is not a limitation in practice for modeling purposes because systems that have final states can be modeled using states that cycle back to themselves and produce stuttering outputs. In fact, as discussed later, the language has syntax for checking an even stronger requirement: progressiveness.
A transition system in the sense above implicitly defines a model (i.e., a Kripke structure) of First-Order Linear Temporal Logic (FO-LTL).
The language of FO-LTL extends that of FOL with the same modal operators of time
as in standard (propositional) LTL:
The set of non-temporal operators depends on the particular theory, in the sense of SMT,
considered (linear integer/real arithmetic, bit vectors, strings, and so on, and
their combinations).
The meaning of theory symbols (such as arithmetic operators) and theory sorts
(such as
More precisely, let us fix a tuple
A valuation of
Let
Let
-
$F$ is atomic and$\mathcal{I}[\boldsymbol x \mapsto \pi[0](\boldsymbol x)][\boldsymbol{x'} \mapsto \pi[1](\boldsymbol x)]$ satisfies$F$ as in FOL; -
$F = \lnot G~$ and$~(\mathcal I, \pi) \not\models G$ ; -
$F = G_1 \land G_2~$ and$~(\mathcal I, \pi) \models G_i$ for$i=1,2$ ; -
$F = \exists z, G$ and$(\mathcal I[z \mapsto v], \pi) \models G$ for some value$v$ for$z$ ; -
$F = \mathbf{eventually}~G$ and$(\mathcal I, \pi^i) \models G$ for some$i \geq 0$ ; -
$F = \mathbf{always}~G$ and$(\mathcal I, \pi^i) \models G$ for all$i \geq 0$ .
The semantics of the propositional connectives
Now let
be a transition system with state variables
The infinite trace semantics of
We call any such pair an execution of
Let
-
$F$ is atomic and$\mathcal I[\boldsymbol x \mapsto \pi[0](\boldsymbol x), \boldsymbol{x'} \mapsto \pi[1](\boldsymbol x)]$ satisfies$F$ as in FOL; -
$F = \lnot G$ and$(\mathcal I, \pi) \not\models_n G$ ; -
$F = G_1 \land G_2$ and$(\mathcal I, \pi) \models_n G_i$ for$i=1,2$ ; -
$F = \exists z, G$ and$(\mathcal I[z \mapsto v], \pi) \models_n G$ for some value$v$ for$z$ ; -
$F = \mathbf{eventually}~G$ and$(\mathcal I, \pi^i) \models_{n-i} G$ for some$i = 0, \ldots, n$ ; -
$F = \mathbf{always}~G$ and$(\mathcal I, \pi^i) \models_{n-i} G$ for all$i = 0, \ldots, n$ .
The semantics of the propositional connectives
Note
This notion is well defined even when
The notion of
MoXI assumes a discrete and linear notion of time and adopts the trace-based semantics defined in the previous section. As mentioned earlier, it builds on the SMT-LIB language, extending it with commands to represent transition systems and to specify properties or queries. It also standardizes a format for witnesses generated by tool for checking MoXI models.
SMT-LIB is a command-based language with LISP-like syntax (s-expressions, in prefix notation) designed to be a common input/output language for SMT solvers.
MoXI adopts the following SMT-LIB commands:
-
(declare-sort
$s$ $n$ )Declares
$s$ to be a sort symbol (i.e., type constructor) of arity$n$ . Examples:(declare-sort A 0) (declare-sort Set 1) ; possible sorts: A, (Set A), (Set (Set A)), (Array Int Real), ...
-
(define-sort
$s$ ($u_1$ $\cdots$ $u_n$ )$\tau$ )Defines
$S$ as synonym of a parametric type$\tau$ with parameters$u_1 \cdots u_n$ . Examples:(declare-sort NestedSet (X) (Set (Set X))) ; possible sorts: (NestedSet A), ... (declare-sort Array2 (X Y) (Array X (Array X Y))) ; possible sorts: (Array2 Int Bool), ...
-
(declare-const
$c$ $\sigma$ )Declares a constant
$c$ of sort$\sigma$ . Examples:(declare-const a A) (declare-const n Int)
-
(define-fun
$f$ ( ($x_1$ $\sigma_1$ )$\cdots$ ($x_1$ $\sigma_1$ ))$\sigma$ $t$ )Defines a (non-recursive) function
$f$ with inputs$x_1, \ldots, x_n$ (of respective sort$\sigma_1, \ldots, \sigma_n$ ), output sort$\sigma$ , and body$t$ . Examples:(declare-fun sq ((n Int)) Int (* n n)) (declare-fun isSqRoot ((m Int) (n Int)) Bool (= n (sq m))) (declare-fun max ((m Int) (n Int)) Int (ite (> m n) m n))
-
(set-logic
$L$ )Defines the model's data logic, that is, the background theories of relevant data types (e.g., integers, reals, bit vectors, and so on) as well as the language of allowed logical constraints (e.g., quantifier-free, linear, etc.).
(set-logic QF_BV)
One addition to SMT-LIB is the binary symbol != for disequality. For each term s and t of the same sort, (!= s t) has the same meaning as (not (= s t)) or, equivalently, (distinct s t).
MoXI adds three commands to SMT-LIB: declare-enum-sort, define-system, and check-system
The first has the form
(declare-enum-sort
where
The other two commands are discussed in detail in the next two sections.
MoXI allows the definition of a model as the composition of one or more systems. MoXI ’s system definition commands follow the SMT-LIB syntax for attribute-value pairs.
An atomic transition system with
(define-system
:input ( (
:output ( (
:local ( (
:init
:trans
:inv
)
where
-
$S$ is the system's identifier; - each
$i_j$ is an input variable of sort$\delta_j$ ; - each
$o_j$ is an output variable of sort$\tau_j$ ; - each
$l_j$ is a local variable of sort$\sigma_j$ ; - all variables above are distinct;
- each
$i_j$ ,$o_j$ ,$l_j$ denote current-state values; -
next-state variables are not provided explicitly but are denoted
by convention by appending
$'$ to the names of the current-state variables$i_j$ ,$o_j$ , and$l_j$ ; -
$I$ , the initial condition, is a one-state formula over the unprimed system's variables (input, output and local state variables) that expresses a constraint on the initial states of$S$ ; -
$T$ , the transition condition, is a two-state formula over all of the system's variables (primed and unprimed) that expresses a constraint on the state transitions of$S$ ; -
$P$ , the invariance condition, is a one state formula over all of the unprimed system's variables that expresses a constraint on all reachable states of$S$ ; - all attributes are optional but can occur at most once;
- the order of the attributes is immaterial except that :input, :output, and :local must occur before :init, :trans, and :inv;
- the default value for a missing attribute is the empty list () for :input, :output, and :local; and true for :init, :trans, and :inv.
Syntactically, the system's identifier, input, output and local variables are
SMT-LIB symbols.
In contrast, the sorts
Discussion: We could allow multiple occurrences of the :inv attribute with conjunctive semantics. Should we allow multiple occurrences of the :trans attribute but with disjunctive semantics? The rationale would be to facilitate the recognition of systems defined by alternative sets of transitions.
Let
Formally, an atomic system
We call
Note
The relation expressed by the formula
Note
The :inv attribute is not strictly necessary since a system with a declaration of the form
(define-system
:output ( (
:local ( (
:init
:trans
:inv
)
can be equivalently expressed with a declaration of the form
(define-system
:output ( (
:local ( (
:init
:trans (and
)
Note
Systems are meant to be progressive: every reachable state has a successor
with respect
(Adapted from "Principles of Cyber-Physical Systems" by R. Alur, 2015)
When reading these examples, it is helpful to keep in mind that, intuitively, in the initial conditions, the input values are given and the local and output values are to be defined, or more generally, constrained with respect to the given ones. In contrast, in the transition conditions, the new input values, and old input, output and local values are given, and the new local and output values are to be constrained with respect to the given ones.
The output of system Delay below is initially 0 and then is the previous input. No local variables are needed.
(define-system Delay :input ( (i Int) ) :output ( (o Int) )
:init (= o 0)
:trans (= o' i) ; the new output is the old input
)A variant of Delay where the output is initially any number in [0,10].
(define-system Delay :input ( (i Int) ) :output ( (o Int) )
:init (<= 0 o 10) ; more than one possible initial output
:trans (= o' i)
)A clocked lossless channel, stuttering when the clock is not ticking. The clock is represented by a Boolean input variable clock.
(define-system StutteringClockedCopy
:input ((clock Bool) (i Int))
:output ((o Int))
:init (=> clock (= o i)) ; o is arbitrary when clock is false
:trans (ite clock (= o’ i’) (= o’ o)) ; ite is if-then-else
)Events carrying data can be modeled as instances of the polymorphic algebraic datatype (Event X) where X is the type of the data carried by the event.
(declare-datatype Event (par (X) (
(absent)
(present (val X))
)))An event-triggered channel that arbitrarily loses its input data.
(define-system LossyIntChannel
:input ((i (Event Int)))
:output ((o (Event Int)))
:inv (or (= o i) (= o absent))
)Equivalent formulation using unconstrained local state.
(define-system LossyIntChannel
:input ((i (Event Int)))
:output ((o (Event Int)))
:local ((s Bool))
; at all times, whether the input event is transmitted
; or not depends on value of s
:inv (= o (ite s i absent))
)TimedSwitch models a timed light switch where the light stays on for at most 10 steps unless it is switched off before. The input Boolean is interpreted as an on/off toggle. The transition predicate is formulated as a set of transitions.
(declare-enum-sort LightStatus (on off))
(define-system TimedSwitch1
:input ( (press Bool) )
:output ( (sig Bool) )
:local ( (s LightStatus) (n Int) )
:inv (= sig (= s on))
:init (and
(= n 0)
(ite press (= s on) (= s off))
)
:trans (let
(; transitions
(stay-off (and (= s off) (not press') (= s' off) (= n' n)))
(turn-on (and (= s off) press' (= s' on) (= n' n)))
(stay-on (and (= s on) (not press') (< n 10) (= s' on) (= n' (+ n 1))))
(turn-off (and (= s on) (or press' (>= n 10)) (= s' off) (= n' 0)))
)
(or stay-off turn-on turn-off stay-on)
)
)A variant of the system above where the transition predicate is formulated guarded-transitions style.
(define-system TimedSwitch2
:input ( (press Bool) )
:output ( (sig Bool) )
:local ( (s LightStatus) (n Int) )
:inv (= sig (= s on))
:init (and
(= n 0)
(ite press (= s on) (= s off))
)
:trans (and
(=> (and (= s off) (not press'))
(and (= s' off) (= n' n))) ; off --> off
(=> (and (= s off) press')
(and (= s' on) (= n' n))) ; off --> on
(=> (and (= s on) (not press') (< 10 n))
(and (= s' on) (= n' (+ n 1)))) ; on --> on
(=> (and (= s on) (or press' (>= n 10)))
(and (= s' off) (= n' 0))) ; on --> off
)
)Another variant but in equational style.
(define-fun flip ((s LightStatus)) LightStatus
(ite (= s off) on off)
)
(define-system TimedSwitch3
:input ( (press Bool) )
:output ( (sig Bool) )
:local ( (s LightStatus) (n Int) )
:inv (= sig (= s on))
:init (and
(= n 0)
(= s (ite press on off))
)
:trans (and
(= s' (ite press' (flip s)
(ite (or (= s off) (>= n 10)) off
on)))
(= n' (ite (or (= s off) (= s' off)) 0
(+ n 1)))
)
)The non-deterministic arbiter below grants input requests expressed by the Boolean inputs r1 and r2. A request is always granted, expressed by the Boolean outputs g1 or grant2, if it is the only request. When both inputs contain a request, one of the two request is granted, with a non-deterministic choice. Since the output depends only on the current values of input and local variables, the systems can be specified simply by an invariant.
(define-system NonDetArbiter
:input ( (r1 Bool) (r2 Bool) )
:output ( (g1 Bool) (g2 Bool) )
:local ( (s Bool) )
:inv (and
(=> (and (not r1) (not r2))
(and (not g1) (not g2)))
(=> (and r1 (not r2))
(and g1 (not g2)))
(=> (and (not r1) r2)
(and (not g1) g2))
(=> (and r1 r2)
; the unconstrained value of `s` is used as non-deterministic choice
(ite s (and g1 (not g2))
(and (not g1) g2)))
)
)The next arbiter is similar to NonDetArbiter but grants requests a cycle later and does not use a local variable for the non-deterministic choice.
(define-system DelayedArbiter
:input ( (r1 Bool) (r2 Bool) )
:output ( (g1 Bool) (g2 Bool) )
:local ( (s Bool) )
:init ( and (not g1) (not g2) ) ; nothing is granted initially
:trans (and
(=> (and (not r1) (not r2))
(and (not g1') (not g2')))
(=> (and r1 (not r2))
(and g1' (not g2')))
(=> (and (not r1) r2)
(and (not g1') g2'))
(=> (and r1 r2)
(!= g1' g2'))
)
)Similar to DelayedArbiter but for requests expressed as integer events.
(define-system IntNonDetArbiter
:input ( (r1 (Event Int)) (r2 (Event Int)) )
:output ( (g1 (Event Int)) (g2 (Event Int)) )
:local ( (s Bool) )
:init (= g1 g2 absent)
:trans (and
(=> (= r1' r2' absent)
(= g1' g2' absent))
(=> (and (!= r1' absent) (= r2' absent))
(and (= g1' r1) (= g2' absent)))
(=> (and (= r1' absent) (!= r2' absent))
(and (= g1' absent) (= g2' r2')))
(=> (and (!= r1' absent) (!= r2' absent))
(or (and (= g1' r1') (= g2' absent))
(and (= g1' absent) (= g2' r2'))))
)
)Transition systems can also be defined as the synchronous[^1] composition of other systems by a command of the form:
(define-system
:input ( (
:output ( (
:local ( (
:subsys (
:subsys (
:init
:trans
:inv
)
where
- :input, :output, :local :init, :trans, and :inv are as in atomic system definitions;
- every :subsys attribute occurs after the :input, :output, and :local attributes but before the :init, :trans, and :inv attributes;
-
$q > 0$ and each$S_i$ is the name of a system other than$S$ ; - the names
$S_1 \ldots,S_q$ need not be all distinct; - each
$N_i$ is a local synonym for$S_i$ , with$N_1,\ldots,N_q$ distinct; - each
$\boldsymbol x_i$ consists of$S$ 's variables of the same sort as$S_i$ 's input; - each
$\boldsymbol y_i$ consists of$S$ 's local/output variables of the same sort as$S_i$ 's output; - the directed subsystem graph rooted at
$S$ is acyclic.
For
Let
Formally, a composite system
where
-
$I_S[\boldsymbol{x}] = I[\boldsymbol{x}] \land \bigwedge_{k=1,\ldots,q} I_k[\boldsymbol{x}_k,\boldsymbol{y}_k,\boldsymbol{l}_k]$
and $T_S[\boldsymbol{x},\boldsymbol{x'}] = P[\boldsymbol{x}] \land T[\boldsymbol{x},\boldsymbol{x'}] \land \bigwedge_{k=1,\ldots,q} T_k[\boldsymbol{x}_k,\boldsymbol{y}_k,\boldsymbol{l}_k, \boldsymbol{x'}_k,\boldsymbol{y'}_k,\boldsymbol{l'}_k]$
;----------------
; Two-step delay
;----------------
; +------------------------------------+
; | DoubleDelay |
; | +-----------+ +-----------+ |
; in | | | temp | | | out
; ----+->| Delay |----->| Delay |--+---->
; | | | | | |
; | +-----------+ +-----------+ |
; +------------------------------------+
; One-step delay
(define-system Delay :input ( (i Int) ) :output ( (o Int) )
:local ( (s Int) )
:inv (= s i)
:init (= o 0)
:trans (= o' s)
)
; Two-step delay
(define-system DoubleDelay :input ( (in Int) ) :output ( (out Int) )
:local ( (temp Int) )
:subsys (D1 (Delay in temp))
:subsys (D2 (Delay temp out))
)
;; DoubleDelay expanded
(define-system DoubleDelay
:input ( (in Int) )
:output ( (out Int) )
:local (
(temp Int)
(s1 Int) ; from `(Delay in temp)`
(s2 Int) ; from `(Delay temp out)`
)
:inv (and
(= s1 in) ; from `(Delay in temp)`
(= s2 temp) ; from `(Delay temp out)`
)
:init (and
(= temp 0) ; from `(Delay in temp)`
(= out 0) ; from `(Delay temp out)`
)
:trans (and
(= temp' s1) ; from `(Delay in temp)`
(= out' s2) ; from `(Delay temp out)`
)
)
; Example trace:
; in = 1, 2, 3, 4, 5, 6, 7, ...
; s1 = 1, 2, 3, 4, 5, 6, 7, ...
; temp = 0, 1, 2, 3, 4, 5, 6, ...
; s2 = 0, 1, 2, 3, 4, 5, 6, ...
; out = 0, 0, 1, 2, 3, 4, 5, ...The next example defines a three-bit counter in terms of three identical one-bit counters. The one-bit counter uses a latch. The latch has a Boolean state represented by state variable s with arbitrary initial value. The value of output out is always the previous value of s. A set request (represented by input set being true) sets the new value of s to true unless there is a concurrent reset request (represented by input reset being true). In that case, the choice between the two requests is resolved arbitrarily using the value of the unconstrained local variable b. In the absence of either a set or a reset, the value of out is unchanged.
(define-system Latch :input ( (set Bool) (reset Bool) ) :output ( (out Bool))
:local ( (s Bool) (b Bool) )
:init (and
(= out b)
)
:trans (and
(= out' s)
(= s' (or (and set (or (not reset) b))
(and (not set) (not reset) out)))
)
)The one-bit counter is implemented using the latch component modeled by Latch.
The counter goes from 0 (represented as false) to 1 (true)
with a carry value of 0, or from 1 to 0 with a carry value of 1 when
the increment signal inc is true.
It is reset to 0 (false) when the start signal is true.
The initial value of the counter is arbitrary.
; +--------------------------------------------------------------+
; | |
; | +--------------------------------------------------------+ |
; | | +-------+ | |
; | +-|-----------------------------------|``-. set | | | |
; | | | |`-._ | :---->| | | |
; | | +--|``-. +--| _]o--|..-` | Latch | | |
; | | | :--+----\``-. | |.-` reset | |-+----> out
; inc ---+----|..-` | ) :--+--------------------->| | |
; | | +--/..-` +-------+ |
; | | | |
; start ------------------+ OneBitCounter |
; | | |
; +--------------|-----------------------------------------------+
; |
; v carry
(define-system OneBitCounter :input ( (inc Bool) (start Bool) )
:output ( (out Bool) (carry Bool) )
:local ( (set Bool) (reset Bool) )
:subsys (L (Latch set reset out))
:inv (and
(= set (and inc (not reset)))
(= reset (or carry start))
(= carry (and inc out))
)
)The three-bit counter is a resettable counter obtained by cascading three 1-bit counters. The output is three Boolean values standing for the three bits, with out0 being the least significant one.
; +---------------------------------------------------------+
; | |
; | +-----------------------------------------------> out0
; | | +------------------------------> out1
; | | | +-------------> out2
; | | | | |
; | +---------+ +---------+ +---------+ |
; | | | car0 | | car1 | | car2 |
; inc ------->| OneBit |----->| OneBit |----->| OneBit |----> |
; | | Counter | | Counter | | Counter | |
; start ----+-->| | +-->| | +-->| | |
; | | +---------+ | +---------+ | +---------+ |
; | +----------------+----------------+ |
; +---------------------------------------------------------+
;
(define-system ThreeBitCounter :input ( (inc Bool) (start Bool) )
:output ( (out0 Bool) (out1 Bool) (out2 Bool) )
:local ( (car0 Bool) (car1 Bool) (car2 Bool) )
:subsys (C1 (OneBitCounter inc start out0 car0))
:subsys (C2 (OneBitCounter car0 start out1 car1))
:subsys (C3 (OneBitCounter car1 start out2 car2))
)Because of the infinite trace semantics every system defined in MoXI is expected to execute forever. In such semantics, the reachability of a deadlocked state (i.e., a state with no successors in the transition relation) indicates the presence of an error in the system's definition. In fact, since these are systems with inputs, the requirements are typically even more stringent: a state should have a successor for every possible next-state input.
Intuitively, for a system definition to define a deadlock-free system,
the following must hold for the variables
-
Every assignment of values to the input variables
$\boldsymbol{i}$ can be extended to an assignment to$\boldsymbol{x}$ that satisfies$I_S[\boldsymbol{x}]$ . -
For every reachable state
$s$ (i.e., assignment to the variables$\boldsymbol{x}$ ), every assignment to the primed input variables$\boldsymbol{i'}$ can be extended to an assignment$s'$ to$\boldsymbol{x'}$ so that$s,s'$ satisfies$T_S$ [$\boldsymbol{x},\boldsymbol{x'}$].
The first restriction above guarantees that the system can start at all.
The second ensures that from any reachable state and for any new input,
the system can move to another state (and so also produce output).
Given a backgrount theory
-
a sufficient condition for (1) is that the following formula is valid in
$\mathcal T$ :$$\forall \boldsymbol{i}, \exists \boldsymbol{o}, \exists \boldsymbol{l}, I_S$$ -
a sufficient condition for (2) is that the following formula is valid in
$\mathcal T$ :$$\forall \boldsymbol{i}~ \forall \boldsymbol{o}~ \forall \boldsymbol{l}~ \forall \boldsymbol{i'}~ \exists \boldsymbol{o'}~ \exists \boldsymbol{l'}~ T_S $$ Note that this condition is not a necessary condition as it needs not apply to unreachable states. Let
$\textrm{Reachable}[\boldsymbol{i}, \boldsymbol{o}, \boldsymbol{l}]$ denote the (possibly higher-order) formula satisfied exactly by the reachable states of$S$ . Then, a more accurate sufficient condition for (2) above would be the validity in$\mathcal T$ of the formula:$$\forall \boldsymbol{i}~ \forall \boldsymbol{o}~ \forall \boldsymbol{l}~ \forall \boldsymbol{i'}~ \exists \boldsymbol{o'}~ \exists \boldsymbol{l'}~ \textrm{Reachable} \Rightarrow T_S[\boldsymbol{i}, \boldsymbol{o}, \boldsymbol{l}] $$
Note
In general, checking the two sufficient conditions above automatically can be impossible or very expensive because of the quantifier alternations in the conditions.
The properties to check for a (possibly composite) defined system are specified using the following command for defining queries on the system’s behavior.
(check-system
:input ( (
:output ( (
:local ( (
:assumption (
:fairness (
:reachable (
:current (
:query (
:queries ( (
)
where
-
$S$ is the identifier of a previously defined system with$m$ inputs,$n$ outputs, and$p$ local variables; - all attributes are optional and their order is immaterial except that :input, :output, :local, have to come before the other attributes [may not need this restriction];
- all attributes except for :input, :output and :local are repeatable.
-
$\boldsymbol{i} = (i_1, \ldots, i_m)$ is a renaming of the corresponding input variables of$S$ of sort$\boldsymbol{\delta} = (\delta_1, \ldots, \delta_m)$ ; -
$\boldsymbol{o} = (o_1, \ldots, o_n)$ is a renaming of the corresponding output variables of$S$ of sort$\boldsymbol{\tau} = (\tau_1, \ldots, \tau_n)$ ; -
$\boldsymbol{l} = (l_1, \ldots, l_p)$ is a renaming of the corresponding local variables of$S$ of sort$\boldsymbol{\sigma} = (\sigma_1, \ldots, \sigma_p)$ ; -
$a$ ,$r$ ,$f$ ,$c$ ,$q$ ,$q_1, \ldots, q_k$ are identifiers; -
$A$ is (non-temporal) formula over the system variables$\boldsymbol{i}$ ,$\boldsymbol{o}$ ,$\boldsymbol{l}$ , and$\boldsymbol{i'}$ expressing an environmental assumption on$\boldsymbol{i'}$ ; -
$F$ is (non-temporal) formula over the system variables$\boldsymbol{i}$ ,$\boldsymbol{o}$ ,$\boldsymbol{l}$ , and$\boldsymbol{i'}$ expressing a fairness condition on$\boldsymbol{i'}$ ; -
$R$ is (non-temporal) formula over all the system variables, primed and unprimed, expressing a state reachability condition; -
$C$ is (non-temporal) formula over all the system variables$\boldsymbol{i}$ ,$\boldsymbol{o}$ ,$\boldsymbol{l}$ expressing a state initiality condition; - each
$g_j$ and$g_{j,k}$ ranges over the$a$ ,$r$ ,$f$ ,$c$ identifiers; -
$(q\ (g_1 \cdots g_q))$ defines a query$q$ as consisting of the formulas named by$g_1, \dots, g_q$ ; the same holds for each$(q_j\ (g_{j,1} \cdots g_{j,n_j}))$ ; - a query can contain more than one assumption, fairness condition and reachability condition but at most one initiality condition.
Note
When the command contains more than one instance of the attributes
:assumption, :reachable, :fairness and :current,
the list of elements of a query
Note
The order of the formula names in a query is immaterial.
Each query (
Given a check command like the above for a system
Specifically, for a system
(1) A
is
(2) A
is
(3) A
is satisfiable in LTL.
(4) A
is satisfiable in LTL.
Let
For each satisfiable query in a check-system command, the model checker is expected to produce
- a
$\mathcal T$ -interpretation$\mathcal I$ of the (global) free symbols in the script; - a witnessing trace in
$\mathcal I$ .
The interpretation
For each unsatisfiable query, the model checker may return a proof certificate for that query’s unsatisfiability.
Note: To enforce the infinite state semantics for an query it is enough for it to contain any fairness condition, including the valid formula true.
Note: For queries with no fairness conditions, the witnessing trace may not be a trace of the system. [Elaborate]
Note: The witnessing trace for a query may satisfy each reachability condition in the query in a different state.
[Non-deterministic arbiter.]
(check-system NonDetArbiter
:input ( (req1 Bool) (req2 Bool) )
:output ( (gr1 Bool) (gr2 Bool) )
; There are never concurrent requests
:assumption (a1 (not (and req1 req2)))
; The same request is never issued twice in a row
:assumption (a2 (and (=> req1 (not req1')) (=> req2 (not req2'))))
; Neg of: every request is immediately granted
:reachable (r (not (and (=> req1 gr1) (=> req2 gr2))))
; check the reachability of r under assumptions a1 and a2
:query (q (a1 a2 r))
)[Temporal queries.]
(define-system Historically :input ((b Bool)) :output ((hb Bool))
:init (= hb b)
:trans (= hb’ (and b’ hb))
)
(define-system Before :input ((b Bool)) :output ((bb Bool))
:init (= bb' false)
:trans (= bb’ b)
)
(define-system Count :input ((b Bool)) :output ((c Int))
:init (= c (ite b 1 0))
:trans (= c’ (+ c (ite b 0 1)))
)
(define-system Monitor :input ((r1 Bool) (r2 Bool)) :output ((g1 Bool) (g2 Bool))
:local ((a1 Bool) (a2 Bool) (b Bool) (h1 Bool) (h2 Bool) (bf Bool) (c1 Int))
:subsys (A (NonDetArbiter r1 r2 g1 g2))
:subsys (H1 (Historically a1 h1))
:subsys (H2 (Historically a2 h2))
:subsys (C (Count g1 c1))
:subsys (B (Before b bf))
:inv (and
; a1 <=> no requests
(= a1 (and (not r1) (not r2)))
; a2 <=> no grants
(= a2 (and (not g1) (not g2)))
; b <=> c1 is 4
(= b (= c1 4))
)
)
(check-system Monitor :input ((r1 Bool) (r2 Bool)) :output ((g1 Bool) (g2 Bool))
:local ((a1 Bool) (a2 Bool) (b Bool) (h1 Bool) (h2 Bool) (bf Bool) (c1 Int))
; no concurrent requests
:assumption (A (not (and r1 r2)))
; neg of: if there have been no requests, there have been no grants
:reachable (P1 (not (=> h1 h2)))
; neg of: a request is granted at most 4 times
:reachable (P2 (not (=> bf (not g1))))
:query (Q1 (A P1))
:query (Q2 (A P2))
)MoXI also defines the content and format of possible responses
(from the model checker) to a check-system command.
Witness traces returned by the model checker are currently limited to lasso traces,
that is, traces of the form
Each witness is then represented by two trails:
- a prefix trail
$p$ and - a lasso trail
$l$ .
A witness trace is then an infinite trace that starts with a prefix
Each response is an s-expression starting with check-system-response and listing several attributes with their values. The format of the response can be verbose or compact. This is indicated by the value full or compact of the attribute :verbosity.
[to do]
Verbose response with input var i, output var o, local var s,
reachability pred r, and fairness condition f.
(check-system-response
:verbosity full
:query (q1 :result sat :model m :trace t)
:query (q2 :result unsat :certificate c)
:query (q3 :result unknown) ; for timeouts and other cases
:trace (t :prefix p :lasso l) ; t = pl^ω
:model (m M) ; M is model in SMT-LIB format
:trail (p ( (0 (i i₀) (o o₀) (s s₀) (r r₀) (f f₀)) ; numbered state/valuation
...
(j (i iⱼ) (o oⱼ) (s sⱼ) (r rⱼ) (f fⱼ))
)
)
:trail (l ( (... ) ... ( ...) ))
:certificate (c :inv F :k n)
)The compact response format is identical to the verbose one except that each trail starts with a fully specified state and continues with states that list only the variables whose value differs from their value in the previous state.
[Complete examples]
(check-system-response
:verbosity compact
...
)[^1] The asynchronous composition of systems is planned for a later version of MoXI.