How to check if a decision tree satisfies an invariant? - model-checking

I know the decision tree and what the invariant is (if that's the right term). All the other definitions used (UsingTor, UsingProxy, etc. can be anything). How can I use TLA+ to check if every leaf of the decision tree satisfies the invariant?
I would know how to do this if the decision tree was a sequence of states: I'd check if it always ends up in a state satisfying this invariant. Not sure how to do this though.
Invariant ==
/\ UsingTor => UsingProxy
/\ UsingProxy => UsingTor
/\ UsingProxy => UsingBlockingClient
/\ UsingBlockingClient => UsingProxy
/\ ToldToUseLocalBitcoinNode => ~ConfiguredToIgnoreLocalBtc
/\ ConfiguredToIgnoreLocalBtc => ~ToldToUseLocalBitcoinNode
/\ ToldToUseLocalBitcoinNode => ~UsingProxy
/\ ~ToldToUseLocalBitcoinNode => DisableUseOfLocalBtcNode
DecisionTree ==
\/ /\ UsingProxy
/\ \/ /\ ConfiguredToIgnoreLocalBtc
/\ UsingBlockingClient
\/ /\ ~ConfiguredToIgnoreLocalBtc
/\ UsingBlockingClient
/\ UsingProxy
/\ ~ToldToUseLocalBitcoinNode => DisableUseOfLocalBtcNode
\/ /\ ~UsingProxy
/\ ~UsingTor
/\ ~UsingBlockingClient

See this example that shows how to use ASSUME to assert some simple mathematical/constant formulas: https://github.com/tlaplus/Examples/blob/master/specifications/SpecifyingSystems/SimpleMath/SimpleMath.tla

Related

Few questions encountered when trying to implementing a state machine in TLA+

I'm trying to implement a state machine in TLA+, and I encountered a few questions when checking it with TLC.
I think there might be some problems in my spec,and you might not understand what I'm implementing in spec.So I want to explain what I'm doing first.
First,it will read two inputs.In_sentence_seq stand for future command sequence,changing the state of the state machine.In_layer_name stand for input data,and will be used in some specfic states later.And they will turn into variable in_seq and layer_set,maybe after some processes though.
Then,the state machine starts with Init,and then change its state(cur_state) by state_changer when in_seq not empty, or by state_stabler when in_seq empty.After that, do something(meaning only one in actions derived_def_global,rule_head,derived_def_rule,check_statement) depend on cur_state or do nothing if cur_state equals 0.After that,change state by state_changer or state_stabler again.And the state machine will repeat the change state->do something or nothing process again and again.
My spec is written in this way:
----------------------------- MODULE Parser -----------------------------
EXTENDS Integers,Naturals,Reals,Sequences
CONSTANTS in_sentence_seq,in_layer_names
ASSUME /\ in_sentence_seq \in Seq(1..5)
/\ in_layer_names \subseteq 0..10
VARIABLES in_seq,layer_set,cur_state,cur_scope,rule_nums,layer_connection_set
vars == << in_seq,layer_set,cur_state,cur_scope,rule_nums,layer_connection_set >>
layer_range == {{x,y}:x \in 0..10,y \in -1..10}
layer_connection_range == {<<x,y,z>>: x \in layer_range , y \in layer_range , z \in layer_range}
TypeOK == /\ in_seq \in Seq(1..5)
/\ layer_set \subseteq layer_range
/\ cur_state \in 0..5
/\ cur_scope \in -1..10
/\ rule_nums \in 0..10
/\ layer_connection_set \subseteq layer_connection_range
Init == /\ in_seq = in_sentence_seq
/\ layer_set = {{x,y}:x \in in_layer_names,y \in {-1}}
/\ cur_state = 0
/\ cur_scope = -1
/\ rule_nums = 0
/\ layer_connection_set = {}
state_changer == /\ Len(in_seq) >= 1
/\ cur_state' = Head(in_seq)
/\ in_seq' = Tail(in_seq)
/\ UNCHANGED << layer_set,cur_scope,rule_nums,layer_connection_set >>
state_stabler == /\ Len(in_seq) = 0
/\ cur_state'= 0
/\ UNCHANGED << in_seq,layer_set,cur_scope,rule_nums,layer_connection_set >>
scope_changer == /\ cur_state = 5
/\ cur_scope' = -1
/\ UNCHANGED << in_seq,layer_set,cur_state,rule_nums,layer_connection_set >>
derived_def_global ==
LET
temp_num == CHOOSE x \in 0..10: {x,-1} \notin layer_set
temp == {temp_num,-1}
temp_one_num == CHOOSE x \in 0..10: {x,-1} \in layer_set
temp_two_num == CHOOSE x \in 0..10: {x,-1} \in (layer_set\{temp})
temp_one == {temp_one_num,-1}
temp_two == {temp_two_num,-1}
IN
/\ cur_state = 1
/\ cur_scope = -1
/\ layer_set' = layer_set \union temp
/\ layer_connection_set' = layer_connection_set \union {<<temp_one,temp_two,temp>>}
/\ UNCHANGED << in_seq,cur_state,cur_scope,rule_nums >>
rule_head == /\ cur_state = 2
/\ cur_scope' = drc_rule_nums
/\ rule_nums' = rule_nums + 1
/\ UNCHANGED << in_seq,layer_set,cur_state,layer_connection_set >>
derived_def_rule ==
LET
temp_num == CHOOSE x \in 0..10: {x,rule_nums} \notin layer_set
temp_one == CHOOSE z \in {{x,y}: x \in 0..10, y \in {-1,rule_nums}}: z \in layer_set
temp_two == CHOOSE z \in {{x,y}: x \in 0..10, y \in {-1,rule_nums}}: z \in (layer_set\{temp_one})
temp == {temp_num,rule_nums}
IN
/\ cur_state = 3
/\ layer_set' = layer_set \union temp
/\ layer_connection_set' = layer_connection_set \union {<<temp_one,temp_two,temp>>}
/\ UNCHANGED << in_seq,cur_state,cur_scope,rule_nums >>
check_statement ==
LET
temp_num == CHOOSE x \in 0..10: {x,rule_nums} \notin layer_set
temp_one == CHOOSE z \in {{x,y}: x \in 0..10, y \in {-1,rule_nums}}: z \in layer_set
temp_two == CHOOSE z \in {{x,y}: x \in 0..10, y \in {-1,rule_nums}}: z \in (layer_set\{temp_one})
temp == {temp_num,rule_nums}
IN
/\ cur_state = 4
/\ layer_set' = layer_set \union temp
/\ layer_connection_set' = layer_connection_set \union {<<temp_one,temp_two,temp>>}
/\ UNCHANGED << in_seq,cur_state,cur_scope,rule_nums >>
Next == state_changer \/ state_stabler \/ scope_changer \/ derived_def_global \/ rule_head \/ derived_def_rule \/ check_statement
Spec == Init /\ [][Next]_vars
=============================================================================
I check my spec using in_layer_names <- {1,2,3,4} and in_sentence_seq <- <<1,2,3,4,5>>.Both in ordinary assignments.
And my problems are as follows:
1.TLC reports actions derived_def_global,derived_def_rule,check_statement are never enabled.
2.TLC reports error no.1 that my spec is attempting to compare integer 0 with non-integer:
{-1, 3}.
3.TLC reports error no.2 occurred when TLC was evaluating the nested
expressions in line 75 and 76.
I wonder how to rewrite my spec to make it run as what I think and solve these problems.And I hope my silly descriptions and problems won't bother you and make you angry.(
Thank you.
As per my comment, you may solve some of your problems (and get closer to the system you are trying to model) by replacing CHOOSE with \E. For example, you could rewrite check_statement this way:
check_statement ==
\E temp_num \in 0..10:
/\ {temp_num,rule_nums} \notin layer_set
/\ \E temp_one \in {{x,y}: x \in 0..10, y \in {-1,rule_nums}}:
/\ temp_one \in layer_set
/\ \E temp_two \in ...:
/\ ...
This is a good idea because in TLA+ CHOOSE performs an arbitrary but deterministic choice, and I suspect you actually want to explore every possible choice.

Reproducing deadlock in TLA+

I'm trying to reproduce a deadlock from Herlihy's "The Art of Multiprocessor Programming" in TLA+. In the following code when a thread wants to acquire a lock it marks itself as a victim and proceed only when another thread becomes a victim. There is a deadlock here if another thread never comes.
class LockTwo implements Lock {
private int victim;
public void lock() {
int i = ThreadID.get();
victim = i; // let the other go first
while (victim == i) {} // wait
}
public void unlock() {}
}
The TLA+ spec is as follows:
------------------------------ MODULE LockTwo ------------------------------
CONSTANT Thread
VARIABLE victim, owner, wasVictim
Null == CHOOSE v: v \notin Thread
Init ==
/\ victim = Null
/\ owner = [t \in Thread |-> FALSE]
/\ wasVictim = [t \in Thread |-> FALSE]
TypeOK ==
/\ victim \in Thread \cup {Null}
/\ owner \in [Thread -> BOOLEAN]
/\ wasVictim \in [Thread -> BOOLEAN]
BecomeVictim(t) ==
/\ wasVictim[t] = FALSE
/\ owner[t] = FALSE
/\ victim' = t
/\ wasVictim' = [wasVictim EXCEPT ![t] = TRUE]
/\ UNCHANGED owner
AcquireLock(t) ==
/\ wasVictim[t] = TRUE
/\ victim # t
/\ owner' = [owner EXCEPT ![t] = TRUE]
/\ wasVictim' = [wasVictim EXCEPT ![t] = FALSE]
/\ UNCHANGED victim
ReleaseLock(t) ==
/\ owner[t] = TRUE
/\ owner' = [owner EXCEPT ![t] = FALSE]
/\ UNCHANGED <<victim, wasVictim>>
Next ==
\E t \in Thread: BecomeVictim(t) \/ AcquireLock(t) \/ ReleaseLock(t)
MutualExclusion ==
\A t1, t2 \in Thread: (t1 # t2) => ~ (owner[t1] /\ owner[t2])
EventualSuccess ==
\A t \in Thread: (victim = t) ~> owner[t]
Spec == Init /\ [][Next]_<<victim, owner, wasVictim>> /\ EventualSuccess
=============================================================================
TLA spec runs fine with Thread = {t1, t2} where t1 and t2 are model values.
How to make TLA to report a deadlock?
See answer by Leslie Lamport on the semi-official Google Group: https://groups.google.com/forum/#!topic/tlaplus/rp5cE4IzEnM
(Mirror: http://discuss.tlapl.us/msg03229.html)

Transitive closure with quantifiers in Alloy

For the setup, I have a set of theorems, each with a set of values as a premise, a label, and a value it proves.
1. A /\ B => C
2. C => D
2. A => D // note same label as C => D
3. B /\ C => V
4. ...
I also have the following constraints:
Labels and premises are fixed for each theorem. One theorem always belongs to label 1 and always has A /\ B as a premise, theorems C => ? and D => ? both always belong to label 2, etc. There may be distinct theorems with the same premise belonging to different labels. For example, it's possible that I could have 4. C => A, even thought we already have 2. C => D.
All premises are of the form A /\ B /\ ... /\ N. I will never have A /\ (B \/ C) as a premise, nor will I have ~A. But I could have two theorems that share a label, one with A /\ B as a premise and one with A /\ C.
The values each theorem proves is variable, and in fact is the only thing that varies. Each theorem may prove at most one value.
All theorems with the same label must prove the same value. If 2. C => (does not prove anything), then I must also have 2. A =>. At most one label can prove a given value. This means it makes sense to write this example as 1. C 2. D 3. V ...
A value is "free" if no theorem proves it. V is never free.
A value is "provable" if it is A) free, B) belongs to a theorem where the premise is satisfiable with provable values.
A model is valid if V is provable. In this case it is, since A and B are free, which gets us C, which gets us V. However, 1. A 2. C 3. V is invalid. What I'm trying to do is figure out which additional facts are required to make all possible models valid. For example, that counterexample disappears if we add a fact that says "A proved value can't be its own premise.
Here's an alloy model representing this:
abstract sig Label {
proves: disj lone Value
}
one sig L1, L2, LV extends Label{}
abstract sig Value{}
one sig A, B, C, D, V extends Value {}
sig Theorem {
premise: Value set -> Label
}
fun free: set Value {
Value - Label.proves
}
pred solvable(v: Value) {
v in free or // ???
}
pred Valid {
solvable[V]
}
pred DefaultTheorems {
one disj T1, T2, T3, T4: Theorem | {
#Theorem = 4
T1.premise = (A + B) -> L1
T2.premise = C -> L2
T3.premise = A -> L2
T4.premise = (B + C) -> LV
}
LV.proves = V
}
check { DefaultTheorems => Valid } for 7
The problem I have is in the solvable predicate. I need it to obey the conjunctions and work for an arbitrary depth. One possible solution would be to use the transitive closure. But if I do v in free or v in free.*(Theorem.(premise.proves)), the model becomes too permissive. It would say that if C is free, then A /\ C -> A is provable. This is because Alloy does not permit sets inside sets, so it collapses {A C} -> A into A -> C and A -> A.
On the other hand, I could write it as
pred solvable(v: Value) {
v in free or some t: Theorem |
let premise' = (t.premise).(proves.v) |
some v' and all v': premise' | solvable[v']
But this is very slow and also has a maximum recursion depth of 3. Is there a way to get the speed and arbitrary depth of using a closure with the accuracy of using a quantifier? I suppose I could add a trace, where each step successively proves more values, but it seems odd to enforce an ordering on a system that doesn't need it.
After a lot of experimentation, I've decided that the only good way to do this is with a trace. Here's the final spec if anybody's interested:
open util/ordering[Step]
sig Step {}
abstract sig Label {
proves: disj lone Value
}
one sig L1, L2, LV extends Label{}
abstract sig Value {
proven_at: set Step
}
one sig A, B, C, D, V extends Value {}
sig Theorem {
premise: Value set -> Label
}
fun free: set Value {
Value - Label.proves
}
pred solvable(v: Value, s: Step) {
v in proven_at.s or
some t: Theorem |
let premise' = (t.premise).(proves.v) |
some premise' and all v': premise' |
v' in proven_at.s
}
pred Valid {
solvable[V, last]
}
fact Trace {
free = proven_at.first
all s: Step - last |
let s' = s.next |
proven_at.s' = proven_at.s + {v: Value | solvable[v, s]}
}
pred DefaultTheorems {
one disj T1, T2, T3, T4: Theorem | {
#Theorem = 4
T1.premise = (A + B) -> L1
T2.premise = C -> L2
T3.premise = A -> L2
T4.premise = (B + C) -> LV
}
LV.proves = V
}
check { DefaultTheorems => Valid } for 8 but 4 Step

Check that system passes all the states

A variable state stands for state of a system, for instance state \in {"ready", "prepare", "do", "cleanup", "done"}. How to express condition that state should eventually pass all the five states (in any order)?
Working example (accepted answer):
EXTENDS Naturals
VARIABLE n
Init == n = 1
Next == IF n < 3 THEN n' = n + 1 ELSE n' = n
Spec == Init /\ [][Next]_<<n>> /\ WF_<<n>>(Next)
Check == \A s \in {1,2,3}: <>(s = n) \* This goes: Model Overview >
\* > "What to check?" > Properties
Given States = {"ready", "prepare", "do", "cleanup", "done"}, you can check that it reaches some given state with
<>(state = "ready")
And you can check that it reaches all states with
\A s \in States: <>(state = s)

How to translate formula into TLA+ code

I've written a TLA+ spec of the Towers of Hanoi problem:
TEX
ASCII
------------------------------- MODULE Hanoi -------------------------------
EXTENDS Sequences, Integers
VARIABLE A, B, C
CanMove(x,y) == /\ Len(x) > 0
/\ IF Len(y) > 0 THEN Head(y) > Head(x) ELSE TRUE
Move(x,y,z) == /\ CanMove(x,y)
/\ x' = Tail(x)
/\ y' = <<Head(x)>> \o y
/\ z' = z
Invariant == C /= <<1,2,3>> \* When we win!
Init == /\ A = <<1,2,3>>
/\ B = <<>>
/\ C = <<>>
Next == \/ Move(A,B,C) \* Move A to B
\/ Move(A,C,B) \* Move A to C
\/ Move(B,A,C) \* Move B to A
\/ Move(B,C,A) \* Move B to C
\/ Move(C,A,B) \* Move C to A
\/ Move(C,B,A) \* Move C to B
=============================================================================
The TLA Model checker will solve the puzzle for me when I specify the Invariant formula as an Invariant.
I want to make it a bit less verbose though, ideally I don't want to pass in the unchanged variable to Move(), but I can't figure out how. What I want to do is to write
Move(x,y) == /\ CanMove(x,y)
/\ x' = Tail(x)
/\ y' = <<Head(x)>> \o y
/\ UNCHANGED (Difference of and {A,B,C} and {y,x})
How can I express that in the TLA language?
Instead of variables A, B, C, you should have a single sequence, towers, where the towers are indexes. This would also have the advantage of being generic in the number of towers. Your Next formula would be shorter, too:
CanMove(i,j) == /\ Len(towers[i]) > 0
/\ Len(towers[j]) = 0 \/ Head(towers[j]) > Head(towers[i])
Move(i, j) == /\ CanMove(i, j)
/\ towers' = [towers EXCEPT ![i] = Tail(#),
![j] = <<Head(towers[i])>> \o #]
Init == towers = << <<1,2,3>>, <<>>, <<>> >> \* Or something more generic
Next == \E i, j \in DOMAIN towers: i /= j /\ Move(i, j)
Alternatively, if you want to continue using letters, you can use a record instead of a sequence for towers, and all you need to change in my suggested spec is:
Init == towers = [a |-> <<1, 2, 3>>, b |-> <<>>, c |-> <<>>]

Resources