Skip to content

Commit 06ae349

Browse files
committed
Fix bugs in failing examples.
1 parent e83b436 commit 06ae349

3 files changed

Lines changed: 89 additions & 49 deletions

File tree

Smt/Reconstruct.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def traceSolve (r : Except Exception (Except Error cvc5Result)) : MetaM MessageD
262262
| _ => m!"{bombEmoji}"
263263

264264
def defaultSolverOptions : List (String × String) := [
265-
("dag-thresh", "0"),
265+
-- ("dag-thresh", "0"),
266266
("simplification", "none"),
267267
("enum-inst", "true"),
268268
("enum-inst-interleave", "true"),

Smt/Reconstruct/ZMod.lean

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ def Lean.Expr.mvarId? : Expr → Option MVarId
3232
| mvar n => some n
3333
| _ => none
3434

35+
def List.zmodRange (n : Nat) : List (ZMod n) :=
36+
List.range n
3537

3638
namespace Smt.Reconstruct.ZMod
3739

38-
39-
4040
open Lean Expr
4141
open Qq
4242
open Translator Term
@@ -350,7 +350,7 @@ theorem roots_complete [Fact n.Prime] {p : Expr n}
350350
theorem root_branch [Fact n.Prime] {ps} {p : Expr n} {i rs}
351351
(hps : variety (ideal ps) ≠ ∅) (hp : p.toPoly ∈ ideal ps)
352352
(hpirs : p.completeRoots i rs)
353-
: orN (rs.map fun r => variety (ideal (ps ++ [.X i + -.C r])) ≠ ∅) := by
353+
: orN (rs.map fun r => variety (ideal (ps ++ [.X i + .C (-r)])) ≠ ∅) := by
354354
rcases Set.nonempty_iff_ne_empty.mpr hps with ⟨ctx, hctx⟩
355355
have hctx' : ∀ q ∈ ideal ps, MvPolynomial.aeval ctx q = 0 :=
356356
MvPolynomial.mem_zeroLocus_iff.mp hctx
@@ -369,33 +369,60 @@ theorem root_branch [Fact n.Prime] {ps} {p : Expr n} {i rs}
369369
refine ⟨ctx, ?_⟩
370370
rw [variety, ideal, MvPolynomial.zeroLocus_span]
371371
intro q hq
372-
have hq2 : q ∈ ps ++ [.X i + -.C (ctx i)] :=
372+
have hq2 : q ∈ ps ++ [.X i + .C (-ctx i)] :=
373373
List.mem_toFinset.mp hq
374374
rcases List.mem_append.mp hq2 with hq | hq
375375
· exact hctx' q (Ideal.subset_span (List.mem_toFinset.mpr hq))
376376
· rcases List.mem_singleton.mp hq with rfl
377377
simp
378378

379-
theorem exhaust_branch [Fact n.Prime] {ps} {is : List Nat}
380-
(hps : variety (ideal ps) ≠ ∅) (his : is ≠ [])
381-
: orN (is.map fun i => ∃ (v : ZMod n), variety (ideal (ps ++ [.X i + -.C v])) ≠ ∅) := by
379+
theorem exhaust_branch' [Fact n.Prime] {i} {ps}
380+
(hps : variety (ideal ps) ≠ ∅)
381+
: ∃ (v : ZMod n), variety (ideal (ps ++ [.X i + .C (-v)])) ≠ ∅ := by
382382
rcases Set.nonempty_iff_ne_empty.mpr hps with ⟨ctx, hctx⟩
383383
have hctx' : ∀ q ∈ ideal ps, MvPolynomial.aeval ctx q = 0 :=
384384
MvPolynomial.mem_zeroLocus_iff.mp hctx
385-
match is, his with
386-
| i :: is, _ =>
387-
simp only [List.map, orN_cons_append]
388-
refine Or.inl ⟨ctx i, ?_⟩
389-
apply Set.nonempty_iff_ne_empty.mp
390-
refine ⟨ctx, ?_⟩
391-
rw [variety, ideal, MvPolynomial.zeroLocus_span]
392-
intro q hq
393-
have hq2 : q ∈ ps ++ [.X i + -.C (ctx i)] :=
394-
List.mem_toFinset.mp hq
395-
rcases List.mem_append.mp hq2 with hq | hq
396-
· exact hctx' q (Ideal.subset_span (List.mem_toFinset.mpr hq))
397-
· rcases List.mem_singleton.mp hq with rfl
398-
simp
385+
refine ⟨ctx i, ?_⟩
386+
apply Set.nonempty_iff_ne_empty.mp
387+
refine ⟨ctx, ?_⟩
388+
rw [variety, ideal, MvPolynomial.zeroLocus_span]
389+
intro q hq
390+
have hq2 : q ∈ ps ++ [.X i + .C (-ctx i)] :=
391+
List.mem_toFinset.mp hq
392+
rcases List.mem_append.mp hq2 with hq | hq
393+
· exact hctx' q (Ideal.subset_span (List.mem_toFinset.mpr hq))
394+
· rcases List.mem_singleton.mp hq with rfl
395+
simp
396+
397+
theorem exhaust_branch [Fact n.Prime] {i} {ps}
398+
(hps : variety (ideal ps) ≠ ∅)
399+
: orN ((List.zmodRange n).map fun v => variety (ideal (ps ++ [.X i + .C (-v)])) ≠ ∅) := by
400+
obtain ⟨v, hv⟩ := exhaust_branch' (i := i) hps
401+
refine orN_map_of_mem (x := v) ?_ hv
402+
unfold List.zmodRange
403+
refine List.mem_flatMap.mpr ⟨v.val, List.mem_range.mpr (ZMod.val_lt v), ?_⟩
404+
simp [ZMod.natCast_zmod_val v]
405+
406+
-- TODO: remove the need for this theorem.
407+
theorem exhaust_branch'' [Fact n.Prime] {i} {ps}
408+
(hps : variety (ideal ps) ≠ ∅)
409+
: variety (ideal (ps ++ [.X i])) ≠ ∅ ∨
410+
orN ((List.zmodRange n).tail.map fun v => variety (ideal (ps ++ [.X i + .C (-v)])) ≠ ∅) := by
411+
have h := exhaust_branch (i := i) hps
412+
have hpos : 0 < n := (Fact.out : n.Prime).pos
413+
obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, (Nat.succ_pred_eq_of_pos hpos).symm⟩
414+
have hrange : List.zmodRange (m + 1) = (0 : ZMod (m + 1)) :: (List.zmodRange (m + 1)).tail := by
415+
have hu : List.zmodRange (m + 1) =
416+
(0 : ZMod (m + 1)) :: ((List.range m).map Nat.succ : List Nat) := by
417+
show (List.range (m + 1) : List (ZMod (m + 1))) = _
418+
rw [List.range_succ_eq_map]
419+
rfl
420+
rewrite [hu]
421+
rfl
422+
rw [hrange, List.map_cons, orN_cons_append] at h
423+
cases h with
424+
| inl h => left; simpa using h
425+
| inr h => exact Or.inr h
399426

400427
def Expr.isFieldPoly (e : Expr n) : Bool :=
401428
match e with
@@ -979,6 +1006,7 @@ open Qq
9791006
let hs : Q($s₁ = $s₂) ← reconstructProof pf.getChildren[1]!
9801007
addThm q((«$e₁».toPoly ∈ $s₁) = («$e₂».toPoly ∈ $s₂)) q(Expr.elem_congr $he $hs)
9811008
| .FF_POLY_CONVERSION =>
1009+
-- TODO: fix the signature of `FF_POLY_CONVERSION` (arg 1 should be an ideal according to docstring)
9821010
let ps := ((pf.getResult[0]!)[0]!)[0]!.getChildren
9831011
let o : Nat ← pure ps[0]!.getSort!.getFiniteFieldSize!
9841012
let ho : Q(Fact «$o».Prime) ← Meta.synthInstance q(Fact «$o».Prime)
@@ -1078,7 +1106,7 @@ open Qq
10781106
let reconstructZMods := fun (t : cvc5.Term) (acc : Q(List (ZMod $o))) => do
10791107
let p : Q(ZMod $o) ← reconstructTerm t
10801108
return q($p :: $acc)
1081-
let ps := (pf.getArguments[1]!).getChildren
1109+
let ps := pf.getArguments[1]!.getChildren
10821110
let ps ← ps.foldrM reconstructMVPs q([])
10831111
let p : Q(ZMod $o) ← reconstructTerm pf.getArguments[4]!
10841112
let p ← Expr.reify o p
@@ -1091,8 +1119,23 @@ open Qq
10911119
let hp : Q(«$p».toPoly ∈ ideal $ps) ← reconstructProof pf.getChildren[1]!
10921120
let tac := if ← useNative then nativeDecide else decide
10931121
let hpirs : Q(«$p».completeRoots $i $rs) ← tac q(«$p».completeRoots $i $rs)
1094-
addThm q(orN («$rs».map fun r => variety (ideal ($ps ++ [.X $i - .C r])) ≠ ∅))
1122+
addThm q(orN («$rs».map fun r => variety (ideal ($ps ++ [.X $i + .C (-r)])) ≠ ∅))
10951123
q(@root_branch $o $ho $ps $p $i $rs $hps $hp $hpirs)
1124+
| .FF_EXHAUST_BRANCH =>
1125+
let o : Nat := pf.getArguments[0]!.getSort!.getFiniteFieldSize!
1126+
let ho : Q(Fact «$o».Prime) ← Meta.synthInstance q(Fact «$o».Prime)
1127+
let reconstructMVPs := fun (t : cvc5.Term) (acc : Q(List (MvPolynomial Nat (ZMod $o)))) => do
1128+
let p : Q(ZMod $o) ← reconstructTerm t
1129+
let p ← MvPolynomialM.reify o p
1130+
return q($p :: $acc)
1131+
let is ← getFFCtx o
1132+
let x : Q(ZMod $o) ← reconstructTerm pf.getArguments[0]!
1133+
let i : Nat := is.findIdx (· == x)
1134+
let ps := pf.getArguments[1]!.getChildren
1135+
let ps ← ps.foldrM reconstructMVPs q([])
1136+
let hps : Q(variety (ideal $ps) ≠ ∅) ← reconstructProof pf.getChildren[0]!
1137+
addThm q(orN ((List.zmodRange $o).map fun v => variety (ideal ($ps ++ [.X $i + .C (-v)])) ≠ ∅))
1138+
q(@exhaust_branch'' $o $ho $i $ps $hps)
10961139
| _ => return none
10971140
where
10981141
decide (p : Q(Prop)) : MetaM (Q($p)) := do

Test/Unit/ZMod.lean

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,36 @@ open MvPolynomial Expr
1212
example (x: ZMod 3) : x* (x-1)* (x-2) ≠ 1 := by
1313
smt
1414

15-
-- example (a b : ZMod 3) : a*(a-1)*(a-2) + b*(b-1)*(b-2) ≠ 1 := by
16-
-- smt
15+
example (a b : ZMod 3) : a*(a-1)*(a-2) + b*(b-1)*(b-2) ≠ 1 := by
16+
smt
1717

1818
-- This ends up killing my editor instance.
19-
-- example [Fact (Nat.Prime 394357)] (x1 x2 x3 x4 x5 : ZMod 394357) :
20-
-- ¬ (x1 + x2 + x3 + x4 + x5 = 0 ∧
21-
-- x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x1 = 0 ∧
22-
-- x1*x2*x3 + x2*x3*x4 + x3*x4*x5 + x4*x5*x1 + x5*x1*x2 = 0 ∧
23-
-- x1*x2*x3*x4 + x2*x3*x4*x5 + x3*x4*x5*x1 + x4*x5*x1*x2 + x5*x1*x2*x3 = 0 ∧
24-
-- x1*x2*x3*x4*x5 = 1) := by
25-
-- smt
19+
-- set_option trace.smt true
20+
-- set_option trace.smt.solve true
21+
example [Fact (Nat.Prime 394357)] (x1 x2 x3 x4 x5 : ZMod 394357) :
22+
¬ (x1 + x2 + x3 + x4 + x5 = 0
23+
x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x1 = 0
24+
x1*x2*x3 + x2*x3*x4 + x3*x4*x5 + x4*x5*x1 + x5*x1*x2 = 0
25+
x1*x2*x3*x4 + x2*x3*x4*x5 + x3*x4*x5*x1 + x4*x5*x1*x2 + x5*x1*x2*x3 = 0
26+
x1*x2*x3*x4*x5 = 1) := by
27+
smt +trust
2628

2729
-- This also ends up killing my editor instance...
28-
-- example [Fact (Nat.Prime 7)] (x1 x2 x3 x4 x5 : ZMod 7) :
29-
-- ¬ (x1 + x2 + x3 + x4 + x5 = 0 ∧
30-
-- x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x1 = 0 ∧
31-
-- x1*x2*x3 + x2*x3*x4 + x3*x4*x5 + x4*x5*x1 + x5*x1*x2 = 0 ∧
32-
-- x1*x2*x3*x4 + x2*x3*x4*x5 + x3*x4*x5*x1 + x4*x5*x1*x2 + x5*x1*x2*x3 = 0 ∧
33-
-- x1*x2*x3*x4*x5 = 1) := by
34-
-- smt
35-
36-
-- Fails without +native
30+
-- set_option trace.smt true
31+
-- set_option trace.smt.solve true
32+
example [Fact (Nat.Prime 7)] (x1 x2 x3 x4 x5 : ZMod 7) :
33+
¬ (x1 + x2 + x3 + x4 + x5 = 0
34+
x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x1 = 0
35+
x1*x2*x3 + x2*x3*x4 + x3*x4*x5 + x4*x5*x1 + x5*x1*x2 = 0
36+
x1*x2*x3*x4 + x2*x3*x4*x5 + x3*x4*x5*x1 + x4*x5*x1*x2 + x5*x1*x2*x3 = 0
37+
x1*x2*x3*x4*x5 = 1) := by
38+
smt +trust
39+
3740
example [Fact (Nat.Prime 5)] (x y : ZMod 5) : ¬ (x * x = 1 ∧ y * y = 2) := by
3841
smt
3942

40-
-- Takes too long...
41-
set_option trace.smt true
42-
set_option trace.smt.reconstruct.proof true
43-
set_option trace.smt.solve true
44-
set_option pp.instantiateMVars false
4543
example [Fact (Nat.Prime 5)] (x y : ZMod 5) : ¬ ( y * y = 2 ∧ x * x = 1) := by
46-
-- smt
47-
sorry
44+
smt
4845

4946
example [Fact (Nat.Prime 5)] (x: ZMod 5) : x* (x-1)* (x-2) ≠ 1 := by
5047
smt +model

0 commit comments

Comments
 (0)