File: .lake/packages/lean4/src/lean/Init/Omega/Constraint.lean

full_name: Lean.Omega.LowerBound
code: /-- An optional lower bound on a integer. -/
abbrev LowerBound : Type 
goal: Type

full_name: Lean.Omega.UpperBound
code: /-- An optional upper bound on a integer. -/
abbrev UpperBound : Type 
goal: Type

full_name: Lean.Omega.LowerBound.sat
code: /-- A lower bound at `x` is satisfied at `t` if `x ≤ t`. -/
abbrev LowerBound.sat (b : LowerBound) (t : Int) 
goal: Bool

full_name: Lean.Omega.UpperBound.sat
code: /-- A upper bound at `y` is satisfied at `t` if `t ≤ y`. -/
abbrev UpperBound.sat (b : UpperBound) (t : Int) 
goal: Bool

full_name: Lean.Omega.instBEqConstraint
code: /--
A `Constraint` consists of an optional lower and upper bound (inclusive),
constraining a value to a set of the form `∅`, `{x}`, `[x, y]`, `[x, ∞)`, `(-∞, y]`, or `(-∞, ∞)`.
-/
structure Constraint where
  /-- A lower bound. -/
  lowerBound : LowerBound
  /-- An upper bound. -/
  upperBound : UpperBound
deriving BEq, DecidableEq, Repr
goal: BEq Lean.Omega.Constraint

full_name: Lean.Omega.Constraint
code: /--
A `Constraint` consists of an optional lower and upper bound (inclusive),
constraining a value to a set of the form `∅`, `{x}`, `[x, y]`, `[x, ∞)`, `(-∞, y]`, or `(-∞, ∞)`.
-/
structure Constraint where
  /-- A lower bound. -/
  lowerBound : LowerBound
  /-- An upper bound. -/
  upperBound : UpperBound
deriving BEq, DecidableEq, Repr
goal: Type

full_name: Lean.Omega.Constraint.upperBound
code: /--
A `Constraint` consists of an optional lower and upper bound (inclusive),
constraining a value to a set of the form `∅`, `{x}`, `[x, y]`, `[x, ∞)`, `(-∞, y]`, or `(-∞, ∞)`.
-/
structure Constraint where
  /-- A lower bound. -/
  lowerBound : LowerBound
  /-- An upper bound. -/
  upperBound : UpperBound
deriving BEq, DecidableEq, Repr
goal: Lean.Omega.UpperBound

full_name: Lean.Omega.Constraint.lowerBound
code: /--
A `Constraint` consists of an optional lower and upper bound (inclusive),
constraining a value to a set of the form `∅`, `{x}`, `[x, y]`, `[x, ∞)`, `(-∞, y]`, or `(-∞, ∞)`.
-/
structure Constraint where
  /-- A lower bound. -/
  lowerBound : LowerBound
  /-- An upper bound. -/
  upperBound : UpperBound
deriving BEq, DecidableEq, Repr
goal: Lean.Omega.LowerBound

full_name: Lean.Omega.instReprConstraint
code: /--
A `Constraint` consists of an optional lower and upper bound (inclusive),
constraining a value to a set of the form `∅`, `{x}`, `[x, y]`, `[x, ∞)`, `(-∞, y]`, or `(-∞, ∞)`.
-/
structure Constraint where
  /-- A lower bound. -/
  lowerBound : LowerBound
  /-- An upper bound. -/
  upperBound : UpperBound
deriving BEq, DecidableEq, Repr
goal: Repr Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.instToString
code: instance : ToString Constraint 
goal: ToString Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.sat
code: /-- A constraint is satisfied at `t` is both the lower bound and upper bound are satisfied. -/
def sat (c : Constraint) (t : Int) : Bool 
goal: Bool

full_name: Lean.Omega.Constraint.map
code: /-- Apply a function to both the lower bound and upper bound. -/
def map (c : Constraint) (f : Int → Int) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.translate
code: /-- Translate a constraint. -/
def translate (c : Constraint) (t : Int) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.translate_sat
code: theorem translate_sat : {c : Constraint} → {v : Int} → sat c v → sat (c.translate t) (v + t) 
goal: c.sat v = true → (c.translate t).sat (v + t) = true

full_name: Lean.Omega.Constraint.flip
code: /--
Flip a constraint.
This operation is not useful by itself, but is used to implement `neg` and `scale`.
-/
def flip (c : Constraint) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.neg
code: /--
Negate a constraint. `[x, y]` becomes `[-y, -x]`.
-/
def neg (c : Constraint) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.neg_sat
code: theorem neg_sat : {c : Constraint} → {v : Int} → sat c v → sat (c.neg) (-v) 
goal: c.sat v = true → c.neg.sat (-v) = true

full_name: Lean.Omega.Constraint.trivial
code: /-- The trivial constraint, satisfied everywhere. -/
def trivial : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.impossible
code: /-- The impossible constraint, unsatisfiable. -/
def impossible : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.exact
code: /-- An exact constraint. -/
def exact (r : Int) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.trivial_say
code: @[simp] theorem trivial_say : trivial.sat t 
goal: Lean.Omega.Constraint.trivial.sat t = true

full_name: Lean.Omega.Constraint.exact_sat
code: @[simp] theorem exact_sat (r : Int) (t : Int) : (exact r).sat t = decide (r = t) 
goal: (Lean.Omega.Constraint.exact r).sat t = decide (r = t)

full_name: Lean.Omega.Constraint.isImpossible
code: /-- Check if a constraint is unsatisfiable. -/
def isImpossible : Constraint → Bool
  
goal: Lean.Omega.Constraint → Bool

full_name: Lean.Omega.Constraint.isExact
code: /-- Check if a constraint requires an exact value. -/
def isExact : Constraint → Bool
  
goal: Lean.Omega.Constraint → Bool

full_name: Lean.Omega.Constraint.not_sat_of_isImpossible
code: theorem not_sat_of_isImpossible (h : isImpossible c) {t} : ¬ c.sat t 
goal: ¬c.sat t = true

full_name: Lean.Omega.Constraint.scale
code: /--
Scale a constraint by multiplying by an integer.
* If `k = 0` this is either impossible, if the original constraint was impossible,
  or the `= 0` exact constraint.
* If `k` is positive this takes `[x, y]` to `[k * x, k * y]`
* If `k` is negative this takes `[x, y]` to `[k * y, k * x]`.
-/
def scale (k : Int) (c : Constraint) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.scale_sat
code: theorem scale_sat {c : Constraint} (k) (w : c.sat t) : (scale k c).sat (k * t) 
goal: (Lean.Omega.Constraint.scale k c).sat (k * t) = true

full_name: Lean.Omega.Constraint.add
code: /-- The sum of two constraints. `[a, b] + [c, d] = [a + c, b + d]`. -/
def add (x y : Constraint) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.add_sat
code: theorem add_sat (w₁ : c₁.sat x₁) (w₂ : c₂.sat x₂) : (add c₁ c₂).sat (x₁ + x₂) 
goal: (c₁.add c₂).sat (x₁ + x₂) = true

full_name: Lean.Omega.Constraint.combo
code: /-- A linear combination of two constraints. -/
def combo (a : Int) (x : Constraint) (b : Int) (y : Constraint) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.combo_sat
code: theorem combo_sat (a) (w₁ : c₁.sat x₁) (b) (w₂ : c₂.sat x₂) :
    (combo a c₁ b c₂).sat (a * x₁ + b * x₂) 
goal: (Lean.Omega.Constraint.combo a c₁ b c₂).sat (a * x₁ + b * x₂) = true

full_name: Lean.Omega.Constraint.combine
code: /-- The conjunction of two constraints. -/
def combine (x y : Constraint) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.combine_sat
code: theorem combine_sat : (c : Constraint) → (c' : Constraint) → (t : Int) →
    (c.combine c').sat t = (c.sat t ∧ c'.sat t) 
goal: ((c.combine c').sat t = true) = (c.sat t = true ∧ c'.sat t = true)

full_name: Lean.Omega.Constraint.div
code: /--
Dividing a constraint by a natural number, and tightened to integer bounds.
Thus the lower bound is rounded up, and the upper bound is rounded down.
-/
def div (c : Constraint) (k : Nat) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.Constraint.div_sat
code: theorem div_sat (c : Constraint) (t : Int) (k : Nat) (n : k ≠ 0) (h : (k : Int) ∣ t) (w : c.sat t) :
    (c.div k).sat (t / k) 
goal: (c.div k).sat (t / ↑k) = true

full_name: Lean.Omega.Constraint.sat'
code: /--
It is convenient below to say that a constraint is satisfied at the dot product of two vectors,
so we make an abbreviation `sat'` for this.
-/
abbrev sat' (c : Constraint) (x y : Coeffs) 
goal: Bool

full_name: Lean.Omega.Constraint.combine_sat'
code: theorem combine_sat' {s t : Constraint} {x y} (ws : s.sat' x y) (wt : t.sat' x y) :
    (s.combine t).sat' x y 
goal: (s.combine t).sat' x y = true

full_name: Lean.Omega.Constraint.div_sat'
code: theorem div_sat' {c : Constraint} {x y} (h : Coeffs.gcd x ≠ 0) (w : c.sat (Coeffs.dot x y)) :
    (c.div (Coeffs.gcd x)).sat' (Coeffs.sdiv x (Coeffs.gcd x)) y 
goal: (c.div x.gcd).sat' (x.sdiv ↑x.gcd) y = true

full_name: Lean.Omega.Constraint.not_sat'_of_isImpossible
code: theorem not_sat'_of_isImpossible (h : isImpossible c) {x y} : ¬ c.sat' x y 
goal: ¬c.sat' x y = true

full_name: Lean.Omega.Constraint.addInequality_sat
code: theorem addInequality_sat (w : c + Coeffs.dot x y ≥ 0) :
    Constraint.sat' { lowerBound := some (-c), upperBound := none } x y 
goal: { lowerBound := some (-c), upperBound := none }.sat' x y = true

full_name: Lean.Omega.Constraint.addEquality_sat
code: theorem addEquality_sat (w : c + Coeffs.dot x y = 0) :
    Constraint.sat' { lowerBound := some (-c), upperBound := some (-c) } x y 
goal: { lowerBound := some (-c), upperBound := some (-c) }.sat' x y = true

full_name: Lean.Omega.normalize?
code: /--
Normalize a constraint, by dividing through by the GCD.

Return `none` if there is nothing to do, to avoid adding unnecessary steps to the proof term.
-/
def normalize? : Constraint × Coeffs → Option (Constraint × Coeffs)
  
goal: Lean.Omega.Constraint × Lean.Omega.Coeffs → Option (Lean.Omega.Constraint × Lean.Omega.Coeffs)

full_name: Lean.Omega.normalize
code: /-- Normalize a constraint, by dividing through by the GCD. -/
def normalize (p : Constraint × Coeffs) : Constraint × Coeffs 
goal: Lean.Omega.Constraint × Lean.Omega.Coeffs

full_name: Lean.Omega.normalizeConstraint
code: /-- Shorthand for the first component of `normalize`. -/
-- This `noncomputable` (and others below) is a safeguard that we only use this in proofs.
noncomputable abbrev normalizeConstraint (s : Constraint) (x : Coeffs) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.normalizeCoeffs
code: /-- Shorthand for the second component of `normalize`. -/
noncomputable abbrev normalizeCoeffs (s : Constraint) (x : Coeffs) : Coeffs 
goal: Lean.Omega.Coeffs

full_name: Lean.Omega.normalize?_eq_some
code: theorem normalize?_eq_some (w : normalize? (s, x) = some (s', x')) :
    normalizeConstraint s x = s' ∧ normalizeCoeffs s x = x' 
goal: Lean.Omega.normalizeConstraint s x = s' ∧ Lean.Omega.normalizeCoeffs s x = x'

full_name: Lean.Omega.normalize_sat
code: theorem normalize_sat {s x v} (w : s.sat' x v) :
    (normalizeConstraint s x).sat' (normalizeCoeffs s x) v 
goal: (Lean.Omega.normalizeConstraint s x).sat' (Lean.Omega.normalizeCoeffs s x) v = true

full_name: Lean.Omega.positivize?
code: /-- Multiply by `-1` if the leading coefficient is negative, otherwise return `none`. -/
def positivize? : Constraint × Coeffs → Option (Constraint × Coeffs)
  
goal: Lean.Omega.Constraint × Lean.Omega.Coeffs → Option (Lean.Omega.Constraint × Lean.Omega.Coeffs)

full_name: Lean.Omega.positivize
code: /-- Multiply by `-1` if the leading coefficient is negative, otherwise do nothing. -/
noncomputable def positivize (p : Constraint × Coeffs) : Constraint × Coeffs 
goal: Lean.Omega.Constraint × Lean.Omega.Coeffs

full_name: Lean.Omega.positivizeConstraint
code: /-- Shorthand for the first component of `positivize`. -/
noncomputable abbrev positivizeConstraint (s : Constraint) (x : Coeffs) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.positivizeCoeffs
code: /-- Shorthand for the second component of `positivize`. -/
noncomputable abbrev positivizeCoeffs (s : Constraint) (x : Coeffs) : Coeffs 
goal: Lean.Omega.Coeffs

full_name: Lean.Omega.positivize?_eq_some
code: theorem positivize?_eq_some (w : positivize? (s, x) = some (s', x')) :
    positivizeConstraint s x = s' ∧ positivizeCoeffs s x = x' 
goal: Lean.Omega.positivizeConstraint s x = s' ∧ Lean.Omega.positivizeCoeffs s x = x'

full_name: Lean.Omega.positivize_sat
code: theorem positivize_sat {s x v} (w : s.sat' x v) :
    (positivizeConstraint s x).sat' (positivizeCoeffs s x) v 
goal: (Lean.Omega.positivizeConstraint s x).sat' (Lean.Omega.positivizeCoeffs s x) v = true

full_name: Lean.Omega.tidy?
code: /-- `positivize` and `normalize`, returning `none` if neither does anything. -/
def tidy? : Constraint × Coeffs → Option (Constraint × Coeffs)
  
goal: Lean.Omega.Constraint × Lean.Omega.Coeffs → Option (Lean.Omega.Constraint × Lean.Omega.Coeffs)

full_name: Lean.Omega.tidy
code: /-- `positivize` and `normalize` -/
def tidy (p : Constraint × Coeffs) : Constraint × Coeffs 
goal: Lean.Omega.Constraint × Lean.Omega.Coeffs

full_name: Lean.Omega.tidyConstraint
code: /-- Shorthand for the first component of `tidy`. -/
abbrev tidyConstraint (s : Constraint) (x : Coeffs) : Constraint 
goal: Lean.Omega.Constraint

full_name: Lean.Omega.tidyCoeffs
code: /-- Shorthand for the second component of `tidy`. -/
abbrev tidyCoeffs (s : Constraint) (x : Coeffs) : Coeffs 
goal: Lean.Omega.Coeffs

full_name: Lean.Omega.tidy_sat
code: theorem tidy_sat {s x v} (w : s.sat' x v) : (tidyConstraint s x).sat' (tidyCoeffs s x) v 
goal: (Lean.Omega.tidyConstraint s x).sat' (Lean.Omega.tidyCoeffs s x) v = true

full_name: Lean.Omega.combo_sat'
code: theorem combo_sat' (s t : Constraint)
    (a : Int) (x : Coeffs) (b : Int) (y : Coeffs) (v : Coeffs)
    (wx : s.sat' x v) (wy : t.sat' y v) :
    (Constraint.combo a s b t).sat' (Coeffs.combo a x b y) v 
goal: (Lean.Omega.Constraint.combo a s b t).sat' (Lean.Omega.Coeffs.combo a x b y) v = true

full_name: Lean.Omega.bmod_div_term
code: /-- The value of the new variable introduced when solving a hard equality. -/
abbrev bmod_div_term (m : Nat) (a b : Coeffs) : Int 
goal: Int

full_name: Lean.Omega.bmod_coeffs
code: /-- The coefficients of the new equation generated when solving a hard equality. -/
def bmod_coeffs (m : Nat) (i : Nat) (x : Coeffs) : Coeffs 
goal: Lean.Omega.Coeffs

full_name: Lean.Omega.bmod_sat
code: theorem bmod_sat (m : Nat) (r : Int) (i : Nat) (x v : Coeffs)
    (h : x.length ≤ i)  -- during proof reconstruction this will be by `decide`
    (p : Coeffs.get v i = bmod_div_term m x v) -- and this will be by `rfl`
    (w : (Constraint.exact r).sat' x v) :
    (Constraint.exact (Int.bmod r m)).sat' (bmod_coeffs m i x) v 
goal: (Lean.Omega.Constraint.exact (r.bmod m)).sat' (Lean.Omega.bmod_coeffs m i x) v = true