module ToySolver.Data.AlgebraicNumber.Complex
(
AComplex((:+))
, realPart
, imagPart
, magnitude
, minimalPolynomial
, conjugate
) where
import Control.Monad
import qualified Data.Sign as Sign
import qualified Data.Map as Map
import Data.Maybe
import qualified ToySolver.CAD as CAD
import qualified ToySolver.Data.AlgebraicNumber.Real as AReal
import ToySolver.Data.AlgebraicNumber.Real (AReal)
import qualified ToySolver.Data.AlgebraicNumber.Root as Root
import qualified ToySolver.Data.Polynomial as P
import ToySolver.Data.Polynomial (Polynomial, UPolynomial, X (..))
infix 6 :+
data AComplex = !AReal :+ !AReal
deriving (Eq, Show)
realPart :: AComplex -> AReal
realPart (x :+ _) = x
imagPart :: AComplex -> AReal
imagPart (_ :+ y) = y
conjugate :: AComplex -> AComplex
conjugate (x :+ y) = x :+ (y)
magnitude :: AComplex -> AReal
magnitude (x :+ y) = AReal.nthRoot 2 (x*x + y*y)
instance Num AComplex where
(x:+y) + (x':+y') = (x+x') :+ (y+y')
(x:+y) (x':+y') = (xx') :+ (yy')
(x:+y) * (x':+y') = (x*x'y*y') :+ (x*y'+y*x')
negate (x:+y) = negate x :+ negate y
abs z = magnitude z :+ 0
signum (0:+0) = 0
signum z@(x:+y) = x/r :+ y/r where r = magnitude z
fromInteger n = fromInteger n :+ 0
instance Fractional AComplex where
(x:+y) / (x':+y') = (x*x'+y*y') / d :+ (y*x'x*y') / d
where d = x'*x' + y'*y'
fromRational a = fromRational a :+ 0
minimalPolynomial :: AComplex -> UPolynomial Rational
minimalPolynomial z@(x :+ y) =
head [q | (q,_) <- P.factor p, P.deg q > 0, P.eval (\X -> z) (P.mapCoeff fromRational q) == 0]
where
p = Root.findPoly (P.var a + P.var b * P.var i) ps
where
a, b, i :: Int
i = 0
a = 1
b = 2
ps =
[ (P.var i) ^ 2 + 1
, P.subst (AReal.minimalPolynomial x) (\X -> P.var a)
, P.subst (AReal.minimalPolynomial y) (\X -> P.var b)
]
roots :: UPolynomial Rational -> [AComplex]
roots f = do
let cs1 = [ (u, [Sign.Zero]), (v, [Sign.Zero]) ]
(cs2, cells2) <- CAD.project [(P.toUPolynomialOf p 0, ss) | (p,ss) <- cs1]
let tmp2 = CAD.project [(P.toUPolynomialOf p 1, ss) | (p,ss) <- cs2]
(cs3, cells3) <- tmp2
guard $ and [Sign.signOf v `elem` ss | (p,ss) <- cs3, let v = P.eval (\_ -> undefined) p]
let m3 = Map.empty
yval <- catMaybes [CAD.findSample m3 cell | cell <- cells3]
let m2 = Map.insert 1 yval m3
xval <- catMaybes [CAD.findSample m2 cell | cell <- cells2]
return $ xval :+ yval
where
f1 :: P.Polynomial Rational Int
f1 = P.subst f (\X -> P.var 0 + P.var 1 * P.var 2)
f2 = P.toUPolynomialOf (P.reduce P.grevlex f1 [P.var 2 * P.var 2 + 1]) 2
u = P.coeff P.mone f2
v = P.coeff (P.var X) f2
test1 = minimalPolynomial (sqrt2 :+ sqrt3)
where
sqrt2 = AReal.nthRoot 2 2
sqrt3 = AReal.nthRoot 2 3
test2 = magnitude (sqrt2 :+ sqrt3)
where
sqrt2 = AReal.nthRoot 2 2
sqrt3 = AReal.nthRoot 2 3
test3 = roots p
where
x = P.var X
p = x 2
test4 = roots p
where
x = P.var X
p = x^2 2
test5 = roots p
where
x = P.var X
p = x^3 1
test6 = roots p
where
x = P.var X
p = x^4 + 2*x^2 + 25