@@ -17,20 +17,35 @@ def mkLePreorderPrefix (declName : Name) : OrderM Expr := do
1717 return mkApp3 (mkConst declName [s.u]) s.type s.leInst s.isPreorderInst
1818
1919/--
20- Returns `declName α leInst ltInst lawfulOrderLtInst isPreorderInst `
20+ Returns `declName α leInst ltInst lawfulOrderLtInst`
2121-/
2222def mkLeLtPrefix (declName : Name) : OrderM Expr := do
2323 let s ← getStruct
24- return mkApp5 (mkConst declName [s.u]) s.type s.leInst s.ltInst?.get! s.lawfulOrderLTInst?.get! s.isPreorderInst
24+ return mkApp4 (mkConst declName [s.u]) s.type s.leInst s.ltInst?.get! s.lawfulOrderLTInst?.get!
25+
26+ /--
27+ Returns `declName α leInst ltInst lawfulOrderLtInst isPreorderInst`
28+ -/
29+ def mkLeLtPreorderPrefix (declName : Name) : OrderM Expr := do
30+ let s ← getStruct
31+ return mkApp (← mkLeLtPrefix declName) s.isPreorderInst
2532
2633/--
2734Returns `declName α leInst ltInst lawfulOrderLtInst isPreorderInst ringInst ordRingInst`
2835-/
2936def mkOrdRingPrefix (declName : Name) : OrderM Expr := do
3037 let s ← getStruct
31- let h ← mkLeLtPrefix declName
38+ let h ← mkLeLtPreorderPrefix declName
3239 return mkApp2 h s.ringInst?.get! s.orderedRingInst?.get!
3340
41+ def mkTransCoreProof (u v w : Expr) (strict₁ strict₂ : Bool) (h₁ h₂ : Expr) : OrderM Expr := do
42+ let h ← match strict₁, strict₂ with
43+ | false , false => mkLePreorderPrefix ``Grind.Order.le_trans
44+ | false , true => mkLeLtPreorderPrefix ``Grind.Order.le_lt_trans
45+ | true , false => mkLeLtPreorderPrefix ``Grind.Order.lt_le_trans
46+ | true , true => mkLeLtPreorderPrefix ``Grind.Order.lt_trans
47+ return mkApp5 h u v w h₁ h₂
48+
3449/--
3550Assume `p₁` is `{ w := u, k := k₁, proof := p₁ }` and `p₂` is `{ w := w, k := k₂, proof := p₂ }`
3651`p₁` is the proof for edge `u → w` and `p₂` the proof for edge `w -> v`.
@@ -41,15 +56,20 @@ Remark: for orders that do not support offsets.
4156def mkTransCore (p₁ : ProofInfo) (p₂ : ProofInfo) (v : NodeId) : OrderM ProofInfo := do
4257 let { w := u, k.strict := s₁, proof := h₁, .. } := p₁
4358 let { w, k.strict := s₂, proof := h₂, .. } := p₂
44- let h ← match s₁, s₂ with
45- | false , false => mkLePreorderPrefix ``Grind.Order.le_trans
46- | false , true => mkLeLtPrefix ``Grind.Order.le_lt_trans
47- | true , false => mkLeLtPrefix ``Grind.Order.lt_le_trans
48- | true , true => mkLeLtPrefix ``Grind.Order.lt_trans
4959 let ns := (← getStruct).nodes
50- let h := mkApp5 h ns[u]! ns[w]! ns[v]! h₁ h₂
60+ let h ← mkTransCoreProof ns[u]! ns[w]! ns[v]! s₁ s₂ h₁ h₂
5161 return { w := p₁.w, k.strict := s₁ || s₂, proof := h }
5262
63+ def mkTransOffsetProof (u v w : Expr) (k₁ k₂ : Weight) (h₁ h₂ : Expr) : OrderM Expr := do
64+ let h ← match k₁.strict, k₂.strict with
65+ | false , false => mkOrdRingPrefix ``Grind.Order.le_trans_k
66+ | false , true => mkOrdRingPrefix ``Grind.Order.le_lt_trans_k
67+ | true , false => mkOrdRingPrefix ``Grind.Order.lt_le_trans_k
68+ | true , true => mkOrdRingPrefix ``Grind.Order.lt_trans_k
69+ let k := k₁.k + k₂.k
70+ let h := mkApp6 h u v w (toExpr k₁.k) (toExpr k₂.k) (toExpr k)
71+ return mkApp3 h h₁ h₂ eagerReflBoolTrue
72+
5373/--
5474Assume `p₁` is `{ w := u, k := k₁, proof := p₁ }` and `p₂` is `{ w := w, k := k₂, proof := p₂ }`
5575`p₁` is the proof for edge `u -(k₁)→ w` and `p₂` the proof for edge `w -(k₂)-> v`.
@@ -58,18 +78,11 @@ Then, this function returns a proof for edge `u -(k₁+k₂) -> v`.
5878Remark: for orders that support offsets.
5979-/
6080def mkTransOffset (p₁ : ProofInfo) (p₂ : ProofInfo) (v : NodeId) : OrderM ProofInfo := do
61- let { w := u, k.k := k₁, k.strict := s₁, proof := h₁, .. } := p₁
62- let { w, k.k := k₂, k.strict := s₂, proof := h₂, .. } := p₂
63- let h ← match s₁, s₂ with
64- | false , false => mkOrdRingPrefix ``Grind.Order.le_trans_k
65- | false , true => mkOrdRingPrefix ``Grind.Order.le_lt_trans_k
66- | true , false => mkOrdRingPrefix ``Grind.Order.lt_le_trans_k
67- | true , true => mkOrdRingPrefix ``Grind.Order.lt_trans_k
68- let k := k₁ + k₂
81+ let { w := u, k:= k₁, proof := h₁, .. } := p₁
82+ let { w, k := k₂, proof := h₂, .. } := p₂
6983 let ns := (← getStruct).nodes
70- let h := mkApp6 h ns[u]! ns[w]! ns[v]! (toExpr k₁) (toExpr k₂) (toExpr k)
71- let h := mkApp3 h h₁ h₂ eagerReflBoolTrue
72- return { w := p₁.w, k.k := k, k.strict := s₁ || s₂, proof := h }
84+ let h ← mkTransOffsetProof ns[u]! ns[w]! ns[v]! k₁ k₂ h₁ h₂
85+ return { w := p₁.w, k.k := k₁.k + k₂.k, k.strict := k₁.strict || k₂.strict, proof := h }
7386
7487/--
7588Assume `p₁` is `{ w := u, k := k₁, proof := p₁ }` and `p₂` is `{ w := w, k := k₂, proof := p₂ }`
@@ -79,10 +92,88 @@ Then, this function returns a proof for edge `u -(k₁+k₂) -> v`.
7992Remark: if the order does not support offset `k₁` and `k₂` are zero.
8093-/
8194public def mkTrans (p₁ : ProofInfo) (p₂ : ProofInfo) (v : NodeId) : OrderM ProofInfo := do
82- let s ← getStruct
83- if s.orderedRingInst?.isSome then
95+ if (← isRing) then
8496 mkTransOffset p₁ p₂ v
8597 else
8698 mkTransCore p₁ p₂ v
8799
100+ def mkPropagateEqTrueProofCore (u v : Expr) (k : Weight) (huv : Expr) (k' : Weight) : OrderM Expr := do
101+ if k.strict == k'.strict then
102+ mkEqTrue huv
103+ else
104+ assert! k.strict && !k'.strict
105+ let h ← mkLeLtPrefix ``Grind.Order.le_eq_true_of_lt
106+ return mkApp3 h u v huv
107+
108+ def mkPropagateEqTrueProofOffset (u v : Expr) (k : Weight) (huv : Expr) (k' : Weight) : OrderM Expr := do
109+ let declName := match k'.strict, k.strict with
110+ | false , false => ``Grind.Order.le_eq_true_of_le_k
111+ | false , true => ``Grind.Order.le_eq_true_of_lt_k
112+ | true , false => ``Grind.Order.lt_eq_true_of_le_k
113+ | true , true => ``Grind.Order.lt_eq_true_of_lt_k
114+ let h ← mkOrdRingPrefix declName
115+ return mkApp6 h u v (toExpr k.k) (toExpr k'.k) eagerReflBoolTrue huv
116+
117+ /--
118+ Given a path `u --(k)--> v` justified by proof `huv`,
119+ construct a proof of `e = True` where `e` is a term corresponding to the edge `u --(k') --> v`
120+ -/
121+ public def mkPropagateEqTrueProof (u v : Expr) (k : Weight) (huv : Expr) (k' : Weight) : OrderM Expr := do
122+ if (← isRing) then
123+ mkPropagateEqTrueProofOffset u v k huv k'
124+ else
125+ mkPropagateEqTrueProofCore u v k huv k'
126+
127+ /--
128+ `u < v → (v ≤ u) = False
129+ -/
130+ def mkPropagateEqFalseProofCore (u v : Expr) (huv : Expr) : OrderM Expr := do
131+ let h ← mkLeLtPreorderPrefix ``Grind.Order.le_eq_false_of_lt
132+ return mkApp3 h u v huv
133+
134+ def mkPropagateEqFalseProofOffset (u v : Expr) (k : Weight) (huv : Expr) (k' : Weight) : OrderM Expr := do
135+ let declName := match k'.strict, k.strict with
136+ | false , false => ``Grind.Order.le_eq_false_of_le_k
137+ | false , true => ``Grind.Order.le_eq_false_of_lt_k
138+ | true , false => ``Grind.Order.lt_eq_false_of_le_k
139+ | true , true => ``Grind.Order.lt_eq_false_of_lt_k
140+ let h ← mkOrdRingPrefix declName
141+ return mkApp6 h u v (toExpr k.k) (toExpr k'.k) eagerReflBoolTrue huv
142+
143+ /--
144+ Given a path `u --(k)--> v` justified by proof `huv`,
145+ construct a proof of `e = False` where `e` is a term corresponding to the edge `u --(k') --> v`
146+ -/
147+ public def mkPropagateEqFalseProof (u v : Expr) (k : Weight) (huv : Expr) (k' : Weight) : OrderM Expr := do
148+ if (← isRing) then
149+ mkPropagateEqFalseProofOffset u v k huv k'
150+ else
151+ mkPropagateEqFalseProofCore u v huv
152+
153+ def mkUnsatProofCore (u v : Expr) (k₁ : Weight) (h₁ : Expr) (k₂ : Weight) (h₂ : Expr) : OrderM Expr := do
154+ let h ← mkTransCoreProof u v u k₁.strict k₂.strict h₁ h₂
155+ assert! k₁.strict || k₂.strict
156+ let hf ← mkLeLtPreorderPrefix ``Grind.Order.lt_unsat
157+ return mkApp2 hf u h
158+
159+ def mkUnsatProofOffset (u v : Expr) (k₁ : Weight) (h₁ : Expr) (k₂ : Weight) (h₂ : Expr) : OrderM Expr := do
160+ let h ← mkTransOffsetProof u v u k₁ k₂ h₁ h₂
161+ let declName := if k₁.strict || k₂.strict then
162+ ``Grind.Order.lt_unsat_k
163+ else
164+ ``Grind.Order.le_unsat_k
165+ let hf ← mkOrdRingPrefix declName
166+ return mkApp4 hf u (toExpr (k₁.k + k₂.k)) eagerReflBoolTrue h
167+
168+ /--
169+ Returns a proof of `False` using a negative cycle composed of
170+ - `u --(k₁)--> v` with proof `h₁`
171+ - `v --(k₂)--> u` with proof `h₂`
172+ -/
173+ def mkUnsatProof (u v : Expr) (k₁ : Weight) (h₁ : Expr) (k₂ : Weight) (h₂ : Expr) : OrderM Expr := do
174+ if (← isRing) then
175+ mkUnsatProofOffset u v k₁ h₁ k₂ h₂
176+ else
177+ mkUnsatProofCore u v k₁ h₁ k₂ h₂
178+
88179end Lean.Meta.Grind.Order
0 commit comments