Plan Synthesis: Wolf–Goat–Cabbage (NuSMV, w/loops)¶
Description of the Case Study¶
We consider plan synthesis (PS) in the classic wolf–goat–cabbage puzzle, following . A farmer must ferry three items across a river, carrying only one at a time. Certain configurations are unsafe (wolf with goat, goat with cabbage) if left unattended. The goal is to synthesize a single plan that always avoids all local requirement violations.
This is an \(\exists_{\text{big}}\,\forall_{\text{small}}\) problem: we search for one big plan that, for every small requirement automaton (encapsulating local violations), maintains safety. We provide a satisfiable instance (a robust plan exists) and an unsatisfiable one (a broken plan step that inevitably violates a requirement).
The NuSMV model(s)¶
MODULE main
VAR
a_state : 0..16;
ASSIGN
init(a_state) := 0;
next(a_state) :=
case
a_state = 0 : {1, 8, 9};
a_state = 1 : 2;
a_state = 2 : 3;
a_state = 3 : 4;
a_state = 4 : {5, 14};
a_state = 5 : 6;
a_state = 6 : 7;
a_state = 7 : 0;
a_state = 8 : 10;
a_state = 9 : 4;
a_state = 10 : 11;
a_state = 11 : 12;
a_state = 12 : 13;
a_state = 13 : 0;
a_state = 14 : 15;
a_state = 15 : {16, 3};
a_state = 16 : 0;
TRUE : a_state; -- totalize (remove if you want a strict graph)
esac;
-- Violation atoms (match y_labels 1..4)
DEFINE
bad_gc := (a_state = 8); -- L=GC,R=FW
bad_fw_gc := (a_state = 15); -- L=FW,R=GC
bad_gw := (a_state = 9); -- L=GW,R=FC
bad_fc := (a_state = 12); -- L=FC,R=GW
safeA := !(bad_gc | bad_fw_gc | bad_gw | bad_fc);
MODULE main
VAR
b_state : 0..4;
ASSIGN
init(b_state) := 0;
next(b_state) :=
case
b_state = 0 : {1, 2, 3, 4}; -- branch to any violation
b_state = 1 : 1; -- self-loops
b_state = 2 : 2;
b_state = 3 : 3;
b_state = 4 : 4;
TRUE : b_state; -- totalize (remove if not desired)
esac;
DEFINE
gc := (b_state = 1);
fw_gc := (b_state = 2);
gw := (b_state = 3);
fc := (b_state = 4);
MODULE main
VAR
a_state : 0..16;
ASSIGN
init(a_state) := 0;
next(a_state) :=
case
a_state = 0 : {1, 8, 9};
a_state = 1 : 2;
a_state = 2 : 8;
a_state = 3 : 4;
a_state = 4 : {5, 14};
a_state = 5 : 6;
a_state = 6 : 7;
a_state = 7 : 0;
a_state = 8 : 10;
a_state = 9 : 4;
a_state = 10 : 11;
a_state = 11 : 12;
a_state = 12 : 13;
a_state = 13 : 0;
a_state = 14 : 15;
a_state = 15 : {16, 3};
a_state = 16 : 0;
TRUE : a_state; -- totalize (remove if you want a strict graph)
esac;
-- Violation atoms (match y_labels 1..4)
DEFINE
bad_gc := (a_state = 8); -- L=GC,R=FW
bad_fw_gc := (a_state = 15); -- L=FW,R=GC
bad_gw := (a_state = 9); -- L=GW,R=FC
bad_fc := (a_state = 12); -- L=FC,R=GW
safeA := !(bad_gc | bad_fw_gc | bad_gw | bad_fc);
The HyperLTL formula(s)¶
The paper formulates plan synthesis as ensuring that the plan’s action never matches any violation of the requirement automaton, at all times:
In our concrete encoding, the big model exposes four violation atoms
\(\mathit{bad\_gc},\ \mathit{bad\_fw\_gc},\ \mathit{bad\_gw},\ \mathit{bad\_fc}\)
and the small model exposes matching labels
\(\mathit{gc},\ \mathit{fw\_gc},\ \mathit{gw},\ \mathit{fc}\).
A pointwise version of \(\varphi_{\mathrm{PS}}\) is:
Exists A . Forall B . G((gc[B] | fw_gc[B] | gw[B] | fc[B]) -> (~bad_gc[A] & ~bad_fw_gc[A] & ~bad_gw[A] & ~bad_fc[A]))
References¶
Filiot, Emmanuel; Lagarde, Guillaume; Laroussinie, François; Markey, Nicolas; Raskin, Jean-François; and Sankur, Ocan. “Efficient Loop Conditions for Bounded Model Checking Hyperproperties.” arXiv:2301.06209, 2023.