For the application in business of imaginary values have already given a premium . Now it's interesting to have something with duals .
. For our generalization, the matrix is transformed into a two-diagonal one, but with further operations it will turn into a triangular one. The coefficients over the second diagonal carry information about the interaction of parameters - in some tasks this may be important information, but for now we will ignore it.data GDual nv = !n :+- (vn) Its parameters are the type of representation of the original field and the parameterized container for representing the vector ε. It is implicitly assumed that the container represents the Additive type class from the linear package. instance (Eq n, Num n, Additive v) => Num (GDual nv) where fromInteger x = (fromInteger x) :+- zero (x1 :+- y1) + (x2 :+- y2) = (x1 + x2) :+- (y1 ^+^ y2) (x1 :+- y1) - (x2 :+- y2) = (x1 - x2) :+- (y1 ^-^ y2) (x1 :+- y1) * (x2 :+- y2) = (x1 * x2) :+- ((y1 ^* x2) ^+^ (x1 *^ y2)) negate (x :+- y) = (negate x) :+- (y ^* (-1)) abs (a@(x :+- y)) = case (signum x) of 0 -> 0 :+- fmap abs y z -> ((z * x) :+- (x *^ y)) signum (x :+- y) = case (signum x) of 0 -> 0 :+- fmap signum y z -> z :+- zero For abs and signum in the neighborhood of zero ( 0: + - ... ), the ratio stated in the type class is violated abs x * signum x == x But at other points it is preserved. instance (Num (GDual nv), Fractional n, Additive v) => Fractional (GDual nv) where (x1 :+- y1) / (x2 :+- y2) = (x1 / x2) :+- ((y1 ^/ x2) ^-^ ((x1 / (x2 * x2)) *^ y2)) recip (x :+- y) = (recip x) :+- (y ^/ (x * x)) fromRational x = (fromRational x) :+- zero The division is not quite full - it does not know how to divide numbers from the neighborhood of zero even when it is possible (the Additive type class does not provide the necessary functionality for this). But in my field of application of such a division should not be - in the calculations in ordinary numbers in this case happens the division of 0/0. Math.GDual.Demo.SimpleSparseSolver.solve :: (Fractional t1, Ord t, Epsilon t1) => [[(t, t1)]] -> [[(t, t1)]] solves a system of linear equations, which is represented by a rectangular sparse matrix. The matrix is a concatenation of the matrix of coefficients and the column of the right side. solve elementary operations leads the matrix to the unit - the right side turns into an answer. Prelude> :load Math.GDual.Demo.SimpleSparseSolver [1 of 1] Compiling Math.GDual.Demo.SimpleSparseSolver ( Math/GDual/Demo/SimpleSparseSolver.hs, interpreted ) Ok, modules loaded: Math.GDual.Demo.SimpleSparseSolver. *Math.GDual.Demo.SimpleSparseSolver> :load Math.GDual Ok, modules loaded: Math.GDual. Prelude Math.GDual> :add Math.GDual.Demo.SimpleSparseSolver [2 of 2] Compiling Math.GDual.Demo.SimpleSparseSolver ( Math/GDual/Demo/SimpleSparseSolver.hs, interpreted ) Ok, modules loaded: Math.GDual.Demo.SimpleSparseSolver, Math.GDual. *Math.GDual.Demo.SimpleSparseSolver> import Math.GDual *Math.GDual.Demo.SimpleSparseSolver Math.GDual> solve [[(0,1 :+- [1,0,0,0]),(1,2 :+- [0,1,0,0]),(2,3)],[(0,1 :+- [0,0,1,0]),(1,1 :+- [0,0,0,1]),(2,1)]] Loading package array-0.4.0.1 ... linking ... done. .... Loading package linear-1.10.1.1 ... linking ... done. [[(2,-1.0+ε[-1.0,2.0,2.0,-4.0])],[(2,2.0+ε[1.0,-2.0,-1.0,2.0])]] *Math.GDual.Demo.SimpleSparseSolver Math.GDual> import Linear *Math.GDual.Demo.SimpleSparseSolver Math.GDual Linear> inv22 $ V2 (V2 (1 :+- [1,0,0,0]) (2 :+- [0,1,0,0])) (V2 (1 :+- [0,0,1,0]) (1 :+- [0,0,0,1])) Just (V2 (V2 -1.0+ε[-1.0,1.0,2.0,-2.0] 2.0+ε[2.0,-1.0,-4.0,2.0]) (V2 1.0+ε[1.0,-1.0,-1.0,1.0] -1.0+ε[-2.0,1.0,2.0,-1.0])) Source: https://habr.com/ru/post/222789/
All Articles