MapleInterpreter.hs revision f14bf11310b51516794b2ad792907c45ebeb73d7
4b0a4c7dea0f67a233dcc42ce9bb18d36de109aeChristian Maeder{-# LANGUAGE FlexibleContexts, TypeSynonymInstances #-}
10397bcc134edbcfbe3ae2c7ea4c6080036aae22Christian MaederModule : $Header$
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian MaederDescription : Maple instance for the AssignmentStore class
23f2c59644866aa82e90de353e77f9f1d1b51b9aChristian MaederCopyright : (c) Ewaryst Schulz, DFKI Bremen 2010
e7ce154edb906685b3fa7f6c0a764e18a4658068Christian MaederLicense : GPLv2 or higher, see LICENSE.txt
4b0a4c7dea0f67a233dcc42ce9bb18d36de109aeChristian MaederMaintainer : Ewaryst.Schulz@dfki.de
4b0a4c7dea0f67a233dcc42ce9bb18d36de109aeChristian MaederStability : experimental
f3a94a197960e548ecd6520bb768cb0d547457bbChristian MaederPortability : non-portable (via imports)
23f2c59644866aa82e90de353e77f9f1d1b51b9aChristian MaederMaple as AssignmentStore
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederimport Common.ProverTools (missingExecutableInPath)
fc8c6570c7b4ee13f375eb607bed2290438573bfChristian Maederimport Common.Utils (getEnvDef, trimLeft)
f8f78a2c8796a387a4348cc672ae08e8d9f69315Christian Maederimport CSL.Parse_AS_Basic (parseExpression)
7c554e9d4a39b8eb3b0881f20807c95dd8e793aeChristian Maeder-- the process communication interface
e8ffec0fa3d3061061bdc16e44247b9cf96b050fChristian Maederimport qualified Interfaces.Process as PC
f8f78a2c8796a387a4348cc672ae08e8d9f69315Christian Maeder--import Control.Monad.Trans (MonadTrans (..), MonadIO (..))
024621f43239cfe9629e35d35a8669fad7acbba2Christian Maederimport Control.Monad.Error (ErrorT(..), MonadError (..))
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederimport Data.List hiding (lookup)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederimport qualified Data.Set as Set
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederimport System.Exit (ExitCode)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederimport Prelude hiding (lookup)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder-- ----------------------------------------------------------------------
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder-- * Maple Calculator Instances
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder-- ----------------------------------------------------------------------
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder-- | MapleInterpreter with Translator based on the CommandState
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederdata MITrans = MITrans { getBMap :: BMap
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder , depGraph :: AssignmentDepGraph ()
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder , debugMode :: Bool
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder , symbolicMode :: Bool
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder , vericondOut :: Maybe Handle
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder , channelTimeout :: PC.DTime }
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder-- Maple interface, built on CommandState
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maedertype MapleIO = ErrorT ASError (IOS MITrans)
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maederinstance AssignmentStore MapleIO where
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder assign = mapleAssign (evalMapleString True) mapleTransS mapleTransVarE
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder mapleAssigns (evalMapleString False []) mapleTransS mapleTransVarE
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder lookup = mapleLookup (evalMapleString True []) mapleTransS
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder eval = mapleEval (evalMapleString True []) mapleTransE
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder check = mapleCheck (evalMapleString True []) mapleTransE
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder names = get >>= return . SMem . getBMap
afa6848d579d235c9677e1ab477916df8e5ae11aChristian Maeder evalRaw s = get >>= liftIO . flip (mapleDirect True) s
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder getUndefinedConstants e = do
e7ce154edb906685b3fa7f6c0a764e18a4658068Christian Maeder adg <- gets depGraph
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder let g = isNothing . depGraphLookup adg
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder return $ Set.filter g $ Set.map SimpleConstant $ setOfUserDefined e
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder genNewKey = do
986e0e9cf8c2358f455460b3fc75ce7c5dcf0973Christian Maeder let (bm, i) = genKey $ getBMap mit
6a7e00a968cb0f3f9ccae19ab47ef3636c7e79bfChristian Maeder put mit { getBMap = bm }
88ece6e49930670e8fd3ee79c89a2e918d2fbd0cChristian Maederinstance VCGenerator MapleIO where
88ece6e49930670e8fd3ee79c89a2e918d2fbd0cChristian Maeder getDepGraph = gets depGraph
6a7e00a968cb0f3f9ccae19ab47ef3636c7e79bfChristian Maeder updateConstant n def =
6a7e00a968cb0f3f9ccae19ab47ef3636c7e79bfChristian Maeder let f gr = updateGraph gr n
6a7e00a968cb0f3f9ccae19ab47ef3636c7e79bfChristian Maeder $ DepGraphAnno { annoDef = def
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder , annoVal = () }
6a7e00a968cb0f3f9ccae19ab47ef3636c7e79bfChristian Maeder mf mit = mit { depGraph = f $ depGraph mit }
6a7e00a968cb0f3f9ccae19ab47ef3636c7e79bfChristian Maeder addVC ea e = do
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder -- s = show $ text "VC for" <+> pretty ea <> text ":" $++$ pretty e
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder s = show $ pretty e <> text ";"
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder -- s = (++ "\n\n;\n\n") $ showRaw $ text "VC for" <+> pretty ea <> text ":" $++$ pretty e
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder-- vcHdl = stdout
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder vcHdl <- liftM (fromMaybe stdout) $ gets vericondOut
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder liftIO $ hPutStrLn vcHdl s where
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maederinstance StepDebugger MapleIO where
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder setDebugMode b = modify mf where mf mit = mit { debugMode = b }
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder getDebugMode = gets debugMode
af621d0066770895fd79562728e93099c8c52060Christian Maeder-- ----------------------------------------------------------------------
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder-- * Maple Transformation Instances
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder-- ----------------------------------------------------------------------
af621d0066770895fd79562728e93099c8c52060Christian Maeder-- TODO: Review the vargen facility and the cache-stuff in Transformation
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder-- | Variable generator instance for internal variables on the Hets-side,
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder-- in contrast to the newvar generation in lookupOrInsert of the BMap, which
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder-- generates variables for the Maple-side. We use nevertheless the same counter.
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maederinstance VarGen MapleIO where
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder let i = newkey $ getBMap s
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder put $ s { getBMap = (getBMap s) { newkey = i + 1 } }
05e2a3161e4589a717c6fe5c7306820273a473c5Christian Maeder return $ "?" ++ show i
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder-- ----------------------------------------------------------------------
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder-- * Maple syntax functions
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder-- ----------------------------------------------------------------------
e76e6a43f51438215737d6fc176c89da05bb86daChristian MaederprintExp :: EXPRESSION -> String
8485da94b57d8b5135ee685b55c982b037ed4140Christian MaederprintExp e = show $ runReader (printExpression e) mapleOpInfoNameMap
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder--printExp = exportExp
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder--printExp = show . pretty
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder-- :: ExpressionPrinter m => EXPRESSION -> m Doc
0a85c4dc6f4bba88e1994e8f1cd3657b6503b220Christian MaedermapleOpInfoMap :: OpInfoMap
e76e6a43f51438215737d6fc176c89da05bb86daChristian MaedermapleOpInfoMap = operatorInfoMap
36c6cc568751e4235502cfee00ba7b597dae78dcChristian MaedermapleOpInfoNameMap :: OpInfoNameMap
a94b530fa82bb281caac766a9c0f7b2fcfe7a584Christian MaedermapleOpInfoNameMap = operatorInfoNameMap
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian Maeder-- TODO: The mapping should be OPNAME to OPNAME or we should remove the mapping
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian Maeder-- just adapt the opinfo-map for pretty printing for each CAS!
dc6b48bb46df8e56da3491c98476e6da0d1d5d1dChristian MaedercslMapleDefaultMapping :: [(OPNAME, String)]
8485da94b57d8b5135ee685b55c982b037ed4140Christian MaedercslMapleDefaultMapping =
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder let idmapping = map (\ x -> (x, show x))
fcb1d8a27670f3206bd4ca28d77d4172619db602Christian Maeder-- ampmapping = map (\ x -> (x, "&" ++ show x))
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder possibleIntervalOps = [ OP_mult, OP_div, OP_plus, OP_minus, OP_neg
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder , OP_cos, OP_sin, OP_tan, OP_sqrt, OP_abs
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder , OP_neq, OP_lt, OP_leq, OP_eq, OP_gt, OP_geq ]
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder logicOps = [ OP_and, OP_or, OP_impl, OP_true, OP_false ]
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder otherOps = [ OP_factor, OP_maxloc, OP_sign, OP_Pi, OP_min, OP_max
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder , OP_fthrt, OP_reldist, OP_reldistLe]
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder specialOps = [(OP_pow, "^"), (OP_failure, "FAIL")]
e76e6a43f51438215737d6fc176c89da05bb86daChristian Maeder-- specialOp = (OP_pow, "&**")
8485da94b57d8b5135ee685b55c982b037ed4140Christian Maeder in specialOps ++ idmapping logicOps ++ idmapping possibleIntervalOps
dc6b48bb46df8e56da3491c98476e6da0d1d5d1dChristian Maeder ++ idmapping otherOps
4b0a4c7dea0f67a233dcc42ce9bb18d36de109aeChristian MaederprintAssignment :: String -> [String] -> EXPRESSION -> String
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian MaederprintAssignment n [] e = concat [n, ":= ", printExp e, ":", n, ";"]
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederprintAssignment n l e = concat [ n, ":= proc", args, printExp e
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian Maeder , " end proc:", n, args, ";"]
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian Maeder where args = concat [ "(", intercalate ", " l, ") " ]
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederprintAssignmentWithEval :: String -> [String] -> EXPRESSION -> String
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederprintAssignmentWithEval n [] e =
fe5dbb45b6a8abf34375b4bc5f2a81cda664c0e4Christian Maeder concat [n, ":= evalf(", printExp e, "):", n, ";"]
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederprintAssignmentWithEval n l e = concat [ n, ":= proc", args, printExp e
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian Maeder , " end proc:", n, args, ";"]
fcec1ffa4a95dbc47cf23f75e6843ceff93a925eChristian Maeder where args = concat [ "(", intercalate ", " l, ") " ]
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederprintEvaluation :: EXPRESSION -> String
836e72a3c413366ba9801726f3b249c7791cb9caChristian MaederprintEvaluation e = printExp e ++ ";"
9c5b1136299d9052e4e995614a3a36a051a2682fChristian MaederprintLookup :: String -> String
c1031ac42b3f3d7d0fe7d9d6b54423a092d473a0Christian MaederprintLookup n = n ++ ";"
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederThe evalf makes the decision much faster. As we verify the result formally
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian Maederthis should not be problematic in a formal context!
fe5dbb45b6a8abf34375b4bc5f2a81cda664c0e4Christian MaederIn the following context "is" gives up if we do not use "evalf":
b5699d97a9e2b4496f98d624f4b0a537986651c3Christian Maederx2 := cos(10+cos(10)/sin(10)+cos(10+cos(10)/sin(10))/sin(10+cos(10)/sin(10))
b5699d97a9e2b4496f98d624f4b0a537986651c3Christian Maeder + cos(10+cos(10)/sin(10)+cos(10+cos(10)/sin(10))/sin(10+cos(10)/sin(10)))
3cafc73a998493f9ed3d5e934c0ab80bcfb465c2Christian Maeder / sin(10+cos(10)/sin(10)+cos(10+cos(10)/sin(10))/sin(10+cos(10)/sin(10))));
7bf6d421b0ea31ae63f1fe04919942b931abda47Christian Maederis(abs(x2)<1.0e-4);
7bf6d421b0ea31ae63f1fe04919942b931abda47Christian MaederprintBooleanExpr :: EXPRESSION -> String
e76e6a43f51438215737d6fc176c89da05bb86daChristian MaederprintBooleanExpr e = concat [ "is(evalf(", printExp e, "));" ]
7bf6d421b0ea31ae63f1fe04919942b931abda47Christian MaedergetBooleanFromExpr :: EXPRESSION -> Either String Bool
c18e9c3c6d5039618f1f2c05526ece84c7794ea3Christian MaedergetBooleanFromExpr (Op (OpId OP_true) _ _ _) = Right True
c18e9c3c6d5039618f1f2c05526ece84c7794ea3Christian MaedergetBooleanFromExpr (Op (OpId OP_false) _ _ _) = Right False
c18e9c3c6d5039618f1f2c05526ece84c7794ea3Christian MaedergetBooleanFromExpr (Op (OpId OP_failure) _ _ _) = Left "Maple FAILURE"
7c554e9d4a39b8eb3b0881f20807c95dd8e793aeChristian MaedergetBooleanFromExpr e = Left $ "Cannot translate expression to boolean: "
7bf6d421b0ea31ae63f1fe04919942b931abda47Christian Maeder-- The evalf is mandatory if we use the if-statement for encoding
3cafc73a998493f9ed3d5e934c0ab80bcfb465c2Christian Maeder-- | As maple does not evaluate boolean expressions we encode them in an
836e72a3c413366ba9801726f3b249c7791cb9caChristian Maeder-- if-stmt and transform the numeric response back.
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaederprintBooleanExpr :: EXPRESSION -> String
76fa667489c5e0868ac68de9f0253ac10f73d0b5Christian MaederprintBooleanExpr e = concat [ "if evalf("
9c5b1136299d9052e4e995614a3a36a051a2682fChristian Maeder , printExp e, ") then 1 else 0 fi;"
e8a2ca3a7b3e9a19ef03b6b1c0b5d03dbad6463cChristian MaedergetBooleanFromExpr :: EXPRESSION -> Bool
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaedergetBooleanFromExpr (Int 1 _) = True
e76e6a43f51438215737d6fc176c89da05bb86daChristian MaedergetBooleanFromExpr (Int 0 _) = False
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian MaedergetBooleanFromExpr e =
ff9a53595208f532c25ac5168f772f48fd80fdb5Christian Maeder error $ "getBooleanFromExpr: can't translate expression to boolean: "
wrapCommand :: IOS PC.CommandState a -> IOS MITrans a
(res, _) <- runIOS (getMI mit) $ PC.call (channelTimeout mit) s
res <- lift $ wrapCommand $ PC.call (channelTimeout mit) s
-- when b $ liftIO $ putStrLn $ show $ map trans $ maybeToList $ parseExpression mapleOpInfoMap $ trimLeft
-> PC.DTime -- ^ timeout for response
cs <- PC.start (maplecmd ++ " -q") v
(_, cs') <- runIOS cs $ PC.call 0.5
fmap fst $ runIOS (getMI rit) (PC.call 0.5 $ "with(" ++ s ++ ");")
(ec, _) <- runIOS (getMI mit) $ PC.close $ Just "quit;"
-> PC.DTime -- ^ timeout for response