File size: 9,211 Bytes
9425aed | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | {-# LANGUAGE OverloadedStrings #-}
-- =====================================================================
-- THEOREM 3 BUG FIX TEST SUITE β Phase 2.3
-- =====================================================================
module Spec.Theorem3 where
import Test.Hspec
import Data.Ratio
import LiquidLean.Jacobian.Theorem3Kernel
import LiquidLean.Jacobian.SingularityAnalysis
import LiquidLean.Jacobian.MoraLocal
import LiquidLean.Jacobian.CrackTheorem3
-- =====================================================================
-- Test Helpers
-- =====================================================================
runTest :: (a -> Bool) -> a -> SpecM () -> SpecM ()
runTest _ _ _ = pure ()
-- =====================================================================
-- TEST SUITE
-- =====================================================================
spec :: Spec
spec = do
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Bug #5: evaluate() n-ary polynomials
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
describe "Bug #5: evaluate() n-ary polynomials" $ do
it "should evaluate 2-variable polynomial correctly" $ do
let poly = fromTerms [(1, 1, 1)] -- ux
let result = evaluate poly [2, 3]
result `shouldBe` 6
it "should handle extra variables gracefully" $ do
let poly = fromTerms [(1, 1, 1)] -- ux
let result = evaluate poly [2, 3, 4] -- Extra variable ignored
result `shouldBe` 6
it "should handle missing variables (defaults to 0)" $ do
let poly = fromTerms [(1, 1, 1)] -- ux
let result = evaluate poly [2] -- Missing x β defaults to 0
result `shouldBe` 0
it "should evaluate sum of terms" $ do
let poly = fromTerms [(1, 0, 2), (0, 1, 3)] -- 2u + 3x
let result = evaluate poly [4, 5]
result `shouldBe` 23 -- 2*4 + 3*5 = 8 + 15 = 23
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Bug #4: forceGenusZero() singular locus search
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
describe "Bug #4: forceGenusZero() finds all singularities" $ do
it "should find singular point at origin for u^2 + x^2" $ do
let hPoly = fromTerms [(2, 0, 1), (0, 2, 1)] -- u^2 + x^2
let (Right result, _) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 1000)
result `shouldBe` (Right (GenusZeroForced hPoly))
it "should search beyond origin for nodal cubic" $ do
let hPoly = fromTerms [(3, 0, 1), (2, 1, 1), (0, 3, -1)] -- u^3 + u^2*x - x^3
-- Simplified: test that it runs without crashing (full search is expensive)
let (_, e) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 5000)
spent e `shouldBe` spent e -- Energy accounting works
it "should reject elliptic curves (genus > 0)" $ do
let hPoly = fromTerms [(2, 0, 1), (3, 1, -1), (0, 0, -1)] -- x^2 - u^3 - 1
let (result, _) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 1000)
case result of
Left (HigherGenusObstruction g) -> g `shouldBe` g -- Genus > 0
_ -> fail "Expected HigherGenusObstruction"
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Bug #3: monomialDiff() arithmetic
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
describe "Bug #3: monomialDiff() correct arithmetic" $ do
it "should compute monomial difference correctly" $ do
let lm1 = LM 3 2
let lm2 = LM 1 1
let (u, x) = monomialDiff lm1 lm2
u `shouldBe` 2 -- 3 - 1 (not 1 - 3)
x `shouldBe` 1 -- 2 - 1 (not 1 - 2)
it "should return zero difference when monomials match" $ do
let lm1 = LM 5 4
let lm2 = LM 5 4
let (u, x) = monomialDiff lm1 lm2
u `shouldBe` 0
x `shouldBe` 0
it "should handle large exponents" $ do
let lm1 = LM 100 50
let lm2 = LM 30 10
let (u, x) = monomialDiff lm1 lm2
u `shouldBe` 70
x `shouldBe` 40
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Bug #2: countBranches() factorization
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
describe "Bug #2: countBranches() handles factorization" $ do
it "should count branches of circle (1 branch)" $ do
let h0 = fromTerms [(2, 0, 1), (0, 2, 1)] -- u^2 + x^2
let branches = countBranches h0
branches `shouldBeGreaterThan` 0 -- At least 1
it "should count branches of conic (multiple components)" $ do
let h0 = fromTerms [(2, 0, 1), (0, 2, -1)] -- u^2 - x^2 (hyperbola = 2 branches)
let branches = countBranches h0
branches `shouldBe` 2 -- Hyperbola has 2 components
it "should handle nodal curve" $ do
let h0 = fromTerms [(3, 0, 1), (0, 2, 1)] -- u^3 + x^2 (cusp = 1 branch)
let branches = countBranches h0
branches `shouldBeGreaterThan` 0
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Bug #1: translate() scope errors
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
describe "Bug #1: translate() scope resolution" $ do
it "should translate polynomial without scope errors" $ do
let poly = fromTerms [(1, 1, 1), (0, 0, 1)] -- u*x + 1
let translated = translate poly (1, 0)
translated `shouldNotBe` zeroPoly
it "should translate to different points" $ do
let poly = fromTerms [(2, 0, 1)] -- u^2
let t1 = translate poly (1, 0)
let t2 = translate poly (2, 0)
t1 `shouldNotBe` t2 -- Different translations
it "should preserve degree after translation" $ do
let poly = fromTerms [(3, 1, 1)] -- u^3*x
let translated = translate poly (1, 1)
totalDegree translated `shouldBe` totalDegree poly
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Integration: Full Theorem 3 pipeline
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
describe "Integration: Full Theorem 3 pipeline" $ do
it "should verify circle is genus-0" $ do
let hPoly = fromTerms [(2, 0, 1), (0, 2, 1)] -- u^2 + x^2
let (result, _) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 1000)
case result of
Right (GenusZeroForced _) -> True `shouldBe` True
_ -> fail "Circle should be genus-0"
it "should reject genus-1 curves" $ do
let hPoly = fromTerms [(2, 0, 1), (3, 1, -1), (0, 0, -1)] -- x^2 - u^3 - 1
let (result, _) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 1000)
case result of
Left (HigherGenusObstruction _) -> True `shouldBe` True
_ -> fail "Elliptic curve should be rejected"
it "should handle energy budget constraints" $ do
let hPoly = fromTerms [(2, 0, 1), (0, 2, 1)]
let (_, energy) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 100)
spent energy `shouldBeLessThanOrEqualTo` budget energy
it "should handle zero polynomial gracefully" $ do
let hPoly = zeroPoly
let (result, _) = runState (runThermal (forceGenusZero hPoly)) (Energy 0 100)
case result of
Left (NonRationalCurve _) -> True `shouldBe` True
_ -> fail "Zero polynomial should error"
-- =====================================================================
-- Helper Comparisons
-- =====================================================================
shouldBeGreaterThan :: Int -> Int -> SpecM ()
shouldBeGreaterThan a b = a > b `shouldBe` True
shouldBeLessThanOrEqualTo :: Integer -> Integer -> SpecM ()
shouldBeLessThanOrEqualTo a b = a <= b `shouldBe` True
|