use warp_types_bmc::TransitionSystem;
use warp_types_pdr::{check, PdrResult};
use warp_types_sat::literal::Lit;
fn safe_constant() -> TransitionSystem {
let mut sys = TransitionSystem::new(1);
sys.add_initial(vec![Lit::neg(0)]); sys.add_transition(vec![Lit::neg(0), Lit::pos(1)]); sys.add_transition(vec![Lit::pos(0), Lit::neg(1)]); sys.add_property(vec![Lit::neg(0)]); sys
}
fn unsafe_counter() -> TransitionSystem {
let mut sys = TransitionSystem::new(2);
sys.add_initial(vec![Lit::neg(0)]); sys.add_initial(vec![Lit::neg(1)]);
sys.add_transition(vec![Lit::pos(0), Lit::pos(2)]); sys.add_transition(vec![Lit::neg(0), Lit::neg(2)]);
sys.add_transition(vec![Lit::neg(0), Lit::neg(1), Lit::neg(3)]);
sys.add_transition(vec![Lit::neg(0), Lit::pos(1), Lit::pos(3)]);
sys.add_transition(vec![Lit::pos(0), Lit::neg(1), Lit::pos(3)]);
sys.add_transition(vec![Lit::pos(0), Lit::pos(1), Lit::neg(3)]);
sys.add_property(vec![Lit::neg(0), Lit::neg(1)]); sys
}
fn invariant_discovery() -> TransitionSystem {
let mut sys = TransitionSystem::new(2);
sys.add_initial(vec![Lit::neg(0)]); sys.add_initial(vec![Lit::neg(1)]);
sys.add_transition(vec![Lit::pos(0), Lit::pos(2)]); sys.add_transition(vec![Lit::neg(0), Lit::neg(2)]);
sys.add_transition(vec![Lit::neg(1), Lit::pos(3)]); sys.add_transition(vec![Lit::pos(1), Lit::neg(3)]);
sys.add_property(vec![Lit::neg(1)]);
sys
}
fn main() {
println!("warp-types-pdr: Phase-typed Property-Directed Reachability\n");
println!("── Example 1: constant 0, property ¬s₀ ──");
print_result(&check(&safe_constant(), 20, 0));
println!("\n── Example 2: 2-bit counter, property ¬(s₀ ∧ s₁) ──");
print_result(&check(&unsafe_counter(), 20, 0));
println!("\n── Example 3: invariant discovery, property ¬(s₁ ∧ ¬s₀) ──");
print_result(&check(&invariant_discovery(), 20, 0));
}
fn print_result(result: &PdrResult) {
match result {
PdrResult::Safe { invariant_frame } => {
println!(" SAFE: inductive invariant at frame {invariant_frame}");
}
PdrResult::CounterexampleFound { depth, trace } => {
println!(" UNSAFE: counterexample at depth {depth}");
for (t, frame) in trace.iter().enumerate() {
let bits: String = frame.iter().map(|&b| if b { '1' } else { '0' }).collect();
println!(" t={t}: {bits}");
}
}
PdrResult::Exhausted { frames_explored } => {
println!(" EXHAUSTED: explored {frames_explored} frames");
}
}
}