[pulse] normalize again when we discover new linear eqs

Summary:
When normalizing discovers new linear arithmetic facts in
`normalize_linear_eqs` we go around once more. Do the same when atoms
become linear equalities.

Reviewed By: skcho

Differential Revision: D23264425

fbshipit-source-id: b355875f3
master
Jules Villard 4 years ago committed by Facebook GitHub Bot
parent 50b94dbbd6
commit 5cceead7ae

@ -1168,29 +1168,50 @@ end = struct
Atom.eval atom' |> sat_of_eval_result
(** return [(new_linear_equalities, phi ∧ atom)], where [new_linear_equalities] is [true] if
[phi.linear_eqs] was changed as a result *)
let and_atom atom phi =
normalize_atom phi atom
>>= function
| None ->
Sat phi
Sat (false, phi)
| Some (Atom.Equal (Linear l, Const c)) | Some (Atom.Equal (Const c, Linear l)) ->
(* NOTE: {!normalize_atom} calls {!Atom.eval}, which normalizes linear equalities so
they end up only on one side, hence only this match case is needed to detect linear
equalities *)
solve_eq l (LinArith.of_q c) phi
let+ phi' = solve_eq l (LinArith.of_q c) phi in
(true, phi')
| Some atom' ->
Sat {phi with atoms= Atom.Set.add atom' phi.atoms}
Sat (false, {phi with atoms= Atom.Set.add atom' phi.atoms})
let normalize_atoms phi =
let atoms0 = phi.atoms in
let init = Sat {phi with atoms= Atom.Set.empty} in
let init = Sat (false, {phi with atoms= Atom.Set.empty}) in
IContainer.fold_of_pervasives_set_fold Atom.Set.fold atoms0 ~init ~f:(fun acc atom ->
let* phi = acc in
and_atom atom phi )
let* changed, phi = acc in
let+ changed', phi = and_atom atom phi in
(changed || changed', phi) )
let normalize phi =
(* NOTE: we may consume a quadratic amount of [fuel] here since the fuel here is not consumed by
[normalize_linear_eqs] (i.e. [normalize_linear_eqs] does not return the remaining
fuel). That's ok because there's not much fuel to begin with, and as long as we're making
progress it's probably worth it anyway. *)
let rec normalize_with_fuel ~fuel phi =
let* new_linear_eqs, phi = normalize_linear_eqs ~fuel phi >>= normalize_atoms in
if new_linear_eqs && fuel > 0 then (
L.d_printfln "new linear equalities, consuming fuel (from %d)" fuel ;
normalize_with_fuel ~fuel:(fuel - 1) phi )
else (
L.d_printfln "ran out of fuel when normalizing" ;
Sat phi )
in
normalize_with_fuel ~fuel:base_fuel phi
let normalize phi = normalize_linear_eqs ~fuel:base_fuel phi >>= normalize_atoms
let and_atom atom phi = and_atom atom phi >>| snd
end
let and_mk_atom mk_atom op1 op2 phi =

@ -198,8 +198,8 @@ let%test_module "normalization" =
{|
true (no var=var)
&&
x = -v6 + v8 -1 y = 1/3·v6 z = 12 w = 7 v = 3 v7 = v8 -1
v8 = 1/12·v9 v9 = 0 v10 = 0
x = -v6 -1 y = 1/3·v6 z = 12 w = 7 v = 3 v7 = -1
v8 = 0 v9 = 0 v10 = 0
&&
true (no atoms)|}]
end )
@ -242,4 +242,9 @@ let%test_module "non-linear simplifications" =
let%expect_test "constant propagation: bitshift" =
simplify ~keep:[x_var] (of_binop Shiftlt (of_binop Shiftrt (i 0b111) (i 2)) (i 2) = x) ;
[%expect {|true (no var=var) && x = 4 && true (no atoms)|}]
let%expect_test "non-linear becomes linear" =
normalize (w = (i 2 * z) - i 3 && z = x * y && y = i 2) ;
[%expect
{|z=v8 w=v7 && x = 1/4·v6 y = 2 z = 1/2·v6 w = v6 -3 && true (no atoms)|}]
end )

Loading…
Cancel
Save