[sledge] Do not simplify Mul and Div terms

Summary:
The partial treatment of Mul and Div terms can simplify some cases,
but since it is only a partial treatment that is not producing a
normal form, in other cases the "simplification" results in large and
non-canonical terms. It is safer to leave them uninterpreted.

Reviewed By: jvillard

Differential Revision: D21042521

fbshipit-source-id: 04fc37f1a
master
Josh Berdine 5 years ago committed by Facebook GitHub Bot
parent a3a6a5a6fe
commit 76695690b8

@ -14,12 +14,9 @@ type kind = Interpreted | Atomic | Uninterpreted
let classify e = let classify e =
match (e : Term.t) with match (e : Term.t) with
| Add _ | Mul _ | Add _ | Ap2 (Memory, _, _) | Ap3 (Extract, _, _, _) | ApN (Concat, _) ->
|Ap2 ((Div | Memory), _, _)
|Ap3 (Extract, _, _, _)
|ApN (Concat, _) ->
Interpreted Interpreted
| Ap1 _ | Ap2 _ | Ap3 _ | ApN _ | And _ | Or _ -> Uninterpreted | Mul _ | Ap1 _ | Ap2 _ | Ap3 _ | ApN _ | And _ | Or _ -> Uninterpreted
| RecN _ | Var _ | Integer _ | Rational _ | Float _ | Nondet _ | Label _ | RecN _ | Var _ | Integer _ | Rational _ | Float _ | Nondet _ | Label _
-> ->
Atomic Atomic
@ -303,8 +300,6 @@ and solve_ ?f d e s =
( ((Add _ | Mul _ | Integer _ | Rational _) as p), q ( ((Add _ | Mul _ | Integer _ | Rational _) as p), q
| q, ((Add _ | Mul _ | Integer _ | Rational _) as p) ) -> | q, ((Add _ | Mul _ | Integer _ | Rational _) as p) ) ->
solve_poly ?f p q s solve_poly ?f p q s
(* e = n / d ==> e × d = n *)
| Some (rep, Ap2 (Div, num, den)) -> solve_ ?f (Term.mul rep den) num s
| Some (rep, var) -> | Some (rep, var) ->
assert (non_interpreted var) ; assert (non_interpreted var) ;
assert (non_interpreted rep) ; assert (non_interpreted rep) ;

@ -603,7 +603,7 @@ and simp_mul2 e f =
(* x₁ × x₂ ==> ∏ᵢ₌₁² xᵢ *) (* x₁ × x₂ ==> ∏ᵢ₌₁² xᵢ *)
| _ -> Prod.to_term (Prod.add e (Prod.of_ f)) | _ -> Prod.to_term (Prod.add e (Prod.of_ f))
let rec simp_div x y = let simp_div x y =
match (x, y) with match (x, y) with
(* e / 0 ==> e / 0 *) (* e / 0 ==> e / 0 *)
| _, Integer {data} when Z.equal Z.zero data -> Ap2 (Div, x, y) | _, Integer {data} when Z.equal Z.zero data -> Ap2 (Div, x, y)
@ -622,12 +622,6 @@ let rec simp_div x y =
(* x / n ==> 1/n × x *) (* x / n ==> 1/n × x *)
| _, Integer {data} -> Sum.to_term (Sum.of_ ~coeff:Q.(inv (of_z data)) x) | _, Integer {data} -> Sum.to_term (Sum.of_ ~coeff:Q.(inv (of_z data)) x)
| _, Rational {data} -> Sum.to_term (Sum.of_ ~coeff:Q.(inv data) x) | _, Rational {data} -> Sum.to_term (Sum.of_ ~coeff:Q.(inv data) x)
(* e / (n / d) ==> (e × d) / n *)
| e, Ap2 (Div, n, d) -> simp_div (simp_mul2 e d) n
(* x / (q × y) ==> (1/q × x) / y *)
| _, Add sum when Qset.is_singleton sum ->
let y, q = Qset.choose_exn sum in
simp_div (simp_mul2 (rational (Q.inv q)) x) y
(* x / y *) (* x / y *)
| _ -> Ap2 (Div, x, y) | _ -> Ap2 (Div, x, y)
@ -1357,33 +1351,10 @@ let height e =
let exists_fv_in vs qset = let exists_fv_in vs qset =
Qset.exists qset ~f:(fun e _ -> exists_vars e ~f:(Var.Set.mem vs)) Qset.exists qset ~f:(fun e _ -> exists_vars e ~f:(Var.Set.mem vs))
let exists_fv_in4 vs w x y z =
exists_fv_in vs w || exists_fv_in vs x || exists_fv_in vs y
|| exists_fv_in vs z
(* solve [0 = rejected_sum + (coeff × prod) + sum] *)
let solve_for_factor rejected_sum coeff prod sum =
let rec find_factor rejected_prod prod =
let* factor, power, prod = Qset.pop_min_elt prod in
if
(not (Q.equal Q.one power))
|| exists_fv_in4 (fv factor) rejected_sum rejected_prod prod sum
then find_factor (Qset.add rejected_prod factor power) prod
else Some (factor, Qset.union rejected_prod prod)
in
let+ factor, prod = find_factor Qset.empty prod in
(* solve [0 = rejected_sum + (coeff × factor × prod) + sum] yielding
[factor = (rejected_sum + sum) / (-coeff × prod)] *)
( factor
, div
(Sum.to_term (Qset.union rejected_sum sum))
(mul (rational (Q.neg coeff)) (Prod.to_term prod)) )
(* solve [0 = rejected_sum + (coeff × mono) + sum] *) (* solve [0 = rejected_sum + (coeff × mono) + sum] *)
let solve_for_mono rejected_sum coeff mono sum = let solve_for_mono rejected_sum coeff mono sum =
match mono with match mono with
| Integer _ -> None | Integer _ -> None
| Mul prod -> solve_for_factor rejected_sum coeff prod sum
| _ -> | _ ->
if exists_fv_in (fv mono) sum then None if exists_fv_in (fv mono) sum then None
else else
@ -1401,23 +1372,17 @@ let rec solve_sum rejected_sum sum =
|> Option.or_else ~f:(fun () -> |> Option.or_else ~f:(fun () ->
solve_sum (Qset.add rejected_sum mono coeff) sum ) solve_sum (Qset.add rejected_sum mono coeff) sum )
let rec solve_div = function
(* [n / d = t] ==> [n = d × t] *)
| Some (Ap2 (Div, num, den), trm) -> solve_div (Some (num, mul den trm))
| o -> o
(* solve [0 = e] *) (* solve [0 = e] *)
let solve_zero_eq ?for_ e = let solve_zero_eq ?for_ e =
[%Trace.call fun {pf} -> pf "0 = %a%a" pp e (Option.pp " for %a" pp) for_] [%Trace.call fun {pf} -> pf "0 = %a%a" pp e (Option.pp " for %a" pp) for_]
; ;
( match e with ( match e with
| Add sum -> | Add sum -> (
( match for_ with match for_ with
| None -> solve_sum Qset.empty sum | None -> solve_sum Qset.empty sum
| Some mono -> | Some mono ->
let* coeff, sum = Qset.find_and_remove sum mono in let* coeff, sum = Qset.find_and_remove sum mono in
solve_for_mono Qset.empty coeff mono sum ) solve_for_mono Qset.empty coeff mono sum )
|> solve_div
| _ -> None ) | _ -> None )
|> |>
[%Trace.retn fun {pf} s -> [%Trace.retn fun {pf} s ->
@ -1426,7 +1391,5 @@ let solve_zero_eq ?for_ e =
Format.fprintf fs "%a ↦ %a" pp c pp r )) Format.fprintf fs "%a ↦ %a" pp c pp r ))
s ; s ;
match (for_, s) with match (for_, s) with
| Some (Mul prod), Some (var, _) ->
assert (not (Q.equal Q.zero (Qset.count prod var)))
| Some f, Some (c, _) -> assert (equal f c) | Some f, Some (c, _) -> assert (equal f c)
| _ -> ()] | _ -> ()]

Loading…
Cancel
Save