From b1df0d04e662b2b4d59c53ced59d872f996d71b9 Mon Sep 17 00:00:00 2001 From: sheaf Date: Mon, 22 Apr 2024 01:52:29 +0200 Subject: [PATCH] Always run Gauss-Seidel at tiny sizes to rule out fake solutions --- brush-strokes/src/lib/Math/Root/Isolation.hs | 37 ++++++++++---------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/brush-strokes/src/lib/Math/Root/Isolation.hs b/brush-strokes/src/lib/Math/Root/Isolation.hs index 13e9114..57a3a9a 100644 --- a/brush-strokes/src/lib/Math/Root/Isolation.hs +++ b/brush-strokes/src/lib/Math/Root/Isolation.hs @@ -250,26 +250,27 @@ defaultRootIsolationAlgorithms :: forall n d . BoxCt n d => Double -> Double -> Box n -> BoxHistory n -> Either String ( NE.NonEmpty ( RootIsolationAlgorithm n d ) ) -defaultRootIsolationAlgorithms minWidth ε_eq box history - -- All the box widths are lower than the minimum width: give up. - | and $ ( \ cd -> width cd <= minWidth ) <$> coordinates box - = Left $ "widths <= " ++ show minWidth - | otherwise - = Right $ case history of - lastRoundBoxes : _ - -- If, in the last round of strategies, we didn't try bisection... - | any ( \case { BisectionStep {} -> False; _ -> True } . fst ) lastRoundBoxes - , ( _step, lastRoundFirstBox ) <- NE.last lastRoundBoxes - -- ...and the last round didn't sufficiently reduce the size of the box... - , not $ box `sufficientlySmallerThan` lastRoundFirstBox - -- ...then try bisecting the box. - -> NE.singleton $ Bisection ( defaultBisectionOptions minWidth ε_eq box ) - -- Otherwise, do a normal round. - -- Currently: we try an interval Gauss–Seidel step followed by box(1)-consistency. - _ -> GaussSeidel _gaussSeidelOptions - NE.:| [ Box1 _box1Options ] +defaultRootIsolationAlgorithms minWidth ε_eq box history = + case history of + lastRoundBoxes : _ + -- If, in the last round of strategies, we didn't try bisection... + | any ( \case { BisectionStep {} -> False; _ -> True } . fst ) lastRoundBoxes + , ( _step, lastRoundFirstBox ) <- NE.last lastRoundBoxes + -- ...and the last round didn't sufficiently reduce the size of the box... + , not $ box `sufficientlySmallerThan` lastRoundFirstBox + -- ...then try bisecting the box... + -- ...unless the box is already too small, in which case we give up. + -> if verySmall + then Left $ "widths <= " ++ show minWidth + else Right $ NE.singleton $ Bisection ( defaultBisectionOptions minWidth ε_eq box ) + -- Otherwise, do a normal round. + -- Currently: we try an interval Gauss–Seidel step followed by box(1)-consistency. + _ -> Right $ GaussSeidel _gaussSeidelOptions + NE.:| [ Box1 _box1Options | not verySmall ] where + verySmall = and $ ( \ cd -> width cd <= minWidth ) <$> coordinates box + _box1Options :: Box1Options n d _box1Options = Box1Options