Skip to content

Commit 5573c25

Browse files
committed
custom tactic
1 parent 527b26e commit 5573c25

1 file changed

Lines changed: 124 additions & 38 deletions

File tree

GridCircuit/Basic.lean

Lines changed: 124 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@ In this file we formalize the answer and related results to [xkcd's "nerd snipin
1515
1616
Here we state the problem in a more general form in aribtrary dimensions: On the $n$-dimensional
1717
grid where each neighboring nodes are connected by an one-ohm resistor, what is the equivalent
18-
resistance between the two marked nodes?
18+
resistance between the two specified nodes?
1919
2020
This file formalizes the following result
21-
* The translation to a formal mathematical problem and proof of the unique solution (if exists).
22-
* The general formula in arbitrary dimensions and for any pair of specific nodes.
23-
* Computation for the solution in the two-dimension case, and the answer to the original question.
21+
* `equivResistance`: formal mathematical model of the problem.
22+
* `equivResistance_eq`: proof of the unique solution (if exists).
23+
* `equivResistance_formula`: The general formula in arbitrary dimensions and for any pair of nodes.
24+
* `computeφ`: explicit computation for the solution in the two-dimension case.
25+
* `equivResistance_2_1`: the answer to the question in xkcd.
26+
2427
2528
Hopefully this can protect me from a car accident.
2629
-/
@@ -1463,6 +1466,13 @@ theorem equivResistance_eq_two_mul_φ [NeZero n] (x : Fin n → ℤ) :
14631466
rw [equivResistance_eq (isValidCircuit_φ 0 x)]
14641467
simp [two_mul]
14651468

1469+
/-- We can also write out the full formula for the equivalent resistance. -/
1470+
theorem equivResistance_formula [NeZero n] (x : Fin n → ℤ) :
1471+
equivResistance x =
1472+
some (2 * (2 * π)⁻¹ ^ n * ∫ (w : Fin n → ℝ) in Set.Icc (fun _ ↦ -π) (fun _ ↦ π),
1473+
(1 - Real.cos (∑ i, x i * w i)) / ∑ i, (2 - 2 * Real.cos (w i))) := by
1474+
rw [equivResistance_eq_two_mul_φ, φ, ← mul_assoc]
1475+
14661476
/-- Applying this to the neighbor of the center, we get that the equivalent resistance between
14671477
two neighboring points is $1 / n$. -/
14681478
theorem equivResistance_off_center [NeZero n] (e : Fin n) :
@@ -2490,40 +2500,116 @@ theorem computeφ_eq (x y : ℕ) :
24902500
exact φ_swap y x
24912501
· simp only [computeφ, h, ↓reduceDIte, (getφTable (x + 1)).eq_φ]
24922502

2503+
theorem equivResistance_eq_of_computeφ (x y : ℕ) (a b : ℚ) (h : computeφ x y = (a / 2, b / 2)) :
2504+
equivResistance ![ofNat(x), ofNat(y)] = some (a * π⁻¹ + b) := by
2505+
change equivResistance ![x, y] = some (a * π⁻¹ + b)
2506+
rw [equivResistance_eq_two_mul_φ, ← computeφ_eq, h]
2507+
simp
2508+
ring
2509+
2510+
open Lean Qq in
2511+
meta def realToRatExpr (e : Q(ℝ)) : MetaM (TSyntax `term) := do
2512+
match e with
2513+
| ~q(OfNat.ofNat $n (self := _)) =>
2514+
let some n := n.rawNatLit? | throwError "{n} is not a natural number"
2515+
.pure <| quote n
2516+
| ~q(OfNat.ofNat $m (self := _) / OfNat.ofNat $n (self := _)) =>
2517+
let some m := m.rawNatLit? | throwError "{m} is not a natural number"
2518+
let some n := n.rawNatLit? | throwError "{n} is not a natural number"
2519+
`($(quote m) / $(quote n))
2520+
| _ => throwError "Unsupported expression {e}"
2521+
2522+
open Lean Lean.Elab.Tactic Qq in
2523+
elab "comput_resistance" : tactic =>
2524+
withMainContext do
2525+
let e ← getMainTarget
2526+
let ⟨u, α, e⟩ ← inferTypeQ e
2527+
match u, α, e with
2528+
| 1, ~q(Prop), ~q(equivResistance ![ofNat($x), ofNat($y)] = some ($rhs)) =>
2529+
let some x := x.rawNatLit? | throwError "{x} is not a natural number"
2530+
let some y := y.rawNatLit? | throwError "{y} is not a natural number"
2531+
let x : TSyntax `term := quote x
2532+
let y : TSyntax `term := quote y
2533+
let (a, b) : TSyntax `term × TSyntax `term ← match rhs with
2534+
| ~q($a * π⁻¹ + $b) =>
2535+
let a ← realToRatExpr a
2536+
let b ← realToRatExpr b
2537+
.pure (a, b)
2538+
| ~q($a * π⁻¹ - $b) =>
2539+
let a ← realToRatExpr a
2540+
let b ← realToRatExpr b
2541+
let nb ← `(-$b)
2542+
.pure (a, nb)
2543+
| ~q($b - $a * π⁻¹) =>
2544+
let a ← realToRatExpr a
2545+
let b ← realToRatExpr b
2546+
let na ← `(-$a)
2547+
.pure (na, b)
2548+
| ~q($a * π⁻¹) =>
2549+
let a ← realToRatExpr a
2550+
.pure (a, quote 0)
2551+
| ~q($a) =>
2552+
let a ← realToRatExpr a
2553+
.pure (quote 0, a)
2554+
| _ => throwError "Unsupported expression"
2555+
evalTactic (← `(tactic| rw [equivResistance_eq_of_computeφ $x $y $a $b ?_]))
2556+
evalTactic (← `(tactic| · congrm some ?_; ring))
2557+
evalTactic (← `(tactic| · decide +kernel))
2558+
| _, _, _ => throwError "Unsupported expression"
2559+
24932560
/-! Now we can verify the value of `φ` at any point in the first quadrant with just kernel
24942561
reduction. -/
24952562

2496-
theorem φ_2d_1_1 : φ ![1, 1] = π⁻¹ := by
2497-
suffices computeφ 1 1 = (1, 0) by
2498-
simpa [this] using (computeφ_eq 1 1).symm
2499-
decide
2500-
2501-
theorem φ_2d_2_2 : φ ![2, 2] = (4 / 3) * π⁻¹ := by
2502-
suffices computeφ 2 2 = (4 / 3, 0) by
2503-
simpa [this] using (computeφ_eq 2 2).symm
2504-
decide +kernel
2505-
2506-
theorem φ_2d_3_3 : φ ![3, 3] = (23 / 15) * π⁻¹ := by
2507-
suffices computeφ 3 3 = (23 / 15, 0) by
2508-
simpa [this] using (computeφ_eq 3 3).symm
2509-
decide +kernel
2510-
2511-
theorem φ_2d_2_1 : φ ![2, 1] = 2 * π⁻¹ - 4⁻¹ := by
2512-
suffices computeφ 2 1 = (2, -4⁻¹) by
2513-
simpa [this, ← sub_eq_add_neg] using (computeφ_eq 2 1).symm
2514-
decide +kernel
2515-
2516-
theorem φ_2d_42_7 : φ ![42, 7] =
2517-
76593647770027443784355182739895062090786294026 / 200507537800595025 * π⁻¹ -
2518-
486376034966331052956526218433 / 4 := by
2519-
suffices computeφ 42 7 =
2520-
(76593647770027443784355182739895062090786294026 / 200507537800595025,
2521-
-486376034966331052956526218433 / 4) by
2522-
simpa [this, ← sub_eq_add_neg, neg_div] using (computeφ_eq 42 7).symm
2523-
decide +kernel
2524-
2525-
/-! Finally, let's answer the original question: the equivalent resistance is $4/\pi - 1/2$ -/
2526-
2527-
theorem equivResistance_2_1 : equivResistance ![2, 1] = some (4 * π⁻¹ - 2⁻¹) := by
2528-
rw [equivResistance_eq_two_mul_φ, φ_2d_2_1]
2529-
congrm some $(by ring)
2563+
theorem equivResistance_0_0 : equivResistance ![0, 0] = some (0) := by
2564+
comput_resistance
2565+
2566+
theorem equivResistance_1_0 : equivResistance ![1, 0] = some (1 / 2) := by
2567+
comput_resistance
2568+
2569+
theorem equivResistance_1_1 : equivResistance ![1, 1] = some (2 * π⁻¹) := by
2570+
comput_resistance
2571+
2572+
theorem equivResistance_2_0 : equivResistance ![2, 0] = some (2 - 4 * π⁻¹) := by
2573+
comput_resistance
2574+
2575+
/-- ✅ This is the answer of the original question: the equivalent resistance is $4 / \pi - 1 / 2$.
2576+
-/
2577+
theorem equivResistance_2_1 : equivResistance ![2, 1] = some (4 * π⁻¹ - 1 / 2) := by
2578+
comput_resistance
2579+
2580+
theorem equivResistance_2_2 : equivResistance ![2, 2] = some (8 / 3 * π⁻¹) := by
2581+
comput_resistance
2582+
2583+
theorem equivResistance_3_0 : equivResistance ![3, 0] = some (17 / 2 - 24 * π⁻¹) := by
2584+
comput_resistance
2585+
2586+
theorem equivResistance_3_1 : equivResistance ![3, 1] = some (46 / 3 * π⁻¹ - 4) := by
2587+
comput_resistance
2588+
2589+
theorem equivResistance_3_2 : equivResistance ![3, 2] = some (4 / 3 * π⁻¹ + 1 / 2) := by
2590+
comput_resistance
2591+
2592+
theorem equivResistance_3_3 : equivResistance ![3, 3] = some (46 / 15 * π⁻¹) := by
2593+
comput_resistance
2594+
2595+
theorem equivResistance_4_0 : equivResistance ![4, 0] = some (40 - 368 / 3 * π⁻¹) := by
2596+
comput_resistance
2597+
2598+
theorem equivResistance_4_1 : equivResistance ![4, 1] = some (80 * π⁻¹ - 49 / 2) := by
2599+
comput_resistance
2600+
2601+
theorem equivResistance_4_2 : equivResistance ![4, 2] = some (6 - 236 / 15 * π⁻¹) := by
2602+
comput_resistance
2603+
2604+
theorem equivResistance_4_3 : equivResistance ![4, 3] = some (24 / 5 * π⁻¹ - 1 / 2) := by
2605+
comput_resistance
2606+
2607+
theorem equivResistance_4_4 : equivResistance ![4, 4] = some (352 / 105 * π⁻¹) := by
2608+
comput_resistance
2609+
2610+
/-- As a show case, the result can go really complicated for points far away. -/
2611+
theorem equivResistance_42_7 :
2612+
equivResistance ![42, 7] =
2613+
some (153187295540054887568710365479790124181572588052 / 200507537800595025 * π⁻¹ -
2614+
486376034966331052956526218433 / 2) := by
2615+
comput_resistance

0 commit comments

Comments
 (0)