Parse error: The level of the expression or operator substituted for 'Def' must be at most 0 - tla+

I have two specs: System and SystemMC. The System spec is the "nice" spec of the system I am specifying, useful for documentation. It defines a CONSTANT MessyAction(_) (in the actual specs I am writing, a hash function) that is messy to specify in an efficiently model-checkable way and so would reduce spec readability. I implement MessyAction(_) in the SystemMC spec, so I can model-check the System spec. However, the parser gives the following error in the SystemMC spec:
Level error in instantiating module 'System': The level of the expression or operator substituted for 'MessyAction' must be at most 0.
What does this error mean, and how can I accomplish my goal of model-checking the System spec without adding a bunch of stuff to it that is optimized for TLC? Here is the System spec:
------------------------------- MODULE System -------------------------------
EXTENDS
Naturals
CONSTANTS
MessyAction(_)
VARIABLES
Counter
-----------------------------------------------------------------------------
TypeInvariant ==
/\ Counter \in Nat
Init ==
/\ Counter = 0
Increment ==
/\ Counter' = Counter + 1
/\ MessyAction(Counter)
Next ==
\/ Increment
=============================================================================
Here is the SystemMC spec:
------------------------------ MODULE SystemMC ------------------------------
EXTENDS
Naturals
CONSTANTS
MaxCounterValue
VARIABLES
Counter,
PastValues
ASSUME MaxCounterValue \in Nat
-----------------------------------------------------------------------------
MessyAction(c) ==
/\ PastValues' = PastValues \cup {c}
S == INSTANCE System
TypeInvariant ==
/\ PastValues \subseteq Nat
/\ S!TypeInvariant
Init ==
/\ PastValues = {}
/\ S!Init
Increment ==
/\ Counter < MaxCounterValue
/\ S!Increment
Next ==
\/ Increment
=============================================================================

Per Leslie Lamport's reply here, when you instantiate a non-constant module (a module containing variables) like System, the CONSTANT entities can only be instantiated by other constants. So, in SystemMC you can rename MessyAction(_) to MessyActionImpl(_), define MessyAction(_) as a CONSTANT, then in the model define MessyAction(c) as MessyActionImpl(c). The System spec is unchanged, but here's the new SystemMC spec:
------------------------------ MODULE SystemMC ------------------------------
EXTENDS
Naturals
CONSTANTS
MessyAction(_),
MaxCounterValue
VARIABLES
Counter,
PastValues
ASSUME MaxCounterValue \in Nat
-----------------------------------------------------------------------------
MessyActionImpl(c) ==
/\ PastValues' = PastValues \cup {c}
S == INSTANCE System
TypeInvariant ==
/\ PastValues \subseteq Nat
/\ S!TypeInvariant
Init ==
/\ PastValues = {}
/\ S!Init
Increment ==
/\ Counter < MaxCounterValue
/\ S!Increment
Next ==
\/ Increment
=============================================================================
When you create a model in the toolbox, define the value of the MessyAction(_) constant as MessyActionImpl(_):
End result:
Voila, dependency injection for TLA+!

Related

Choosing one item from a symmetric set

I have a TLA+ spec akin to the following:
CONSTANT Items
VARIABLE item
And I'd like Items to be symmetric, and to select a single element from Items and store it into item.
I've been using item = CHOOSE x \in Items: TRUE, but I learned that this breaks symmetry on Items: TLC will always select the first item from the set.
I'd like to select a single item in a way that preserves symmetry, to allow TLC to explore all states. I don't care which item we select -- only that it is one, and that it is from Items. (Later, I need item to be \in Items.
While I'd prefer item to be a single element, it would also be okay for item to be a set of cardinality 1, so later I can check for \subseteq Items.
It was recommended to me to replace CHOOSE with {x \in Items: TRUE} to preserve symmetry and have the result be \subseteq Items, but this does not constrain the resulting set to cardinality 1.
Is there a way to ask TLA+ to give me a single item, or a set of cardinality 1, from a symmetric set of values?
I learned a bit more about TLA+/TLC since posting the question, and here's my answer:
To simply select an element from a symmetry set in the initial predicate:
item \in Items
or in an action:
item' \in Items
If you want to select an item that matches a predicate, as you can specify with CHOOSE, then this is the alternative:
item \in {x \in Items: P(x)}
This'll form a subset of Items that match the predicate, then select a single element of those.
Here's some data that shows the difference between this syntax and CHOOSE. Consider this module:
----------------------------- MODULE ChooseDemo -----------------------------
CONSTANT Items
VARIABLE item
TypeInvariant == item \in Items
Init == item = CHOOSE x \in Items: TRUE
Next == item' \in {x \in Items: x /= item}
=============================================================================
When Items has three items:
NOT a symmetry set: TLC finds 1 initial state and a total of 7 (3 distinct) states.
symmetry set: TLC finds 1 initial state and a total of 3 (1 distinct) states.
Now consider this module:
--------------------------- MODULE SetFormingDemo ---------------------------
CONSTANT Items
VARIABLE item
TypeInvariant == item \in Items
Init == item \in {x \in Items: TRUE}
Next == item' \in {x \in Items: x /= item}
=============================================================================
When Items has three items:
NOT a symmetry set: TLC finds 3 (3 distinct) initial states and a total of 9 (3 distinct) states.
symmetry set: TLC finds 3 (1 distinct) initial state and a total of 5 (1 distinct) states.
Hence, by using the set-forming syntax, TLC finds more states than it did with CHOOSE.

Cardinality constraints in MiniZinc

The MiniZinc constraint solver allows to express cardinality constraints very easily using the built-in sum() function:
% This predicate is true, iff 2 of the array
% elements are true
predicate exactly_two_sum(array[int] of var bool: x) =
(sum(x) == 2);
The cardinality constraint is met, if and only if the number if true elements in the array of Boolean variables is as specified. Booleans are automatically mapped to integer values 0 and 1 to compute the sum.
I implemented my own cardinality constraint predicate as set of counter slices:
% This predicate is true, iff 2 of the array
% elements are true
predicate exactly_two_serial(array[int] of var bool: x) =
let
{
int: lb = min(index_set(x));
int: ub = max(index_set(x));
int: len = length(x);
}
in
if len < 2 then
false
else if len == 2 then
x[lb] /\ x[ub]
else
(
let
{
% 1-of-3 counter is modelled as a set of slices
% with 3 outputs each
array[lb+1..ub-1] of var bool: t0;
array[lb+1..ub-1] of var bool: t1;
array[lb+1..ub-1] of var bool: t2;
}
in
% first two slices are hard-coded
(t0[lb+1] == not(x[lb] \/ x[lb+1])) /\
(t1[lb+1] == (x[lb] != x[lb+1])) /\
(t2[lb+1] == (x[lb] /\ x[lb+1])) /\
% remaining slices are regular
forall(i in lb+2..ub-1)
(
(t0[i] == t0[i-1] /\ not x[i]) /\
(t1[i] == (t0[i-1] /\ x[i]) \/ (t1[i-1] /\ not x[i])) /\
(t2[i] == (t1[i-1] /\ x[i]) \/ (t2[i-1] /\ not x[i]))
) /\
% output 2 of final slice must be true to fulfil predicate
((t1[ub-1] /\ x[ub]) \/ (t2[ub-1] /\ not x[ub]))
)
endif endif;
This implementation is using a parallel encoding with fewer lines/variables between the slices:
% This predicate is true, iff 2 of the array
% elements are true
predicate exactly_two_parallel(array[int] of var bool: x) =
let
{
int: lb = min(index_set(x));
int: ub = max(index_set(x));
int: len = length(x);
}
in
if len < 2 then
false
else if len == 2 then
x[lb] /\ x[ub]
else
(
let
{
% counter is modelled as a set of slices
% with 2 outputs each
% Encoding:
% 0 0 : 0 x true
% 0 1 : 1 x true
% 1 0 : 2 x true
% 1 1 : more than 2 x true
array[lb+1..ub] of var bool: t0;
array[lb+1..ub] of var bool: t1;
}
in
% first two slices are hard-coded
(t1[lb+1] == (x[lb] /\ x[lb+1])) /\
(t0[lb+1] == not t1[lb+1]) /\
% remaining slices are regular
forall(i in lb+2..ub)
(
(t0[i] == (t0[i-1] != x[i]) \/ (t0[i-1] /\ t1[i-1])) /\
(t1[i] == t1[i-1] \/ (t0[i-1] /\ x[i]))
) /\
% output of final slice must be 1 0 to fulfil predicate
(t1[ub] /\ not t0[ub])
)
endif endif;
Question:
Does it make sense to use home-grown cardinality predicates? Or is the MiniZinc implementation of sum() beyond all doubts in terms of solution speed?
Update:
I am using Gecode as solver back-end.
Linear sums is typically one of the most significant constraints to implement well in a constraint solver, so for your case the initial version using a simple sum is much better. In particular, the propagator in Gecode that implements the Boolean sum is heavily optimized to be as efficient as possible.
As a general rule, it is typically a good idea to use the constraints that are available. In particular, if what one is doing maps well to a global constraint that is typically a good idea. A related example would be if you want to count the occurrences of several different numbers in an array of integers, in which case the global cardinality constraint is very useful.
For completeness: When using lazy clause generation solvers (Chuffed for example), (novel) decompositions may sometimes be surprisingly useful. But that is a much more advanced topic.

Referencing previous state in Promela LTL statement

I'm getting started with Promela, and I'm having trouble expressing some LTL formulas.
An example is the following sequence value that I'd like to assert is monotonically increasing. Intuitively I want to write that in the next state, sequence is >= its previous value, but looking through documentation, I don't see a way to express this. Is there a method for expressing this type of formula?
byte sequence = 0;
ltl p0 { [] sequence >= prev(sequence) }
... processes that manipulate sequence ...
Assuming that it's possible to express the monotonically increasing property of sequence above, I'm wondering if there is a syntax for wildcard array indexing. Similar to the above example, I intuitively want to reference all previous index entries.
byte values[N];
byte index = 0;
ltl p1 { values[0..index-1] are monotonically increasing }
... processes ...
Thanks a lot for your help. Promela seems really great :)
AFAIK,
Monotonically Non-decreasing Sequence.
Linear Temporal Logic has a X operator that allows one to express a property that refers to a boolean condition holding in the next state, as opposed to the previous state.
However, one cannot directly compare an integer value of the current state with that of the next state within an LTL formula, because X evaluates to a Boolean value.
In theory, what one can do is to encode the <= operator over the integer as a Boolean property by bit-blasting it, e.g. by means of some clever use of the modulo operator or bitwise operations (it should not be too hard with unsigned variables) and a bit-to-bit comparison of the corresponding Boolean values (see final note).
From a modeling point of view, however, the easiest approach is to enrich your model with a prev_value variable and simply check that in each state the property prev_value <= cur_value holds. Notice that in this case you should use the d_step command to group together the two value assignments, so that they are conflated within a single state with no intermediate transitions, e.g.
...
byte prev_value;
byte cur_value;
...
d_step {
prev_value = cur_value;
cur_value = ... non-blocking function ...
}
Otherwise, the invariant property relating prev_value to cur_value may result to be broken on the corresponding automaton for some state s_i. (note: this would actually not hinder the verification of the specific LTL property you are interested in, but it can be an issue with other formulas)
Wildcard Indexing.
If I understand correctly, you want to express a property s.t. --in each state-- only memory locations from 0 up to index-1 are required to be monotonically non-decreasing, with index being a variable which can change value (arbitrarily?).
The structure of such property should be:
ltl p1 {
[] (
((1 <= index) -> "... values[0] is monotonically non-decreasing ...") &&
((2 <= index) -> "... values[1] is monotonically non-decreasing ...") &&
((3 <= index) -> "... values[2] is monotonically non-decreasing ...") &&
...
((N <= index) -> "... values[N-1] is monotonically non-decreasing ...")
)
}
I believe the answer to your question is no. However, I suggest you to use macros for the C preprocessor to simplify the encoding of your properties and avoid writing the same things over and over again.
Note:
Let's take curr_int and next_int 0-1 Integer variables s.t. next_int is equal to the value of curr_int in the next state (aka, curr_int is the previous value of next_int), and a curr Boolean variable s.t. curr is true if and only if curr_int is equal to 1.
Then, by the LTL semantics, X curr is true if and only if curr_int (next_int) is equal to 1 in the next (current) state.
Consider the following truth-table for state s_i:
curr_int | next_int | curr_int <= next_int
0 | 0 | 1
0 | 1 | 1
1 | 0 | 0
1 | 1 | 1
From the above definitions, we can rewrite it as:
curr | X curr | EXPR
false | false | true
false | true | true
true | false | false
true | true | true
From the truth-table it's can be seen that EXPR corresponds to
!curr v (X curr)
which can be more elegantly rewritten as
curr -> (X curr)
Thich is our final LTL-encodeable version of curr_int <= next_int for a given state s_i, when both are 0-1 Integer variables.
There is no such symbol in Promela. Yet any Past Time LTL formula can be translated into Future Time LTL (probably even more cumbersome one).
Not sure though is there an easy way to compare values of variables in different states.
Also check LTL specification pattern repository for past.
See discusssion in CS stackexhange
https://cstheory.stackexchange.com/questions/29444/do-past-time-ltl-and-future-time-ltl-have-the-same-expressiveness

SVA Property for a simple waveform

Waveform:-
I did a property as:
property p1;
a |=> (b == 1)[=2] ##1 (c == 1)[=2]
endproperty
But this property doesn't work well for this waveform, it isn't working for 3 or more "b's" before the "c's" and it isn't working for "c's" after the first "b".
I need a property that just can pass after the "a" signal just 2 "b's" and after just "2 c's" with any quantity of gaps between them.
thanks for help.
You do not specify that b should not be 1 when during the pulses on c, nor do you specify that c should not be 1 during the pulses on b.
So, how about something like this:
property p1;
a |=> ((c == 0) throughout (b == 1)[->2]) ##1 ((b == 0) throughout (c == 1)[->2]);
endproperty
The [->N] operator is the exact non-consecutive repetition operator or goto repetition operator. With goto repetition, the expression must hold in the final cycle of the match; in other words, the match is achieved as soon as the specified number of repetitions has occurred.

Constraint programming boolean solver

Huey, Dewey and Louie are being questioned by their uncle. These are the statements they make:
• Huey: “Dewey and Louie had equal share in it; if one is guilty, so is the other.”
• Dewey: “If Huey is guilty, then so am I.”
• Louie: “Dewey and I are not both guilty.”
Their uncle, knowing that they are scouts realizes that they cannot tell a lie.
My solution.
var bool :D; var bool :L; var bool :H;
constraint D <->L;
constraint H -> D;
constraint D!=L;
solve satisfy;
output[show(D), "\n", show(L),"\n", show(H)];
Minizinc can't solve it.
Here's my (old) version of this problem: http://www.hakank.org/minizinc/huey_dewey_louie.mzn
var bool: huey;
var bool: dewey;
var bool: louie;
constraint
% Huey: Dewey and Louie has equal share in it; if one is quitly, so is the other.
(dewey <-> louie)
% Dewey: If Huey is guilty, then so am I.
/\
(huey -> dewey)
% Louie: Dewey and I are not both quilty.
/\
(not (dewey /\ louie))
;
For this kind of problems I prefer to use Boolean Satisfiability (SAT) directly. Your problem can obviously be formulated as a propositional logic formula as follows (using the DIMACS format) :
Atom 1 : Dewey is guilty (i.e. will be associated to the literals -1 and 1 in the CNF)
Atom 2 : Louie is guilty (i.e. will be associated to the literals -2 and 2 in the CNF)
Atom 3 : Huey is guilty (i.e. will be associated to the literals -3 and 3 in the CNF)
The CNF file is then :
p cnf 4 3
-1 2 0
-2 1 0
-3 1 0
-1 -2 0
And here the solution using an 'online' SAT Solver : http://boolsat.com/show/5320e18a0148a30002000002
Yet another solution, using CLP(B) (constraint logic programming over Boolean variables) with SICStus Prolog or SWI:
:- use_module(library(clpb)).
guilty(H, D, L) :-
sat(D =:= L), % Huey
sat(H =< D), % Dewey
sat(~(D*L)). % Louie
Example query and its result:
?- guilty(H, D, L).
D = H, H = L, L = 0.
Another option is to ask WolframAlpha:
not (L xor D) and (H implies D) and not (L and D)
As suggested by Hakan, the following equivalent expression is also possible:
(L equivalent D) and (H implies D) and not (L and D)
Result is a truth table which has only (!D !H !L) as solution.

Resources