|
|
|
@ -7,9 +7,13 @@
|
|
|
|
|
|
|
|
|
|
(** Arithmetic terms *)
|
|
|
|
|
|
|
|
|
|
open Ses.Var_intf
|
|
|
|
|
include Arithmetic_intf
|
|
|
|
|
|
|
|
|
|
module Representation (Trm : INDETERMINATE) = struct
|
|
|
|
|
module Representation
|
|
|
|
|
(Var : VAR)
|
|
|
|
|
(Trm : INDETERMINATE with type var := Var.t) =
|
|
|
|
|
struct
|
|
|
|
|
module Prod = struct
|
|
|
|
|
include Multiset.Make
|
|
|
|
|
(Int)
|
|
|
|
@ -64,6 +68,16 @@ module Representation (Trm : INDETERMINATE) = struct
|
|
|
|
|
(** [get_trm m] is [Some x] iff [equal m (of_ x 1)] *)
|
|
|
|
|
let get_trm mono =
|
|
|
|
|
match Prod.only_elt mono with Some (trm, 1) -> Some trm | _ -> None
|
|
|
|
|
|
|
|
|
|
(* traverse *)
|
|
|
|
|
|
|
|
|
|
let trms mono =
|
|
|
|
|
Iter.from_iter (fun f -> Prod.iter mono ~f:(fun trm _ -> f trm))
|
|
|
|
|
|
|
|
|
|
(* query *)
|
|
|
|
|
|
|
|
|
|
let vars p = Iter.flat_map ~f:Trm.vars (trms p)
|
|
|
|
|
let fv p = Var.Set.of_iter (vars p)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module Sum = struct
|
|
|
|
@ -99,6 +113,8 @@ module Representation (Trm : INDETERMINATE) = struct
|
|
|
|
|
(Sum.pp "@ + " pp_coeff_mono)
|
|
|
|
|
poly
|
|
|
|
|
|
|
|
|
|
let pp = ppx (fun _ -> None)
|
|
|
|
|
|
|
|
|
|
let mono_invariant mono =
|
|
|
|
|
let@ () = Invariant.invariant [%here] mono [%sexp_of: Mono.t] in
|
|
|
|
|
Prod.iter mono ~f:(fun base power ->
|
|
|
|
@ -268,14 +284,72 @@ module Representation (Trm : INDETERMINATE) = struct
|
|
|
|
|
|
|
|
|
|
(* traverse *)
|
|
|
|
|
|
|
|
|
|
let iter poly =
|
|
|
|
|
Iter.from_iter (fun f ->
|
|
|
|
|
Sum.iter poly ~f:(fun mono _ ->
|
|
|
|
|
Prod.iter mono ~f:(fun trm _ -> f trm) ) )
|
|
|
|
|
let monos poly =
|
|
|
|
|
Iter.from_iter (fun f -> Sum.iter poly ~f:(fun mono _ -> f mono))
|
|
|
|
|
|
|
|
|
|
let trms poly = Iter.flat_map ~f:Mono.trms (monos poly)
|
|
|
|
|
|
|
|
|
|
type product = Prod.t
|
|
|
|
|
|
|
|
|
|
let fold_factors = Prod.fold
|
|
|
|
|
let fold_monomials = Sum.fold
|
|
|
|
|
|
|
|
|
|
(* query *)
|
|
|
|
|
|
|
|
|
|
let vars p = Iter.flat_map ~f:Trm.vars (trms p)
|
|
|
|
|
|
|
|
|
|
(* solve *)
|
|
|
|
|
|
|
|
|
|
let exists_fv_in vs poly = Iter.exists ~f:(Var.Set.mem vs) (vars poly)
|
|
|
|
|
|
|
|
|
|
(** [solve_for_mono r c m p] solves [0 = r + (c×m) + p] as [m = q]
|
|
|
|
|
([Some (m, q)]) such that [r + (c×m) + p = m - q] *)
|
|
|
|
|
let solve_for_mono rejected_poly coeff mono poly =
|
|
|
|
|
if Mono.equal_one mono || exists_fv_in (Mono.fv mono) poly then None
|
|
|
|
|
else
|
|
|
|
|
Some
|
|
|
|
|
( Sum.of_ mono Q.one
|
|
|
|
|
, mulc (Q.inv (Q.neg coeff)) (Sum.union rejected_poly poly) )
|
|
|
|
|
|
|
|
|
|
(** [solve_poly r p] solves [0 = r + p] as [m = q] ([Some (m, q)]) such
|
|
|
|
|
that [r + p = m - q] *)
|
|
|
|
|
let rec solve_poly rejected poly =
|
|
|
|
|
[%trace]
|
|
|
|
|
~call:(fun {pf} -> pf "0 = (%a) + (%a)" pp rejected pp poly)
|
|
|
|
|
~retn:(fun {pf} s ->
|
|
|
|
|
pf "%a"
|
|
|
|
|
(Option.pp "%a" (fun fs (v, q) ->
|
|
|
|
|
Format.fprintf fs "%a ↦ %a" pp v pp q ))
|
|
|
|
|
s )
|
|
|
|
|
@@ fun () ->
|
|
|
|
|
let* mono, coeff, poly = Sum.pop_min_elt poly in
|
|
|
|
|
match solve_for_mono rejected coeff mono poly with
|
|
|
|
|
| Some _ as soln -> soln
|
|
|
|
|
| None -> solve_poly (Sum.add mono coeff rejected) poly
|
|
|
|
|
|
|
|
|
|
(* solve [0 = e] *)
|
|
|
|
|
let solve_zero_eq ?for_ e =
|
|
|
|
|
[%trace]
|
|
|
|
|
~call:(fun {pf} ->
|
|
|
|
|
pf "0 = %a%a" Trm.pp e (Option.pp " for %a" Trm.pp) for_ )
|
|
|
|
|
~retn:(fun {pf} s ->
|
|
|
|
|
pf "%a"
|
|
|
|
|
(Option.pp "%a" (fun fs (c, r) ->
|
|
|
|
|
Format.fprintf fs "%a ↦ %a" pp c pp r ))
|
|
|
|
|
s ;
|
|
|
|
|
match (for_, s) with
|
|
|
|
|
| Some f, Some (c, _) -> assert (equal (trm f) c)
|
|
|
|
|
| _ -> () )
|
|
|
|
|
@@ fun () ->
|
|
|
|
|
let* a = Embed.get_arith e in
|
|
|
|
|
match for_ with
|
|
|
|
|
| None -> solve_poly Sum.empty a
|
|
|
|
|
| Some for_ -> (
|
|
|
|
|
let* for_poly = Embed.get_arith for_ in
|
|
|
|
|
match get_mono for_poly with
|
|
|
|
|
| Some m ->
|
|
|
|
|
let* c, p = Sum.find_and_remove m a in
|
|
|
|
|
solve_for_mono Sum.empty c m p
|
|
|
|
|
| _ -> None )
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|