@@ -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
3638namespace Smt.Reconstruct.ZMod
3739
38-
39-
4040open Lean Expr
4141open Qq
4242open Translator Term
@@ -350,7 +350,7 @@ theorem roots_complete [Fact n.Prime] {p : Expr n}
350350theorem 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
400427def 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
10971140where
10981141 decide (p : Q(Prop )) : MetaM (Q($p)) := do
0 commit comments