@ -1704,10 +1704,10 @@ let and_fold_subst_variables phi0 ~up_to_f:phi_foreign ~init ~f:f_var =
module QuantifierElimination : sig
val eliminate_vars : keep _pre: Var . Set . t -> keep_post : Var . Set . t -> t -> t SatUnsat . t
(* * [eliminate_vars ~keep _pre ~keep_post φ] substitutes every variable [x] in [φ] with [x']
whenever [ x' ] is a distinguished representative of the equivalence class of [ x ] in [ φ ] such
that [ x' ∈ keep_pre ∪ keep_post ] * )
val eliminate_vars : keep : Var . Set . t -> t -> t SatUnsat . t
(* * [eliminate_vars ~keep φ] substitutes every variable [x] in [φ] with [x'] whenever [x'] is a
distinguished representative of the equivalence class of [ x ] in [ φ ] such that
[ x' ∈ keep_pre ∪ keep_post ] * )
end = struct
exception Contradiction
@ -1749,12 +1749,8 @@ end = struct
; both = subst_var_formula subst phi . both }
let eliminate_vars ~ keep_pre ~ keep_post phi =
let subst =
VarUF . reorient
~ should_keep : ( fun x -> Var . Set . mem x keep_pre | | Var . Set . mem x keep_post )
phi . known . var_eqs
in
let eliminate_vars ~ keep phi =
let subst = VarUF . reorient ~ should_keep : ( fun x -> Var . Set . mem x keep ) phi . known . var_eqs in
try Sat ( subst_var subst phi ) with Contradiction -> Unsat
end
@ -1841,18 +1837,18 @@ module DeadVariables = struct
(* * Get rid of atoms when they contain only variables that do not appear in atoms mentioning
variables in [ keep _pre] or [ keep_post ] , or variables appearing in atoms together with
variables in these sets , and so on . In other words , the variables to keep are all the ones
transitively reachable from variables in [ keep _pre ∪ keep_post ] in the graph connecting two
variables whenever they appear together in a same atom of the formula . * )
let eliminate ~ keep_pre ~ keep_post phi =
variables in [ keep ] , or variables appearing in atoms together with variables in these sets ,
and so on . In other words , the variables to keep are all the ones transitively reachable from
variables in [ keep ] in the graph connecting two variables whenever they appear together in a
same atom of the formula . * )
let eliminate ~ can_be_pruned ~ keep phi =
(* We only consider [phi.both] when building the relation. Considering [phi.known] and
[ phi . pruned ] as well could lead to us keeping more variables around , but that's not necessarily
a good idea . Ignoring them means we err on the side of reporting potentially slightly more
issues than we would otherwise , as some atoms in [ phi . pruned ] may vanish unfairly as a
result . * )
let var_graph = build_var_graph phi . both in
let vars_to_keep = get_reachable_from var_graph ( Var . Set . union keep _pre keep_post ) in
let vars_to_keep = get_reachable_from var_graph keep in
L . d_printfln " Reachable vars: %a " Var . Set . pp vars_to_keep ;
let simplify_phi phi =
let var_eqs =
@ -1877,24 +1873,24 @@ module DeadVariables = struct
let known = simplify_phi phi . known in
let both = simplify_phi phi . both in
let pruned =
(* discard atoms that callers have no way of influencing, i.e. those that do not contain
variables related to variables in the pre * )
let vars_to_keep_pre = get_reachable_from var_graph keep_pre in
Atom . Set . filter ( fun atom -> not ( Atom . has_var_notin vars_to_keep_pre atom ) ) phi . pruned
(* discard atoms that callers have no way of influencing, i.e. more or less those that do not
contain variables related to variables in the pre * )
let closed_prunable_vars = get_reachable_from var_graph can_be_pruned in
Atom . Set . filter ( fun atom -> not ( Atom . has_var_notin closed_prunable_vars atom ) ) phi . pruned
in
{ known ; pruned ; both }
end
let simplify tenv ~ get_dynamic_type ~ keep_pre ~ keep_post phi =
let simplify tenv ~ get_dynamic_type ~ can_be_pruned ~ keep phi =
let open SatUnsat . Import in
let * phi , new_eqs = normalize tenv ~ get_dynamic_type phi in
L . d_printfln_escaped " @[Simplifying %a@,wrt %a ( pre) and %a (post) @]" pp phi Var . Set . pp keep _pre
Var . Set . pp keep_post ;
L . d_printfln_escaped " @[Simplifying %a@,wrt %a ( keep), with prunables=%a @]" pp phi Var . Set . pp keep
Var . Set . pp can_be_pruned ;
(* get rid of as many variables as possible *)
let + phi = QuantifierElimination . eliminate_vars ~ keep _pre ~ keep_post phi in
let + phi = QuantifierElimination . eliminate_vars ~ keep phi in
(* TODO: doing [QuantifierElimination.eliminate_vars; DeadVariables.eliminate] a few times may
eliminate even more variables * )
let phi = DeadVariables . eliminate ~ keep_pre ~ keep_post phi in
let phi = DeadVariables . eliminate ~ can_be_pruned ~ keep phi in
( phi , new_eqs )