[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 5 years ago committed by Facebook GitHub Bot
parent 50b94dbbd6
commit 5cceead7ae

@ -1168,29 +1168,50 @@ end = struct
Atom.eval atom' |> sat_of_eval_result 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 = let and_atom atom phi =
normalize_atom phi atom normalize_atom phi atom
>>= function >>= function
| None -> | None ->
Sat phi Sat (false, phi)
| Some (Atom.Equal (Linear l, Const c)) | Some (Atom.Equal (Const c, Linear l)) -> | 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 (* 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 they end up only on one side, hence only this match case is needed to detect linear
equalities *) equalities *)
solve_eq l (LinArith.of_q c) phi let+ phi' = solve_eq l (LinArith.of_q c) phi in
(true, phi')
| Some atom' -> | 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 normalize_atoms phi =
let atoms0 = phi.atoms in 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 -> IContainer.fold_of_pervasives_set_fold Atom.Set.fold atoms0 ~init ~f:(fun acc atom ->
let* phi = acc in let* changed, phi = acc in
and_atom atom phi ) 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 end
let and_mk_atom mk_atom op1 op2 phi = let and_mk_atom mk_atom op1 op2 phi =

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

Loading…
Cancel
Save