-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Equation solver and calculator à la metafont
--
-- An equation solver and calculator in the spirit of Metafont.
--
-- Like metafont, it can solve linear equations, and evaluate nonlinear
-- expressions. In addition to metafont, it also solves for angles, and
-- makes the solution independend of the order of the equations.
@package mfsolve
@version 0.3.2.2
-- | This module implements an equation solver that solves and evaluates
-- expressions on the fly. It is based on Prof. D.E.Knuth's
-- metafont. The goal of mfsolve is to make the solver useful in
-- an interactive program, by enhancing the bidirectionality of the
-- solver. Like metafont, it can solve linear equations, and evaluate
-- nonlinear expressions. In addition to metafont, it also solves for
-- angles, and makes the solution independend of the order of the
-- equations.
--
-- The Expr datatype allows for calculations with constants and
-- unknown variables. The Dependencies datatype contains all
-- dependencies and known equations.
--
--
Examples:
--
-- Let's define some variables. The SimpleVar type is a simple
-- wrapper around String to provide nice output, since the Show
-- instance for String outputs quotation marks.
--
--
-- let [x, y, t, a] = map (makeVariable . SimpleVar) ["x", "y", "t", "a"]
--
--
-- Solve linear equations:
--
--
-- showVars $ flip execSolver noDeps $ do
-- 2*x + y === 5
-- x - y === 1
--
--
--
-- x = 2.0
-- y = 1.0
--
--
-- Solve for angle (pi/4):
--
--
-- showVars $ flip execSolver noDeps $ sin(t) === 1/sqrt(2)
--
--
--
-- t = 0.7853981633974484
--
--
-- Solve for angle (pi/3) and amplitude:
--
--
-- showVars $ flip execSolver noDeps $ do
-- a*sin(x) === sqrt 3
-- a*cos(x) === 1
--
--
--
-- x = 1.0471975511965979
-- a = 2.0
--
--
-- Allow nonlinear expression with unknown variables:
--
--
-- showVars $ flip execSolver noDeps $ do
-- sin(sqrt(x)) === y
-- x === 2
--
--
--
-- x = 2.0
-- y = 0.9877659459927355
--
--
-- Find the angle and amplitude when using a rotation matrix:
--
--
-- showVars $ flip execSolver noDeps $ do
-- a*cos t*x - a*sin t*y === 30
-- a*sin t*x + a*cos t*y === 40
-- x === 10
-- y === 10
--
--
--
-- x = 10.0
-- y = 10.0
-- t = 0.14189705460416402
-- a = 3.5355339059327373
--
module Math.MFSolve
-- | A simplified datatype representing an expression. This can be used to
-- inspect the structure of a Expr, which is hidden.
data SimpleExpr v n
SEBin :: BinaryOp -> SimpleExpr v n -> SimpleExpr v n -> SimpleExpr v n
SEUn :: UnaryOp -> SimpleExpr v n -> SimpleExpr v n
Var :: v -> SimpleExpr v n
Const :: n -> SimpleExpr v n
-- | A mathematical expression of several variables. Several Numeric
-- instances (Num, Floating and Fractional) are
-- provided, so doing calculations over Expr is more convenient.
data Expr v n
-- | A linear expression of several variables. For example: 2*a + 3*b +
-- 2 would be represented as LinExpr 2 [(a, 2), (b, 3)].
data LinExpr v n
LinExpr :: n -> [(v, n)] -> LinExpr v n
data UnaryOp
-- | sine
Sin :: UnaryOp
-- | cosine
Cos :: UnaryOp
-- | absolute value
Abs :: UnaryOp
-- | reciprocal (1/x)
Recip :: UnaryOp
-- | sign
Signum :: UnaryOp
-- | natural exponential (e^x)
Exp :: UnaryOp
-- | natural logarithm (log x)
Log :: UnaryOp
-- | hyperbolic cosine
Cosh :: UnaryOp
-- | inverse hyperbolic tangent
Atanh :: UnaryOp
-- | tangent
Tan :: UnaryOp
-- | hyperbolic tangent
Tanh :: UnaryOp
-- | hyperbolic sine
Sinh :: UnaryOp
-- | inverse sine
Asin :: UnaryOp
-- | inverse cosine
Acos :: UnaryOp
-- | inverse hyperbolic sine
Asinh :: UnaryOp
-- | inverse hyperbolic cosine
Acosh :: UnaryOp
-- | inverse tangent
Atan :: UnaryOp
data BinaryOp
-- | Addition
Add :: BinaryOp
-- | Multiplication
Mul :: BinaryOp
newtype SimpleVar
SimpleVar :: String -> SimpleVar
-- | Create an expression from a variable
makeVariable :: Num n => v -> Expr v n
-- | Create an expression from a constant
makeConstant :: n -> Expr v n
-- | Evaluate the expression given a variable substitution.
evalExpr :: Floating n => (v -> n) -> SimpleExpr v n -> n
-- | Make a expression from a simple expression.
fromSimple :: (Floating n, Ord n, Ord v) => SimpleExpr v n -> Expr v n
-- | Convert an Expr to a SimpleExpr.
toSimple :: (Num n, Eq n) => Expr v n -> SimpleExpr v n
-- | evaluate a simple expression using the given substitution.
evalSimple :: Floating m => (n -> m) -> (v -> m) -> SimpleExpr v n -> m
-- | The expression contains the given variable.
hasVar :: (Num t, Eq v, Eq t) => v -> Expr v t -> Bool
-- | map a simple expression using the given substitution.
mapSimple :: (Floating m, Floating n) => (n -> m) -> (v -> u) -> SimpleExpr v n -> SimpleExpr u m
-- | map an expression using the given substitution.
mapExpr :: (Floating m, Floating n, Ord u, Ord v, Eq n, Ord m) => (n -> m) -> (v -> u) -> Expr v n -> Expr u m
-- | This hidden datatype represents a system of equations. It contains
-- linear dependencies on variables as well as nonlinear equations. The
-- following terminology is used from metafont:
--
--
-- - known variable: A variable who's dependency is just a
-- number.
-- - dependend variable: A variable which depends linearly on
-- other variables.
-- - independend variable: any other variable.
--
--
-- A dependend variable can only depend on other
-- independend variables. Nonlinear equations will be simplified
-- by substituting and evaluating known variables, or by reducing some
-- trigonometric equations to linear equations.
data Dependencies v n
-- | An error type for ===, =&= and addEquation:
data DepError v n
-- | The variable is not defined.
UndefinedVar :: v -> DepError v n
-- | The variable is defined but dependend an other variables.
UnknownVar :: v -> n -> DepError v n
-- | The equation was reduced to the impossible equation `a == 0` for
-- nonzero a, which means the equation is inconsistent with previous
-- equations.
InconsistentEq :: n -> Expr v n -> DepError v n
-- | The equation was reduced to the redundant equation `0 == 0`, which
-- means it doesn't add any information.
RedundantEq :: Expr v n -> DepError v n
-- | An empty system of equations.
noDeps :: Dependencies v n
-- | addEquation d e: Add the equation e = 0 to the
-- system d.
addEquation :: (Hashable n, Hashable v, RealFrac (Phase n), Ord v, Floating n) => Dependencies v n -> Expr v n -> Either (DepError v n) (Dependencies v n)
-- | Eliminate an variable from the equations. Returns the eliminated
-- equations. Before elimination it performs substitution to minimize the
-- number of eliminated equations.
--
-- Important: this function is still experimental and mostly
-- untested.
eliminate :: (Hashable n, Show n, Hashable v, RealFrac (Phase n), Ord v, Show v, Floating n) => Dependencies v n -> v -> (Dependencies v n, [Expr v n])
-- | Return the value of the variable, or a list of variables it depends
-- on. Only linear dependencies are shown.
getKnown :: (Eq v, Hashable v) => v -> Dependencies v n -> Either [v] n
-- | Return all known variables.
knownVars :: Dependencies v n -> [(v, n)]
-- | Return True if the variable is known or dependend.
varDefined :: (Eq v, Hashable v) => v -> Dependencies v n -> Bool
-- | Return all nonlinear equations e_i, where e_i = 0.
nonlinearEqs :: (Ord n, Ord v, Floating n) => Dependencies v n -> [Expr v n]
-- | Return all dependend variables with their dependencies.
dependendVars :: Eq n => Dependencies v n -> [(v, LinExpr v n)]
-- | Make the expressions on both sides equal
(===) :: (MonadState (Dependencies v n) m, MonadError (DepError v n) m, Eq v, Hashable v, Hashable n, RealFrac n, Floating n, Ord v) => Expr v n -> Expr v n -> m ()
infixr 1 ===
-- | Make the pairs of expressions on both sides equal. No error is
-- signaled if the equation for one of the sides is Redundant
-- for example in (x, 0) == (y, 0).
(=&=) :: (MonadState (Dependencies v n) m, MonadError (DepError v n) m, Eq v, Hashable v, Hashable n, RealFrac n, Floating n, Ord v) => (Expr v n, Expr v n) -> (Expr v n, Expr v n) -> m ()
infixr 1 =&=
-- | Get the dependencies from a state monad. Specialized version of
-- get.
dependencies :: MonadState (Dependencies v n) m => m (Dependencies v n)
-- | Return the value of the variable or throw an error.
getValue :: (MonadState (Dependencies v n) m, MonadError (DepError v n) m, Eq v, Hashable v) => v -> m n
-- | Monadic version of getKnown.
getKnownM :: (MonadState (Dependencies v n) m, Hashable v, Eq v) => v -> m (Either [v] n)
-- | Monadic version of varDefined.
varDefinedM :: (MonadState (Dependencies v n) m, Hashable v, Eq v) => v -> m Bool
-- | Monadic version of eliminate.
eliminateM :: (MonadState (Dependencies v n) m, Hashable n, Hashable v, Show n, Show v, RealFrac n, Ord v, Floating n) => v -> m [Expr v n]
-- | Succeed even when trowing a RedundantEq error.
ignore :: MonadError (DepError v n) m => m () -> m ()
-- | A monad for solving equations. Basicly just a state and exception
-- monad over Dependencies and DepError.
type MFSolver v n a = MFSolverT v n Identity a
-- | run the solver.
runSolver :: MFSolver v n a -> Dependencies v n -> Either (DepError v n) (a, Dependencies v n)
-- | Return the result of solving the equations or an error.
evalSolver :: MFSolver v n a -> Dependencies v n -> Either (DepError v n) a
-- | Run the solver and return the dependencies or an error.
execSolver :: MFSolver v n a -> Dependencies v n -> Either (DepError v n) (Dependencies v n)
-- | Return the result of solving the equations, or throw the error as an
-- exception.
unsafeSolve :: (Typeable n, Typeable v, Show n, Show v, Ord n, Num n) => Dependencies v n -> MFSolver v n a -> a
-- | Show all variables and equations. Useful in combination with
-- execSolver.
showVars :: (Show n, Show v, Ord n, Ord v, Floating n) => Either (DepError v n) (Dependencies v n) -> IO ()
-- | A monad transformer for solving equations. Basicly just a state and
-- exception monad transformer over Dependencies and
-- DepError.
data MFSolverT v n m a
runSolverT :: MFSolverT v n m a -> Dependencies v n -> m (Either (DepError v n) (a, Dependencies v n))
-- | Return the result of solving the equations or an error. Monadic
-- version.
evalSolverT :: Functor f => MFSolverT v n f b -> Dependencies v n -> f (Either (DepError v n) b)
-- | Run the solver and return the dependencies or an error. Monadic
-- version.
execSolverT :: Functor m => MFSolverT v n m a -> Dependencies v n -> m (Either (DepError v n) (Dependencies v n))
-- | Return the result of solving the equations, or throw the error as an
-- exception. Monadic version.
unsafeSolveT :: (Num n, Ord n, Show n, Show v, Typeable n, Typeable v, Monad m) => Dependencies v n -> MFSolverT v n m a -> m a
instance GHC.Classes.Eq Math.MFSolve.BinaryOp
instance GHC.Generics.Generic Math.MFSolve.UnaryOp
instance GHC.Classes.Eq Math.MFSolve.UnaryOp
instance GHC.Generics.Generic Math.MFSolve.SimpleVar
instance GHC.Classes.Ord Math.MFSolve.SimpleVar
instance GHC.Classes.Eq Math.MFSolve.SimpleVar
instance (GHC.Show.Show n, GHC.Show.Show v) => GHC.Show.Show (Math.MFSolve.LinExpr v n)
instance (GHC.Classes.Eq n, GHC.Classes.Eq v) => GHC.Classes.Eq (Math.MFSolve.LinExpr v n)
instance GHC.Generics.Generic (Math.MFSolve.LinExpr v n)
instance GHC.Generics.Generic (Math.MFSolve.Expr v n)
instance (GHC.Classes.Eq n, GHC.Classes.Eq v) => GHC.Classes.Eq (Math.MFSolve.Expr v n)
instance GHC.Generics.Generic (Math.MFSolve.NonLinExpr v n)
instance (GHC.Classes.Eq v, GHC.Classes.Eq n) => GHC.Classes.Eq (Math.MFSolve.NonLinExpr v n)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Math.MFSolve.MFSolverT v n m)
instance Control.Monad.Writer.Class.MonadWriter s m => Control.Monad.Writer.Class.MonadWriter s (Math.MFSolve.MFSolverT v n m)
instance Control.Monad.Reader.Class.MonadReader s m => Control.Monad.Reader.Class.MonadReader s (Math.MFSolve.MFSolverT v n m)
instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError (Math.MFSolve.DepError v n) (Math.MFSolve.MFSolverT v n m)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Math.MFSolve.Dependencies v n) (Math.MFSolve.MFSolverT v n m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Math.MFSolve.MFSolverT v n m)
instance GHC.Base.Monad m => GHC.Base.Monad (Math.MFSolve.MFSolverT v n m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Math.MFSolve.MFSolverT v n m)
instance GHC.Base.Functor m => GHC.Base.Functor (Math.MFSolve.MFSolverT v n m)
instance Control.Monad.Trans.Class.MonadTrans (Math.MFSolve.MFSolverT v n)
instance (GHC.Classes.Ord n, GHC.Num.Num n, GHC.Show.Show v, GHC.Show.Show n, Data.Typeable.Internal.Typeable v, Data.Typeable.Internal.Typeable n) => GHC.Exception.Type.Exception (Math.MFSolve.DepError v n)
instance (GHC.Num.Num n, GHC.Classes.Ord n, GHC.Show.Show n, GHC.Show.Show v) => GHC.Show.Show (Math.MFSolve.DepError v n)
instance (GHC.Show.Show n, GHC.Float.Floating n, GHC.Classes.Ord n, GHC.Classes.Ord v, GHC.Show.Show v) => GHC.Show.Show (Math.MFSolve.Dependencies v n)
instance (Data.Hashable.Class.Hashable v, Data.Hashable.Class.Hashable n) => Data.Hashable.Class.Hashable (Math.MFSolve.NonLinExpr v n)
instance (Data.Hashable.Class.Hashable v, Data.Hashable.Class.Hashable n) => Data.Hashable.Class.Hashable (Math.MFSolve.Expr v n)
instance (GHC.Classes.Ord n, GHC.Num.Num n, GHC.Classes.Eq n, GHC.Show.Show v, GHC.Show.Show n) => GHC.Show.Show (Math.MFSolve.Expr v n)
instance (GHC.Float.Floating n, GHC.Classes.Ord n, GHC.Classes.Ord v) => GHC.Num.Num (Math.MFSolve.Expr v n)
instance (GHC.Float.Floating n, GHC.Classes.Ord n, GHC.Classes.Ord v) => GHC.Real.Fractional (Math.MFSolve.Expr v n)
instance (GHC.Float.Floating n, GHC.Classes.Ord n, GHC.Classes.Ord v) => GHC.Float.Floating (Math.MFSolve.Expr v n)
instance (Data.Hashable.Class.Hashable v, Data.Hashable.Class.Hashable n) => Data.Hashable.Class.Hashable (Math.MFSolve.LinExpr v n)
instance Data.Hashable.Class.Hashable Math.MFSolve.SimpleVar
instance GHC.Show.Show Math.MFSolve.SimpleVar
instance (GHC.Show.Show v, GHC.Classes.Ord n, GHC.Show.Show n, GHC.Num.Num n, GHC.Classes.Eq n) => GHC.Show.Show (Math.MFSolve.SimpleExpr v n)
instance Data.Hashable.Class.Hashable Math.MFSolve.UnaryOp
instance GHC.Show.Show Math.MFSolve.UnaryOp
instance GHC.Show.Show Math.MFSolve.BinaryOp