/- Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ module prelude public import Init.Grind.Ordered.Ring import Init.Grind.Ring public section namespace Lean.Grind.Order attribute [local instance] Ring.intCast /-! Helper theorems to assert constraints -/ theorem eq_mp {p q : Prop} (h₁ : p = q) (h₂ : p) : q := by subst p; simp [*] theorem eq_mp_not {p q : Prop} (h₁ : p = q) (h₂ : ¬ p) : ¬ q := by subst p; simp [*] theorem eq_trans_true {p q : Prop} (h₁ : p = q) (h₂ : q = True) : p = True := by subst p; simp [*] theorem eq_trans_false {p q : Prop} (h₁ : p = q) (h₂ : q = False) : p = False := by subst p; simp [*] theorem eq_trans_true' {p q : Prop} (h₁ : p = q) (h₂ : p = True) : q = True := by subst p; simp [*] theorem eq_trans_false' {p q : Prop} (h₁ : p = q) (h₂ : p = False) : q = False := by subst p; simp [*] theorem le_of_eq_1 {α} [LE α] [Std.IsPreorder α] {a b : α} : a = b → a ≤ b := by intro h; subst a; apply Std.IsPreorder.le_refl theorem le_of_eq_2 {α} [LE α] [Std.IsPreorder α] {a b : α} : a = b → b ≤ a := by intro h; subst a; apply Std.IsPreorder.le_refl /- **Note**: `le_of_eq_1_k` and `le_of_eq_2_k` contain unnecessary instances, but the extra arguments simplify the proof generation in `grind order` (fewer cases). -/ theorem le_of_eq_1_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} : a = b → a ≤ b + Int.cast (R := α) 0 := by rw [Ring.intCast_zero, Semiring.add_zero] intro h; subst a; apply Std.IsPreorder.le_refl theorem le_of_eq_2_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} : a = b → b ≤ a + Int.cast (R := α) 0 := by rw [Ring.intCast_zero, Semiring.add_zero] intro h; subst a; apply Std.IsPreorder.le_refl theorem le_of_not_le {α} [LE α] [Std.IsLinearPreorder α] {a b : α} : ¬ a ≤ b → b ≤ a := by intro h have := Std.IsLinearPreorder.le_total a b cases this; contradiction; assumption theorem lt_of_not_le {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsLinearPreorder α] {a b : α} : ¬ a ≤ b → b < a := by intro h rw [Std.LawfulOrderLT.lt_iff] have := Std.IsLinearPreorder.le_total a b cases this; contradiction; simp [*] theorem le_of_not_lt {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsLinearPreorder α] {a b : α} : ¬ a < b → b ≤ a := by rw [Std.LawfulOrderLT.lt_iff] open Classical in rw [Classical.not_and_iff_not_or_not, Classical.not_not] intro h; cases h next => have := Std.IsLinearPreorder.le_total a b cases this; contradiction; assumption next => assumption theorem le_of_not_lt_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsLinearPreorder α] [Ring α] [OrderedRing α] {a b : α} {k k' : Int} : k'.beq' (-k) → ¬ a < b + k → b ≤ a + k' := by simp; intro _ h; subst k' replace h := le_of_not_lt h replace h := OrderedAdd.add_le_left h (-k) rw [Semiring.add_assoc, AddCommGroup.add_neg_cancel, Semiring.add_zero] at h rw [Ring.intCast_neg] assumption theorem lt_of_not_le_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsLinearPreorder α] [Ring α] [OrderedRing α] {a b : α} {k k' : Int} : k'.beq' (-k) → ¬ a ≤ b + k → b < a + k' := by simp; intro _ h; subst k' replace h := lt_of_not_le h replace h := OrderedAdd.add_lt_left h (-k) rw [Semiring.add_assoc, AddCommGroup.add_neg_cancel, Semiring.add_zero] at h rw [Ring.intCast_neg] assumption theorem int_lt {x y k k' : Int} : k'.beq' (k-1) → x < y + k → x ≤ y + k' := by simp; intro; subst k'; omega /-! Helper theorem for equality propagation -/ theorem eq_of_le_of_le {α} [LE α] [Std.IsPartialOrder α] {a b : α} : a ≤ b → b ≤ a → a = b := Std.IsPartialOrder.le_antisymm _ _ /-! Transitivity -/ theorem le_trans {α} [LE α] [Std.IsPreorder α] {a b c : α} (h₁ : a ≤ b) (h₂ : b ≤ c) : a ≤ c := Std.IsPreorder.le_trans _ _ _ h₁ h₂ theorem lt_trans {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] {a b c : α} (h₁ : a < b) (h₂ : b < c) : a < c := Preorder.lt_trans h₁ h₂ theorem le_lt_trans {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] {a b c : α} (h₁ : a ≤ b) (h₂ : b < c) : a < c := Preorder.lt_of_le_of_lt h₁ h₂ theorem lt_le_trans {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] {a b c : α} (h₁ : a < b) (h₂ : b ≤ c) : a < c := Preorder.lt_of_lt_of_le h₁ h₂ theorem lt_unsat {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] (a : α) : a < a → False := Preorder.lt_irrefl a /-! Transitivity with offsets -/ theorem le_trans_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b c : α} {k₁ k₂ : Int} (k : Int) (h₁ : a ≤ b + k₁) (h₂ : b ≤ c + k₂) : k == k₂ + k₁ → a ≤ c + k := by intro h; simp at h; subst k replace h₂ := OrderedAdd.add_le_left_iff (M := α) k₁ |>.mp h₂ have := le_trans h₁ h₂ simp [Ring.intCast_add, ← Semiring.add_assoc, this] theorem lt_trans_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b c : α} {k₁ k₂ : Int} (k : Int) (h₁ : a < b + k₁) (h₂ : b < c + k₂) : k == k₂ + k₁ → a < c + k := by intro h; simp at h; subst k replace h₂ := OrderedAdd.add_lt_left_iff (M := α) k₁ |>.mp h₂ have := lt_trans h₁ h₂ simp [Ring.intCast_add, ← Semiring.add_assoc, this] theorem le_lt_trans_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b c : α} {k₁ k₂ : Int} (k : Int) (h₁ : a ≤ b + k₁) (h₂ : b < c + k₂) : k == k₂ + k₁ → a < c + k := by intro h; simp at h; subst k replace h₂ := OrderedAdd.add_lt_left_iff (M := α) k₁ |>.mp h₂ have := le_lt_trans h₁ h₂ simp [Ring.intCast_add, ← Semiring.add_assoc, this] theorem lt_le_trans_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b c : α} {k₁ k₂ : Int} (k : Int) (h₁ : a < b + k₁) (h₂ : b ≤ c + k₂) : k == k₂ + k₁ → a < c + k := by intro h; simp at h; subst k replace h₂ := OrderedAdd.add_le_left_iff (M := α) k₁ |>.mp h₂ have := lt_le_trans h₁ h₂ simp [Ring.intCast_add, ← Semiring.add_assoc, this] /-! Unsat detection -/ theorem le_unsat_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a : α} {k : Int} : k.blt' 0 → a ≤ a + k → False := by simp; intro h₁ h₂ replace h₂ := OrderedAdd.add_le_left_iff (-a) |>.mp h₂ rw [AddCommGroup.add_neg_cancel, Semiring.add_assoc, Semiring.add_comm _ (-a)] at h₂ rw [← Semiring.add_assoc, AddCommGroup.add_neg_cancel, Semiring.add_comm, Semiring.add_zero] at h₂ rw [← Ring.intCast_zero] at h₂ replace h₂ := OrderedRing.le_of_intCast_le_intCast _ _ h₂ omega theorem lt_unsat_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a : α} {k : Int} : k.ble' 0 → a < a + k → False := by simp; intro h₁ h₂ replace h₂ := OrderedAdd.add_lt_left_iff (-a) |>.mp h₂ rw [AddCommGroup.add_neg_cancel, Semiring.add_assoc, Semiring.add_comm _ (-a)] at h₂ rw [← Semiring.add_assoc, AddCommGroup.add_neg_cancel, Semiring.add_comm, Semiring.add_zero] at h₂ rw [← Ring.intCast_zero] at h₂ replace h₂ := OrderedRing.lt_of_intCast_lt_intCast _ _ h₂ omega /-! Helper theorems -/ private theorem add_lt_add_of_le_of_lt {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b c d : α} (hab : a ≤ b) (hcd : c < d) : a + c < b + d := lt_le_trans (OrderedAdd.add_lt_right a hcd) (OrderedAdd.add_le_left hab d) private theorem add_lt_add_of_lt_of_le {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b c d : α} (hab : a < b) (hcd : c ≤ d) : a + c < b + d := le_lt_trans (OrderedAdd.add_le_right a hcd) (OrderedAdd.add_lt_left hab d) /-! Theorems for propagating constraints to `True` -/ theorem le_eq_true_of_lt {α} [LE α] [LT α] [Std.LawfulOrderLT α] {a b : α} : a < b → (a ≤ b) = True := by simp; intro h exact Std.le_of_lt h theorem le_eq_true_of_le_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} {k₁ k₂ : Int} : k₁.ble' k₂ → a ≤ b + k₁ → (a ≤ b + k₂) = True := by simp; intro h₁ h₂ replace h₁ : 0 ≤ k₂ - k₁ := by omega replace h₁ := OrderedRing.nonneg_intCast_of_nonneg (R := α) _ h₁ replace h₁ := OrderedAdd.add_le_add h₂ h₁ rw [Semiring.add_zero, Semiring.add_assoc, Int.sub_eq_add_neg, Int.add_comm] at h₁ rw [Ring.intCast_add, Ring.intCast_neg, ← Semiring.add_assoc (k₁ : α)] at h₁ rw [AddCommGroup.add_neg_cancel, Semiring.add_comm 0, Semiring.add_zero] at h₁ assumption theorem le_eq_true_of_lt_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} {k₁ k₂ : Int} : k₁.ble' k₂ → a < b + k₁ → (a ≤ b + k₂) = True := by intro h₁ h₂ replace h₂ := Std.le_of_lt h₂ apply le_eq_true_of_le_k <;> assumption theorem lt_eq_true_of_lt_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} {k₁ k₂ : Int} : k₁.ble' k₂ → a < b + k₁ → (a < b + k₂) = True := by simp; intro h₁ h₂ replace h₁ : 0 ≤ k₂ - k₁ := by omega replace h₁ := OrderedRing.nonneg_intCast_of_nonneg (R := α) _ h₁ replace h₁ := add_lt_add_of_le_of_lt h₁ h₂ rw [Semiring.add_comm, Semiring.add_zero, Semiring.add_comm, Semiring.add_assoc, Int.sub_eq_add_neg, Int.add_comm] at h₁ rw [Ring.intCast_add, Ring.intCast_neg, ← Semiring.add_assoc (k₁ : α)] at h₁ rw [AddCommGroup.add_neg_cancel, Semiring.add_comm 0, Semiring.add_zero] at h₁ assumption theorem lt_eq_true_of_le_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} {k₁ k₂ : Int} : k₁.blt' k₂ → a ≤ b + k₁ → (a < b + k₂) = True := by simp; intro h₁ h₂ replace h₁ : 0 < k₂ - k₁ := by omega replace h₁ := OrderedRing.pos_intCast_of_pos (R := α) _ h₁ replace h₁ := add_lt_add_of_le_of_lt h₂ h₁ rw [Semiring.add_zero, Semiring.add_assoc, Int.sub_eq_add_neg, Int.add_comm] at h₁ rw [Ring.intCast_add, Ring.intCast_neg, ← Semiring.add_assoc (k₁ : α)] at h₁ rw [AddCommGroup.add_neg_cancel, Semiring.add_comm 0, Semiring.add_zero] at h₁ assumption /-! Theorems for propagating constraints to `False` -/ theorem le_eq_false_of_lt {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] {a b : α} : a < b → (b ≤ a) = False := by simp; intro h₁ h₂ have := lt_le_trans h₁ h₂ have := Preorder.lt_irrefl a contradiction theorem lt_eq_false_of_lt {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] {a b : α} : a < b → (b < a) = False := by simp; intro h₁ h₂ have := lt_trans h₁ h₂ have := Preorder.lt_irrefl a contradiction theorem lt_eq_false_of_le {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] {a b : α} : a ≤ b → (b < a) = False := by simp; intro h₁ h₂ have := le_lt_trans h₁ h₂ have := Preorder.lt_irrefl a contradiction theorem le_eq_false_of_le_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] {a b : α} {k₁ k₂ : Int} : (k₂ + k₁).blt' 0 → a ≤ b + k₁ → (b ≤ a + k₂) = False := by intro h₁; simp; intro h₂ h₃ have h := le_trans_k (k₂ + k₁) h₂ h₃ simp at h apply le_unsat_k h₁ h theorem lt_eq_false_of_le_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] (a b : α) (k₁ k₂ : Int) : (k₂ + k₁).ble' 0 → a ≤ b + k₁ → (b < a + k₂) = False := by intro h₁; simp; intro h₂ h₃ have h := le_lt_trans_k (k₂ + k₁) h₂ h₃ simp at h apply lt_unsat_k h₁ h theorem lt_eq_false_of_lt_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] (a b : α) (k₁ k₂ : Int) : (k₂ + k₁).ble' 0 → a < b + k₁ → (b < a + k₂) = False := by intro h₁; simp; intro h₂ h₃ have h := lt_trans_k (k₂ + k₁) h₂ h₃ simp at h apply lt_unsat_k h₁ h theorem le_eq_false_of_lt_k {α} [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α] (a b : α) (k₁ k₂ : Int) : (k₂ + k₁).ble' 0 → a < b + k₁ → (b ≤ a + k₂) = False := by intro h₁; simp; intro h₂ h₃ have h := lt_le_trans_k (k₂ + k₁) h₂ h₃ simp at h apply lt_unsat_k h₁ h end Lean.Grind.Order