File: .lake/packages/lean4/src/lean/Lean/Elab/Tactic/Omega/Core.lean

full_name: Lean.Elab.Tactic.Omega.initFn._@..lake.packages.lean4.src.lean.Lean.Elab.Tactic.Omega.Core._hyg.5
code: initialize Lean.registerTraceClass `omega
goal: IO Unit

full_name: Lean.Elab.Tactic.Omega.«instToExprLinearCombo_.lake»
code: instance : ToExpr LinearCombo 
goal: Lean.ToExpr Lean.Omega.LinearCombo

full_name: Lean.Elab.Tactic.Omega.«instToExprConstraint_.lake»
code: instance : ToExpr Constraint 
goal: Lean.ToExpr Lean.Omega.Constraint

full_name: Lean.Elab.Tactic.Omega.Proof
code: /--
A delayed proof that a constraint is satisfied at the atoms.
-/
abbrev Proof : Type 
goal: Type

full_name: Lean.Elab.Tactic.Omega.Justification.tidy
code: /--
Our internal representation of an argument "justifying" that a constraint holds on some coefficients.
We'll use this to construct the proof term once a contradiction is found.
-/
inductive Justification : Constraint → Coeffs → Type
  /--
  `Problem.assumptions[i]` generates a proof that `s.sat' coeffs atoms`
  -/
  | assumption (s : Constraint) (x : Coeffs) (i : Nat) : Justification s x
  /-- The result of `tidy` on another `Justification`. -/
  | tidy (j : Justification s c) : Justification (tidyConstraint s c) (tidyCoeffs s c)
  /-- The result of `combine` on two `Justifications`. -/
  | combine {s t c} (j : Justification s c) (k : Justification t c) : Justification (s.combine t) c
  /-- A linear `combo` of two `Justifications`. -/
  | combo {s t x y} (a : Int) (j : Justification s x) (b : Int) (k : Justification t y) :
    Justification (Constraint.combo a s b t) (Coeffs.combo a x b y)
  /--
  The justification for the constraing constructed using "balanced mod" while
  eliminating an equality.
  -/
  | bmod (m : Nat) (r : Int) (i : Nat) {x} (j : Justification (.exact r) x) :
      Justification (.exact (Int.bmod r m)) (bmod_coeffs m i x)
goal: Lean.Elab.Tactic.Omega.Justification (Lean.Omega.tidyConstraint s c) (Lean.Omega.tidyCoeffs s c)

full_name: Lean.Elab.Tactic.Omega.Justification.assumption
code: /--
Our internal representation of an argument "justifying" that a constraint holds on some coefficients.
We'll use this to construct the proof term once a contradiction is found.
-/
inductive Justification : Constraint → Coeffs → Type
  /--
  `Problem.assumptions[i]` generates a proof that `s.sat' coeffs atoms`
  -/
  | assumption (s : Constraint) (x : Coeffs) (i : Nat) : Justification s x
  /-- The result of `tidy` on another `Justification`. -/
  | tidy (j : Justification s c) : Justification (tidyConstraint s c) (tidyCoeffs s c)
  /-- The result of `combine` on two `Justifications`. -/
  | combine {s t c} (j : Justification s c) (k : Justification t c) : Justification (s.combine t) c
  /-- A linear `combo` of two `Justifications`. -/
  | combo {s t x y} (a : Int) (j : Justification s x) (b : Int) (k : Justification t y) :
    Justification (Constraint.combo a s b t) (Coeffs.combo a x b y)
  /--
  The justification for the constraing constructed using "balanced mod" while
  eliminating an equality.
  -/
  | bmod (m : Nat) (r : Int) (i : Nat) {x} (j : Justification (.exact r) x) :
      Justification (.exact (Int.bmod r m)) (bmod_coeffs m i x)
goal: Lean.Elab.Tactic.Omega.Justification s x

full_name: Lean.Elab.Tactic.Omega.Justification
code: /--
Our internal representation of an argument "justifying" that a constraint holds on some coefficients.
We'll use this to construct the proof term once a contradiction is found.
-/
inductive Justification : Constraint → Coeffs → Type
  /--
  `Problem.assumptions[i]` generates a proof that `s.sat' coeffs atoms`
  -/
  | assumption (s : Constraint) (x : Coeffs) (i : Nat) : Justification s x
  /-- The result of `tidy` on another `Justification`. -/
  | tidy (j : Justification s c) : Justification (tidyConstraint s c) (tidyCoeffs s c)
  /-- The result of `combine` on two `Justifications`. -/
  | combine {s t c} (j : Justification s c) (k : Justification t c) : Justification (s.combine t) c
  /-- A linear `combo` of two `Justifications`. -/
  | combo {s t x y} (a : Int) (j : Justification s x) (b : Int) (k : Justification t y) :
    Justification (Constraint.combo a s b t) (Coeffs.combo a x b y)
  /--
  The justification for the constraing constructed using "balanced mod" while
  eliminating an equality.
  -/
  | bmod (m : Nat) (r : Int) (i : Nat) {x} (j : Justification (.exact r) x) :
      Justification (.exact (Int.bmod r m)) (bmod_coeffs m i x)
goal: Lean.Omega.Constraint → Lean.Omega.Coeffs → Type

full_name: Lean.Elab.Tactic.Omega.Justification.bmod
code: /--
Our internal representation of an argument "justifying" that a constraint holds on some coefficients.
We'll use this to construct the proof term once a contradiction is found.
-/
inductive Justification : Constraint → Coeffs → Type
  /--
  `Problem.assumptions[i]` generates a proof that `s.sat' coeffs atoms`
  -/
  | assumption (s : Constraint) (x : Coeffs) (i : Nat) : Justification s x
  /-- The result of `tidy` on another `Justification`. -/
  | tidy (j : Justification s c) : Justification (tidyConstraint s c) (tidyCoeffs s c)
  /-- The result of `combine` on two `Justifications`. -/
  | combine {s t c} (j : Justification s c) (k : Justification t c) : Justification (s.combine t) c
  /-- A linear `combo` of two `Justifications`. -/
  | combo {s t x y} (a : Int) (j : Justification s x) (b : Int) (k : Justification t y) :
    Justification (Constraint.combo a s b t) (Coeffs.combo a x b y)
  /--
  The justification for the constraing constructed using "balanced mod" while
  eliminating an equality.
  -/
  | bmod (m : Nat) (r : Int) (i : Nat) {x} (j : Justification (.exact r) x) :
      Justification (.exact (Int.bmod r m)) (bmod_coeffs m i x)
goal: Lean.Elab.Tactic.Omega.Justification (Lean.Omega.Constraint.exact (r.bmod m)) (Lean.Omega.bmod_coeffs m i x)

full_name: Lean.Elab.Tactic.Omega.Justification.combine
code: /--
Our internal representation of an argument "justifying" that a constraint holds on some coefficients.
We'll use this to construct the proof term once a contradiction is found.
-/
inductive Justification : Constraint → Coeffs → Type
  /--
  `Problem.assumptions[i]` generates a proof that `s.sat' coeffs atoms`
  -/
  | assumption (s : Constraint) (x : Coeffs) (i : Nat) : Justification s x
  /-- The result of `tidy` on another `Justification`. -/
  | tidy (j : Justification s c) : Justification (tidyConstraint s c) (tidyCoeffs s c)
  /-- The result of `combine` on two `Justifications`. -/
  | combine {s t c} (j : Justification s c) (k : Justification t c) : Justification (s.combine t) c
  /-- A linear `combo` of two `Justifications`. -/
  | combo {s t x y} (a : Int) (j : Justification s x) (b : Int) (k : Justification t y) :
    Justification (Constraint.combo a s b t) (Coeffs.combo a x b y)
  /--
  The justification for the constraing constructed using "balanced mod" while
  eliminating an equality.
  -/
  | bmod (m : Nat) (r : Int) (i : Nat) {x} (j : Justification (.exact r) x) :
      Justification (.exact (Int.bmod r m)) (bmod_coeffs m i x)
goal: Lean.Elab.Tactic.Omega.Justification (s.combine t) c

full_name: Lean.Elab.Tactic.Omega.Justification.combo
code: /--
Our internal representation of an argument "justifying" that a constraint holds on some coefficients.
We'll use this to construct the proof term once a contradiction is found.
-/
inductive Justification : Constraint → Coeffs → Type
  /--
  `Problem.assumptions[i]` generates a proof that `s.sat' coeffs atoms`
  -/
  | assumption (s : Constraint) (x : Coeffs) (i : Nat) : Justification s x
  /-- The result of `tidy` on another `Justification`. -/
  | tidy (j : Justification s c) : Justification (tidyConstraint s c) (tidyCoeffs s c)
  /-- The result of `combine` on two `Justifications`. -/
  | combine {s t c} (j : Justification s c) (k : Justification t c) : Justification (s.combine t) c
  /-- A linear `combo` of two `Justifications`. -/
  | combo {s t x y} (a : Int) (j : Justification s x) (b : Int) (k : Justification t y) :
    Justification (Constraint.combo a s b t) (Coeffs.combo a x b y)
  /--
  The justification for the constraing constructed using "balanced mod" while
  eliminating an equality.
  -/
  | bmod (m : Nat) (r : Int) (i : Nat) {x} (j : Justification (.exact r) x) :
      Justification (.exact (Int.bmod r m)) (bmod_coeffs m i x)
goal: Lean.Elab.Tactic.Omega.Justification (Lean.Omega.Constraint.combo a s b t) (Lean.Omega.Coeffs.combo a x b y)

full_name: Lean.Elab.Tactic.Omega.Justification.tidy?
code: /-- Wrapping for `Justification.tidy` when `tidy?` is nonempty. -/
nonrec def Justification.tidy? (j : Justification s c) : Option (Σ s' c', Justification s' c') 
goal: Option ((s' : Lean.Omega.Constraint) × (c' : Lean.Omega.Coeffs) × Lean.Elab.Tactic.Omega.Justification s' c')

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Tactic.Omega.Core.0.Lean.Elab.Tactic.Omega.Justification.bullet
code: private def bullet (s : String) 
goal: String

full_name: Lean.Elab.Tactic.Omega.Justification.toString
code: /-- Print a `Justification` as an indented tree structure. -/
def toString : Justification s x → String
  
goal: Lean.Elab.Tactic.Omega.Justification s x → String

full_name: Lean.Elab.Tactic.Omega.Justification.instToString
code: instance : ToString (Justification s x) 
goal: ToString (Lean.Elab.Tactic.Omega.Justification s x)

full_name: Lean.Elab.Tactic.Omega.Justification.tidyProof
code: /-- Construct the proof term associated to a `tidy` step. -/
def tidyProof (s : Constraint) (x : Coeffs) (v : Expr) (prf : Expr) : Expr 
goal: Lean.Expr

full_name: Lean.Elab.Tactic.Omega.Justification.combineProof
code: /-- Construct the proof term associated to a `combine` step. -/
def combineProof (s t : Constraint) (x : Coeffs) (v : Expr) (ps pt : Expr) : Expr 
goal: Lean.Expr

full_name: Lean.Elab.Tactic.Omega.Justification.comboProof
code: /-- Construct the proof term associated to a `combo` step. -/
def comboProof (s t : Constraint) (a : Int) (x : Coeffs) (b : Int) (y : Coeffs)
    (v : Expr) (px py : Expr) : Expr 
goal: Lean.Expr

full_name: Lean.Elab.Tactic.Omega.Justification.bmodProof
code: /-- Construct the proof term associated to a `bmod` step. -/
def bmodProof (m : Nat) (r : Int) (i : Nat) (x : Coeffs) (v : Expr) (w : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Lean.Elab.Tactic.Omega.Justification.proof
code: /-- Constructs a proof that `s.sat' c v = true` -/
def proof (v : Expr) (assumptions : Array Proof) : Justification s c → Proof
  
goal: Lean.Elab.Tactic.Omega.Justification s c → Lean.Elab.Tactic.Omega.Proof

full_name: Lean.Elab.Tactic.Omega.Fact.justification
code: /-- A `Justification` bundled together with its parameters. -/
structure Fact where
  /-- The coefficients of a constraint. -/
  coeffs : Coeffs
  /-- The constraint. -/
  constraint : Constraint
  /-- The justification of a derived fact. -/
  justification : Justification constraint coeffs
goal: Lean.Elab.Tactic.Omega.Justification self.constraint self.coeffs

full_name: Lean.Elab.Tactic.Omega.Fact
code: /-- A `Justification` bundled together with its parameters. -/
structure Fact where
  /-- The coefficients of a constraint. -/
  coeffs : Coeffs
  /-- The constraint. -/
  constraint : Constraint
  /-- The justification of a derived fact. -/
  justification : Justification constraint coeffs
goal: Type

full_name: Lean.Elab.Tactic.Omega.Fact.constraint
code: /-- A `Justification` bundled together with its parameters. -/
structure Fact where
  /-- The coefficients of a constraint. -/
  coeffs : Coeffs
  /-- The constraint. -/
  constraint : Constraint
  /-- The justification of a derived fact. -/
  justification : Justification constraint coeffs
goal: Lean.Omega.Constraint

full_name: Lean.Elab.Tactic.Omega.Fact.coeffs
code: /-- A `Justification` bundled together with its parameters. -/
structure Fact where
  /-- The coefficients of a constraint. -/
  coeffs : Coeffs
  /-- The constraint. -/
  constraint : Constraint
  /-- The justification of a derived fact. -/
  justification : Justification constraint coeffs
goal: Lean.Omega.Coeffs

full_name: Lean.Elab.Tactic.Omega.Fact.instToString
code: instance : ToString Fact 
goal: ToString Lean.Elab.Tactic.Omega.Fact

full_name: Lean.Elab.Tactic.Omega.Fact.tidy
code: /-- `tidy`, implemented on `Fact`. -/
def tidy (f : Fact) : Fact 
goal: Lean.Elab.Tactic.Omega.Fact

full_name: Lean.Elab.Tactic.Omega.Fact.combo
code: /-- `combo`, implemented on `Fact`. -/
def combo (a : Int) (f : Fact) (b : Int) (g : Fact) : Fact 
goal: Lean.Elab.Tactic.Omega.Fact

full_name: Lean.Elab.Tactic.Omega.Problem.numVars
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Nat

full_name: Lean.Elab.Tactic.Omega.Problem.constraints
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Lean.HashMap Lean.Omega.Coeffs Lean.Elab.Tactic.Omega.Fact

full_name: Lean.Elab.Tactic.Omega.Problem.assumptions
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Array Lean.Elab.Tactic.Omega.Proof

full_name: Lean.Elab.Tactic.Omega.Problem.proveFalse?_spec
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: (self.possible || self.proveFalse?.isSome) = true

full_name: Lean.Elab.Tactic.Omega.Problem.equalities
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Lean.HashSet Lean.Omega.Coeffs

full_name: Lean.Elab.Tactic.Omega.Problem.explanation?
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Thunk String

full_name: Lean.Elab.Tactic.Omega.Problem.possible
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Bool

full_name: Lean.Elab.Tactic.Omega.Problem.proveFalse?
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Option Lean.Elab.Tactic.Omega.Proof

full_name: Lean.Elab.Tactic.Omega.Problem.eliminations
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: List (Lean.Elab.Tactic.Omega.Fact × Nat × Int)

full_name: Lean.Elab.Tactic.Omega.Problem
code: /--
A `omega` problem.

This is a hybrid structure:
it contains both `Expr` objects giving proofs of the "ground" assumptions
(or rather continuations which will produce the proofs when needed)
and internal representations of the linear constraints that we manipulate in the algorithm.

While the algorithm is running we do not synthesize any new `Expr` proofs: proof extraction happens
only once we've found a contradiction.
-/
structure Problem where
  /-- The ground assumptions that the algorithm starts from. -/
  assumptions : Array Proof := ∅
  /-- The number of variables in the problem. -/
  numVars : Nat := 0
  /-- The current constraints, indexed by their coefficients. -/
  constraints : HashMap Coeffs Fact := ∅
  /--
  The coefficients for which `constraints` contains an exact constraint (i.e. an equality).
  -/
  equalities : HashSet Coeffs := ∅
  /--
  Equations that have already been used to eliminate variables,
  along with the variable which was removed, and its coefficient (either `1` or `-1`).
  The earlier elements are more recent,
  so if these are being reapplied it is essential to use `List.foldr`.
  -/
  eliminations : List (Fact × Nat × Int) := []
  /-- Whether the problem is possible. -/
  possible : Bool := true
  /-- If the problem is impossible, then `proveFalse?` will contain a proof of `False`. -/
  proveFalse? : Option Proof := none
  /-- Invariant between `possible` and `proveFalse?`. -/
  proveFalse?_spec : possible || proveFalse?.isSome := by rfl
  /--
  If we have found a contradiction,
  `explanation?` will contain a human readable account of the deriviation.
  -/
  explanation? : Thunk String := ""
goal: Type

full_name: Lean.Elab.Tactic.Omega.Problem.isEmpty
code: /-- Check if a problem has no constraints. -/
def isEmpty (p : Problem) : Bool 
goal: Bool

full_name: Lean.Elab.Tactic.Omega.Problem.instToString
code: instance : ToString Problem 
goal: ToString Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.proveFalse
code: /--
Takes a proof that `s.sat' x v` for some `s` such that `s.isImpossible`,
and constructs a proof of `False`.
-/
def proveFalse {s x} (j : Justification s x) (assumptions : Array Proof) : Proof 
goal: Lean.Elab.Tactic.Omega.Proof

full_name: Lean.Elab.Tactic.Omega.Problem.insertConstraint
code: /--
Insert a constraint into the problem,
without checking if there is already a constraint for these coefficients.
-/
def insertConstraint (p : Problem) : Fact → Problem
  
goal: Lean.Elab.Tactic.Omega.Fact → Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.addConstraint
code: /--
Add a constraint into the problem,
combining it with any existing constraints for the same coefficients.
-/
def addConstraint (p : Problem) : Fact → Problem
  
goal: Lean.Elab.Tactic.Omega.Fact → Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.selectEquality
code: /--
Walk through the equalities, finding either the first equality with minimal coefficient `±1`,
or otherwise the equality with minimal `(r.minNatAbs, r.maxNatAbs)` (ordered lexicographically).

Returns the coefficients of the equality, along with the value of `minNatAbs`.

Although we don't need to run a termination proof here, it's nevertheless important that we use this
ordering so the algorithm terminates in practice!
-/
def selectEquality (p : Problem) : Option (Coeffs × Nat) 
goal: Option (Lean.Omega.Coeffs × Nat)

full_name: Lean.Elab.Tactic.Omega.Problem.replayEliminations
code: /--
If we have already solved some equalities, apply those to some new `Fact`.
-/
def replayEliminations (p : Problem) (f : Fact) : Fact 
goal: Lean.Elab.Tactic.Omega.Fact

full_name: Lean.Elab.Tactic.Omega.Problem.solveEasyEquality
code: /--
Solve an "easy" equality, i.e. one with a coefficient that is `±1`.

After solving, the variable will have been eliminated from all constraints.
-/
def solveEasyEquality (p : Problem) (c : Coeffs) : Problem 
goal: Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.dealWithHardEquality
code: /--
We deal with a hard equality by introducing a new easy equality.

After solving the easy equality,
the minimum lexicographic value of `(c.minNatAbs, c.maxNatAbs)` will have been reduced.
-/
def dealWithHardEquality (p : Problem) (c : Coeffs) : OmegaM Problem 
goal: Lean.Elab.Tactic.Omega.OmegaM Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.solveEquality
code: /--
Solve an equality, by deciding whether it is easy (has a `±1` coefficient) or hard,
and delegating to the appropriate function.
-/
def solveEquality (p : Problem) (c : Coeffs) (m : Nat) : OmegaM Problem 
goal: Lean.Elab.Tactic.Omega.OmegaM Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.solveEqualities
code: /-- Recursively solve all equalities. -/
partial def solveEqualities (p : Problem) : OmegaM Problem 
goal: Lean.Elab.Tactic.Omega.OmegaM Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.addInequality_proof
code: /-- Constructing the proof term for `addInequality`. -/
def addInequality_proof (c : Int) (x : Coeffs) (p : Proof) : Proof 
goal: Lean.Elab.Tactic.Omega.Proof

full_name: Lean.Elab.Tactic.Omega.Problem.addEquality_proof
code: /-- Constructing the proof term for `addEquality`. -/
def addEquality_proof (c : Int) (x : Coeffs) (p : Proof) : Proof 
goal: Lean.Elab.Tactic.Omega.Proof

full_name: Lean.Elab.Tactic.Omega.Problem.addInequality
code: /--
Helper function for adding an inequality of the form `const + Coeffs.dot coeffs atoms ≥ 0`
to a `Problem`.

(This is only used while initializing a `Problem`. During elimination we use `addConstraint`.)
-/
-- We are given `prf? : const + Coeffs.dot coeffs atoms ≥ 0`,
-- and need to transform this to `Coeffs.dot coeffs atoms ≥ -const`.
def addInequality (p : Problem) (const : Int) (coeffs : Coeffs) (prf? : Option Proof) : Problem 
goal: Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.addEquality
code: /--
Helper function for adding an equality of the form `const + Coeffs.dot coeffs atoms = 0`
to a `Problem`.

(This is only used while initializing a `Problem`. During elimination we use `addConstraint`.)
-/
def addEquality (p : Problem) (const : Int) (coeffs : Coeffs) (prf? : Option Proof) : Problem 
goal: Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.addInequalities
code: /-- Folding `addInequality` over a list. -/
def addInequalities (p : Problem) (ineqs : List (Int × Coeffs × Option Proof)) : Problem 
goal: Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.addEqualities
code: /-- Folding `addEquality` over a list. -/
def addEqualities (p : Problem) (eqs : List (Int × Coeffs × Option Proof)) : Problem 
goal: Lean.Elab.Tactic.Omega.Problem

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.lowerBounds
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: List (Lean.Elab.Tactic.Omega.Fact × Int)

full_name: Lean.Elab.Tactic.Omega.Problem.instInhabitedFourierMotzkinData
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: Inhabited Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.lowerExact
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: Bool

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: Type

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.upperBounds
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: List (Lean.Elab.Tactic.Omega.Fact × Int)

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.var
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: Nat

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.upperExact
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: Bool

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.irrelevant
code: /-- Representation of the data required to run Fourier-Motzkin elimination on a variable. -/
structure FourierMotzkinData where
  /-- Which variable is being eliminated. -/
  var : Nat
  /-- The "irrelevant" facts which do not involve the target variable. -/
  irrelevant : List Fact := []
  /--
  The facts which give a lower bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  lowerBounds : List (Fact × Int) := []
  /--
  The facts which give an upper bound on the target variable,
  and the coefficient of the target variable in each.
  -/
  upperBounds : List (Fact × Int) := []
  /--
  Whether the elimination would be exact, because all of the lower bound coefficients are `±1`.
  -/
  lowerExact : Bool := true
  /--
  Whether the elimination would be exact, because all of the upper bound coefficients are `±1`.
  -/
  upperExact : Bool := true
deriving Inhabited
goal: List Lean.Elab.Tactic.Omega.Fact

full_name: Lean.Elab.Tactic.Omega.Problem.instToStringFourierMotzkinData
code: instance : ToString FourierMotzkinData 
goal: ToString Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.isEmpty
code: /-- Is a Fourier-Motzkin elimination empty (i.e. there are no relevant constraints). -/
def FourierMotzkinData.isEmpty (d : FourierMotzkinData) : Bool 
goal: Bool

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.size
code: /-- The number of new constraints that would be introduced by Fourier-Motzkin elimination. -/
def FourierMotzkinData.size (d : FourierMotzkinData) : Nat 
goal: Nat

full_name: Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData.exact
code: /-- Is the Fourier-Motzkin elimination known to be exact? -/
def FourierMotzkinData.exact (d : FourierMotzkinData) : Bool 
goal: Bool

full_name: Lean.Elab.Tactic.Omega.Problem.fourierMotzkinData
code: /-- Prepare the Fourier-Motzkin elimination data for each variable. -/
-- TODO we could short-circuit here, if we find one with `size = 0`.
def fourierMotzkinData (p : Problem) : Array FourierMotzkinData 
goal: Array Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData

full_name: Lean.Elab.Tactic.Omega.Problem.fourierMotzkinSelect
code: /--
Decides which variable to run Fourier-Motzkin elimination on, and returns the associated data.

We prefer eliminations which introduce no new inequalities, or otherwise exact eliminations,
and break ties by the number of new inequalities introduced.
-/
def fourierMotzkinSelect (data : Array FourierMotzkinData) : MetaM FourierMotzkinData 
goal: Lean.MetaM Lean.Elab.Tactic.Omega.Problem.FourierMotzkinData

full_name: Lean.Elab.Tactic.Omega.Problem.fourierMotzkin
code: /--
Run Fourier-Motzkin elimination on one variable.
-/
-- This is only in MetaM to enable tracing.
def fourierMotzkin (p : Problem) : MetaM Problem 
goal: Lean.MetaM Lean.Elab.Tactic.Omega.Problem