219 lines
7.2 KiB
Plaintext
219 lines
7.2 KiB
Plaintext
|
|
// NEGATIVE TEST: This file contains an INTENTIONALLY INCOMPLETE solution.
|
||
|
|
//
|
||
|
|
// The trace for problem2 is missing the wire connecting f1's output to f2's input.
|
||
|
|
// When Trace theory has proper wire axioms, this should FAIL axiom checking.
|
||
|
|
//
|
||
|
|
// This file serves as a regression test: if this ever starts passing,
|
||
|
|
// either the axioms are broken or the solver has a bug.
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// THEORY: PetriNet
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
theory PetriNet {
|
||
|
|
P : Sort;
|
||
|
|
T : Sort;
|
||
|
|
in : Sort;
|
||
|
|
out : Sort;
|
||
|
|
|
||
|
|
in/src : in -> P;
|
||
|
|
in/tgt : in -> T;
|
||
|
|
out/src : out -> T;
|
||
|
|
out/tgt : out -> P;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// THEORY: Marking
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
theory (N : PetriNet instance) Marking {
|
||
|
|
token : Sort;
|
||
|
|
token/of : token -> N/P;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// THEORY: ReachabilityProblem
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
theory (N : PetriNet instance) ReachabilityProblem {
|
||
|
|
initial_marking : N Marking instance;
|
||
|
|
target_marking : N Marking instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// THEORY: Trace (with Wire axioms)
|
||
|
|
//
|
||
|
|
// A trace records transition firings and token flow via wires.
|
||
|
|
// The completeness axioms (ax5, ax6) ensure every arc is accounted for.
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
theory (N : PetriNet instance) Trace {
|
||
|
|
// Firings
|
||
|
|
F : Sort;
|
||
|
|
F/of : F -> N/T;
|
||
|
|
|
||
|
|
// Wires connect output arcs of firings to input arcs of other firings
|
||
|
|
W : Sort;
|
||
|
|
W/src_firing : W -> F;
|
||
|
|
W/src_arc : W -> N/out;
|
||
|
|
W/tgt_firing : W -> F;
|
||
|
|
W/tgt_arc : W -> N/in;
|
||
|
|
|
||
|
|
// Wire coherence: source arc must belong to source firing's transition
|
||
|
|
ax/wire_src_coherent : forall w : W.
|
||
|
|
|- w W/src_arc N/out/src = w W/src_firing F/of;
|
||
|
|
|
||
|
|
// Wire coherence: target arc must belong to target firing's transition
|
||
|
|
ax/wire_tgt_coherent : forall w : W.
|
||
|
|
|- w W/tgt_arc N/in/tgt = w W/tgt_firing F/of;
|
||
|
|
|
||
|
|
// Wire place coherence: wire connects matching places
|
||
|
|
ax/wire_place_coherent : forall w : W.
|
||
|
|
|- w W/src_arc N/out/tgt = w W/tgt_arc N/in/src;
|
||
|
|
|
||
|
|
// Terminals
|
||
|
|
input_terminal : Sort;
|
||
|
|
output_terminal : Sort;
|
||
|
|
input_terminal/of : input_terminal -> N/P;
|
||
|
|
output_terminal/of : output_terminal -> N/P;
|
||
|
|
|
||
|
|
// Terminals connect to specific firings and arcs
|
||
|
|
input_terminal/tgt_firing : input_terminal -> F;
|
||
|
|
input_terminal/tgt_arc : input_terminal -> N/in;
|
||
|
|
output_terminal/src_firing : output_terminal -> F;
|
||
|
|
output_terminal/src_arc : output_terminal -> N/out;
|
||
|
|
|
||
|
|
// Terminal coherence axioms
|
||
|
|
ax/input_terminal_coherent : forall i : input_terminal.
|
||
|
|
|- i input_terminal/tgt_arc N/in/tgt = i input_terminal/tgt_firing F/of;
|
||
|
|
|
||
|
|
ax/output_terminal_coherent : forall o : output_terminal.
|
||
|
|
|- o output_terminal/src_arc N/out/src = o output_terminal/src_firing F/of;
|
||
|
|
|
||
|
|
// Terminal place coherence
|
||
|
|
ax/input_terminal_place : forall i : input_terminal.
|
||
|
|
|- i input_terminal/of = i input_terminal/tgt_arc N/in/src;
|
||
|
|
|
||
|
|
ax/output_terminal_place : forall o : output_terminal.
|
||
|
|
|- o output_terminal/of = o output_terminal/src_arc N/out/tgt;
|
||
|
|
|
||
|
|
// COMPLETENESS: Every arc of every firing must be accounted for.
|
||
|
|
|
||
|
|
// Input completeness: catches the missing wire in solution2!
|
||
|
|
ax/input_complete : forall f : F, arc : N/in.
|
||
|
|
arc N/in/tgt = f F/of |-
|
||
|
|
(exists w : W. w W/tgt_firing = f, w W/tgt_arc = arc) \/
|
||
|
|
(exists i : input_terminal. i input_terminal/tgt_firing = f, i input_terminal/tgt_arc = arc);
|
||
|
|
|
||
|
|
// Output completeness: every output arc must be captured
|
||
|
|
ax/output_complete : forall f : F, arc : N/out.
|
||
|
|
arc N/out/src = f F/of |-
|
||
|
|
(exists w : W. w W/src_firing = f, w W/src_arc = arc) \/
|
||
|
|
(exists o : output_terminal. o output_terminal/src_firing = f, o output_terminal/src_arc = arc);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// THEORY: Iso
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
theory (X : Sort) (Y : Sort) Iso {
|
||
|
|
fwd : X -> Y;
|
||
|
|
bwd : Y -> X;
|
||
|
|
|
||
|
|
// Roundtrip axioms ensure this is a true bijection
|
||
|
|
fb : forall x : X. |- x fwd bwd = x;
|
||
|
|
bf : forall y : Y. |- y bwd fwd = y;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// THEORY: Solution
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
theory (N : PetriNet instance) (RP : N ReachabilityProblem instance) Solution {
|
||
|
|
trace : N Trace instance;
|
||
|
|
initial_iso : (trace/input_terminal) (RP/initial_marking/token) Iso instance;
|
||
|
|
target_iso : (trace/output_terminal) (RP/target_marking/token) Iso instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// INSTANCE: ExampleNet
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
instance ExampleNet : PetriNet = {
|
||
|
|
A : P; B : P; C : P;
|
||
|
|
ab : T; ba : T; abc : T;
|
||
|
|
|
||
|
|
ab_in : in; ab_in in/src = A; ab_in in/tgt = ab;
|
||
|
|
ab_out : out; ab_out out/src = ab; ab_out out/tgt = B;
|
||
|
|
|
||
|
|
ba_in : in; ba_in in/src = B; ba_in in/tgt = ba;
|
||
|
|
ba_out : out; ba_out out/src = ba; ba_out out/tgt = A;
|
||
|
|
|
||
|
|
abc_in1 : in; abc_in1 in/src = A; abc_in1 in/tgt = abc;
|
||
|
|
abc_in2 : in; abc_in2 in/src = B; abc_in2 in/tgt = abc;
|
||
|
|
abc_out : out; abc_out out/src = abc; abc_out out/tgt = C;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// PROBLEM 2: Can we reach C from two A-tokens?
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
instance problem2 : ExampleNet ReachabilityProblem = {
|
||
|
|
initial_marking = {
|
||
|
|
t1 : token; t1 token/of = ExampleNet/A;
|
||
|
|
t2 : token; t2 token/of = ExampleNet/A;
|
||
|
|
};
|
||
|
|
target_marking = {
|
||
|
|
t : token;
|
||
|
|
t token/of = ExampleNet/C;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================
|
||
|
|
// INCOMPLETE SOLUTION 2: This should FAIL!
|
||
|
|
//
|
||
|
|
// The trace has two firings (f1: ab, f2: abc) but NO WIRE
|
||
|
|
// connecting f1's output to f2's B-input. The axiom
|
||
|
|
// ax/must_be_fed should catch this: f2's abc_in2 arc
|
||
|
|
// is neither wired nor terminal-fed.
|
||
|
|
// ============================================================
|
||
|
|
|
||
|
|
instance solution2_incomplete : ExampleNet problem2 Solution = {
|
||
|
|
trace = {
|
||
|
|
f1 : F; f1 F/of = ExampleNet/ab;
|
||
|
|
f2 : F; f2 F/of = ExampleNet/abc;
|
||
|
|
|
||
|
|
// Input terminals for the two initial A-tokens
|
||
|
|
it1 : input_terminal;
|
||
|
|
it1 input_terminal/of = ExampleNet/A;
|
||
|
|
it1 input_terminal/tgt_firing = f1;
|
||
|
|
it1 input_terminal/tgt_arc = ExampleNet/ab_in;
|
||
|
|
|
||
|
|
it2 : input_terminal;
|
||
|
|
it2 input_terminal/of = ExampleNet/A;
|
||
|
|
it2 input_terminal/tgt_firing = f2;
|
||
|
|
it2 input_terminal/tgt_arc = ExampleNet/abc_in1;
|
||
|
|
|
||
|
|
// Output terminal for the final C-token
|
||
|
|
ot : output_terminal;
|
||
|
|
ot output_terminal/of = ExampleNet/C;
|
||
|
|
ot output_terminal/src_firing = f2;
|
||
|
|
ot output_terminal/src_arc = ExampleNet/abc_out;
|
||
|
|
|
||
|
|
// INTENTIONALLY MISSING: The wire from f1's ab_out to f2's abc_in2!
|
||
|
|
// This means f2's abc_in2 (the B-input) is not fed by anything.
|
||
|
|
};
|
||
|
|
|
||
|
|
initial_iso = {
|
||
|
|
trace/it1 fwd = problem2/initial_marking/t1;
|
||
|
|
trace/it2 fwd = problem2/initial_marking/t2;
|
||
|
|
problem2/initial_marking/t1 bwd = trace/it1;
|
||
|
|
problem2/initial_marking/t2 bwd = trace/it2;
|
||
|
|
};
|
||
|
|
|
||
|
|
target_iso = {
|
||
|
|
trace/ot fwd = problem2/target_marking/t;
|
||
|
|
problem2/target_marking/t bwd = trace/ot;
|
||
|
|
};
|
||
|
|
}
|