@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Robert Y. Lewis
55-/
66import Mathlib.Tactic.Linarith.Datatypes
7- import Batteries.Data.RBMap.WF
87
98/-!
109# Parsing input expressions into linear form
@@ -16,19 +15,43 @@ It identifies atoms up to ring-equivalence: that is, `(y*3)*x` will be identifie
1615where the monomial `x*y` is the linear atom.
1716
1817* Variables are represented by natural numbers.
19- * Monomials are represented by `Monom := RBMap ℕ ℕ`.
18+ * Monomials are represented by `Monom := TreeMap ℕ ℕ`.
2019 The monomial `1` is represented by the empty map.
21- * Linear combinations of monomials are represented by `Sum := RBMap Monom ℤ`.
20+ * Linear combinations of monomials are represented by `Sum := TreeMap Monom ℤ`.
2221
2322 All input expressions are converted to `Sum`s, preserving the map from expressions to variables.
2423We then discard the monomial information, mapping each distinct monomial to a natural number.
25- The resulting `RBMap ℕ ℤ` represents the ring-normalized linear form of the expression.
24+ The resulting `TreeMap ℕ ℤ` represents the ring-normalized linear form of the expression.
2625This is ultimately converted into a `Linexp` in the obvious way.
2726
2827`linearFormsAndMaxVar` is the main entry point into this file. Everything else is contained.
2928-/
3029
3130open Mathlib.Ineq Batteries
31+ open Std (TreeMap)
32+
33+ namespace Std.TreeMap
34+
35+ -- This will be replaced by a `BEq` instance implemented in the standard library,
36+ -- likely in Q4 2025.
37+
38+ /-- Returns true if the two maps have the same size and the same keys and values
39+ (with keys compared using the ordering, and values compared using `BEq`). -/
40+ def beq {α β : Type *} [BEq β] {c : α → α → Ordering} (m₁ m₂ : TreeMap α β c) : Bool :=
41+ m₁.size == m₂.size && Id.run do
42+ -- This could be made more efficient by simultaneously traversing both maps.
43+ for (k, v) in m₁ do
44+ if let some v' := m₂[k]? then
45+ if v != v' then
46+ return false
47+ else
48+ return false
49+ return true
50+
51+ instance {α β : Type*} [BEq β] {c : α → α → Ordering} : BEq (TreeMap α β c) := ⟨beq⟩
52+
53+ end Std.TreeMap
54+
3255
3356section
3457open Lean Elab Tactic Meta
@@ -47,26 +70,26 @@ def List.findDefeq {v : Type} (red : TransparencyMode) (m : List (Expr × v)) (e
4770end
4871
4972/--
50- We introduce a local instance allowing addition of `RBMap `s,
73+ We introduce a local instance allowing addition of `TreeMap `s,
5174removing any keys with value zero.
5275We don't need to prove anything about this addition, as it is only used in meta code.
5376-/
5477local instance {α β : Type*} {c : α → α → Ordering} [Add β] [Zero β] [DecidableEq β] :
55- Add (RBMap α β c) where
78+ Add (TreeMap α β c) where
5679 add := fun f g => (f.mergeWith (fun _ b b' => b + b') g).filter (fun _ b => b ≠ 0 )
5780
5881namespace Linarith
5982
60- /-- A local abbreviation for `RBMap ` so we don't need to write `Ord.compare` each time. -/
61- abbrev Map (α β) [Ord α] := RBMap α β Ord.compare
83+ /-- A local abbreviation for `TreeMap ` so we don't need to write `Ord.compare` each time. -/
84+ abbrev Map (α β) [Ord α] := TreeMap α β Ord.compare
6285
6386/-! ### Parsing datatypes -/
6487
6588/-- Variables (represented by natural numbers) map to their power. -/
6689abbrev Monom : Type := Map ℕ ℕ
6790
6891/-- `1` is represented by the empty monomial, the product of no variables. -/
69- def Monom.one : Monom := RBMap .empty
92+ def Monom.one : Monom := TreeMap .empty
7093
7194/-- Compare monomials by first comparing their keys and then their powers. -/
7295def Monom.lt : Monom → Monom → Bool :=
@@ -81,16 +104,16 @@ instance : Ord Monom where
81104abbrev Sum : Type := Map Monom ℤ
82105
83106/-- `1` is represented as the singleton sum of the monomial `Monom.one` with coefficient 1. -/
84- def Sum.one : Sum := RBMap .empty.insert Monom.one 1
107+ def Sum.one : Sum := TreeMap .empty.insert Monom.one 1
85108
86109/-- `Sum.scaleByMonom s m` multiplies every monomial in `s` by `m`. -/
87110def Sum.scaleByMonom (s : Sum) (m : Monom) : Sum :=
88- s.foldr (fun m' coeff sm => sm.insert (m + m') coeff) RBMap .empty
111+ s.foldr (fun m' coeff sm => sm.insert (m + m') coeff) TreeMap .empty
89112
90113/-- `sum.mul s1 s2` distributes the multiplication of two sums. -/
91114def Sum.mul (s1 s2 : Sum) : Sum :=
92- s1.foldr (fun mn coeff sm => sm + ((s2.scaleByMonom mn).mapVal (fun _ v => v * coeff)))
93- RBMap .empty
115+ s1.foldr (fun mn coeff sm => sm + ((s2.scaleByMonom mn).map (fun _ v => v * coeff)))
116+ TreeMap .empty
94117
95118/-- The `n`th power of `s : Sum` is the `n`-fold product of `s`, with `s.pow 0 = Sum.one`. -/
96119partial def Sum.pow (s : Sum) : ℕ → Sum
@@ -106,18 +129,18 @@ partial def Sum.pow (s : Sum) : ℕ → Sum
106129
107130/-- `SumOfMonom m` lifts `m` to a sum with coefficient `1`. -/
108131def SumOfMonom (m : Monom) : Sum :=
109- RBMap .empty.insert m 1
132+ TreeMap .empty.insert m 1
110133
111- /-- The unit monomial `one` is represented by the empty RBMap . -/
112- def one : Monom := RBMap .empty
134+ /-- The unit monomial `one` is represented by the empty TreeMap . -/
135+ def one : Monom := TreeMap .empty
113136
114137/-- A scalar `z` is represented by a `Sum` with coefficient `z` and monomial `one` -/
115138def scalar (z : ℤ) : Sum :=
116- RBMap .empty.insert one z
139+ TreeMap .empty.insert one z
117140
118141/-- A single variable `n` is represented by a sum with coefficient `1` and monomial `n`. -/
119142def var (n : ℕ) : Sum :=
120- RBMap .empty.insert (RBMap .empty.insert n 1 ) 1
143+ TreeMap .empty.insert (TreeMap .empty.insert n 1 ) 1
121144
122145
123146/-! ### Parsing algorithms -/
@@ -159,7 +182,7 @@ and forces some functions that call it into `MetaM` as well.
159182partial def linearFormOfExpr (red : TransparencyMode) (m : ExprMap) (e : Expr) :
160183 MetaM (ExprMap × Sum) :=
161184 match e.numeral? with
162- | some 0 => return ⟨m, RBMap .empty⟩
185+ | some 0 => return ⟨m, TreeMap .empty⟩
163186 | some (n+1 ) => return ⟨m, scalar (n+1 )⟩
164187 | none =>
165188 match e.getAppFnArgs with
@@ -174,10 +197,10 @@ partial def linearFormOfExpr (red : TransparencyMode) (m : ExprMap) (e : Expr) :
174197 | (``HSub.hSub, #[_, _, _, _, e1, e2]) => do
175198 let (m1, comp1) ← linearFormOfExpr red m e1
176199 let (m2, comp2) ← linearFormOfExpr red m1 e2
177- return (m2, comp1 + comp2.mapVal (fun _ v => -v))
200+ return (m2, comp1 + comp2.map (fun _ v => -v))
178201 | (``Neg.neg, #[_, _, e]) => do
179202 let (m1, comp) ← linearFormOfExpr red m e
180- return (m1, comp.mapVal (fun _ v => -v))
203+ return (m1, comp.map (fun _ v => -v))
181204 | (``HPow.hPow, #[_, _, _, _, a, n]) => do
182205 match n.numeral? with
183206 | some n => do
@@ -190,18 +213,18 @@ partial def linearFormOfExpr (red : TransparencyMode) (m : ExprMap) (e : Expr) :
190213`elimMonom s map` eliminates the monomial level of the `Sum` `s`.
191214
192215`map` is a lookup map from monomials to variable numbers.
193- The output `RBMap ℕ ℤ` has the same structure as `s : Sum`,
216+ The output `TreeMap ℕ ℤ` has the same structure as `s : Sum`,
194217but each monomial key is replaced with its index according to `map`.
195218If any new monomials are encountered, they are assigned variable numbers and `map` is updated.
196219-/
197220def elimMonom (s : Sum) (m : Map Monom ℕ) : Map Monom ℕ × Map ℕ ℤ :=
198221 s.foldr (fun mn coeff ⟨map, out⟩ ↦
199- match map.find? mn with
222+ match map[mn]? with
200223 | some n => ⟨map, out.insert n coeff⟩
201224 | none =>
202225 let n := map.size
203226 ⟨map.insert mn n, out.insert n coeff⟩)
204- (m, RBMap .empty)
227+ (m, TreeMap .empty)
205228
206229/--
207230`toComp red e e_map monom_map` converts an expression of the form `t < 0`, `t ≤ 0`, or `t = 0`
@@ -240,7 +263,7 @@ It also returns the largest variable index that appears in comparisons in `c`.
240263def linearFormsAndMaxVar (red : TransparencyMode) (pfs : List Expr) :
241264 MetaM (List Comp × ℕ) := do
242265 let pftps ← (pfs.mapM inferType)
243- let (l, _, map) ← toCompFold red [] pftps RBMap .empty
266+ let (l, _, map) ← toCompFold red [] pftps TreeMap .empty
244267 trace[linarith.detail] "monomial map: {map.toList.map fun ⟨k,v⟩ => (k.toList, v)}"
245268 return (l, map.size - 1 )
246269
0 commit comments