Cubicle BRAB in Why3 index


module Cubicle_Bwd

  use import ref.Ref
  use import fol.FOL
  use import abstract_queue.AbstractQueue as Q
  use import reachability.Reachability

  (* remove unecessary axioms for solvers *)
  meta remove_prop prop extensionality
  meta remove_prop prop structure_exists
  meta remove_prop prop model_true
  meta remove_prop prop model_false
  meta remove_prop prop model_and
  meta remove_prop prop model_or
  meta remove_prop prop model_neg
  meta remove_prop prop valid_def
  (* meta remove_prop prop and_a *)
  (* meta remove_prop prop and_c *)
  (* meta remove_prop prop or_a *)
  (* meta remove_prop prop or_c *)
  meta remove_prop prop sat_def
  (* meta remove_prop prop sat_or *)
  meta remove_prop prop sat_neg
  meta remove_prop prop sat_and
  meta remove_prop prop valid_or
  meta remove_prop prop valid_neg
  meta remove_prop prop valid_and
  meta remove_prop prop valid_sat
  meta remove_prop prop pre_star_def2
  meta remove_prop prop pre_star_def3
  meta remove_prop prop reachable_imply
  meta remove_prop prop reachable_and
  meta remove_prop prop pre_and
  meta remove_prop prop pre_or
  meta remove_prop prop unsat_invalid
  meta remove_prop prop model_extensionality
  meta remove_prop prop forget_subsumed_or
  meta remove_prop prop imply_or
  meta remove_prop prop imply_bigger
  meta remove_prop prop imply_transitive
  meta remove_prop prop or_same
  meta remove_prop prop pre_star_bigger
  meta remove_prop prop reachable_bigger
  
  
  
  type result = Safe | Unsafe
  exception Unsafe_trace

  
  val visited : ref f
  val q : Q.t

    
  let bwd (tau : trans_rel) (init : f) (theta : f) =
    (* Soundness *)
    ensures { result = Safe -> not (reachable tau init theta) }
    (* Completeness *)
    ensures { result = Unsafe -> reachable tau init theta }
    visited := ffalse;
    Q.clear q;
    try
       if sat (init & theta) then raise Unsafe_trace;
       visited := theta ++ !visited;
       Q.push (pre tau theta) q;
       while not (Q.is_empty q) do
        invariant { not (sat (init & !visited)) &&
                    pre_star tau !visited = !visited ++ (pre_star tau q.formula) &&
                    pre_star tau theta = !visited ++ (pre_star tau q.formula) }
        let ghost old_q = Q.copy q in
        let phi = Q.pop q in
        if sat (init & phi) then raise Unsafe_trace;
        if not (phi |== !visited) then (
          let ghost old_v = !visited in
          visited := phi ++ !visited;
          Q.push (pre tau phi) q;
          assert {
                   !visited ++ (pre_star tau q.formula) =
	  	     old_v ++ pre_star tau phi ++ pre_star tau (~ phi & old_q.formula)

		   &&
	  
                   !visited ++ (pre_star tau q.formula) =
                     old_v ++ (pre_star tau (ttrue & (phi ++ old_q.formula))) }
        )
        else
          assert {
                valid ((~ (~ phi)) ++ (pre_star tau (~ phi)))

                &&

                !visited ++ (pre_star tau ((~ phi) & old_q.formula)) =
                (!visited ++ (ttrue ++ (pre_star tau (~ phi)))) & (pre_star tau !visited)

                &&

                !visited ++ (pre_star tau ((~ phi) & old_q.formula)) =
                ttrue & (pre_star tau !visited)
          }
        
       done;
      Safe
    with
        | Unsafe_trace -> Unsafe
        | Q.Empty -> absurd
    end
end

Generated by why3doc 0.82+git