module ToySolver.Data.FOL.Arith
(
Expr (..)
, var
, evalExpr
, module ToySolver.Data.ArithRel
, Atom (..)
, evalAtom
, module ToySolver.Data.FOL.Formula
, SatResult (..)
) where
import qualified Data.IntMap as IM
import qualified Data.IntSet as IS
import Data.Ratio
import ToySolver.Data.ArithRel
import ToySolver.Data.FOL.Formula
import ToySolver.Data.Var
data Expr r
= Const r
| Var Var
| Expr r :+: Expr r
| Expr r :*: Expr r
| Expr r :/: Expr r
deriving (Eq, Ord, Show)
instance Num r => Num (Expr r) where
a + b = a :+: b
a * b = a :*: b
a b = a + negate b
negate a = Const (1) :*: a
abs a = a
signum _ = 1
fromInteger = Const . fromInteger
instance Fractional r => Fractional (Expr r) where
a / b = a :/: b
fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
instance Functor Expr where
fmap f = g
where
g (Const c) = Const (f c)
g (Var v) = Var v
g (a :+: b) = g a :+: g b
g (a :*: b) = g a :*: g b
g (a :/: b) = g a :/: g b
instance Variables (Expr r) where
vars (Const _) = IS.empty
vars (Var v) = IS.singleton v
vars (a :+: b) = vars a `IS.union` vars b
vars (a :*: b) = vars a `IS.union` vars b
vars (a :/: b) = vars a `IS.union` vars b
var :: Var -> Expr r
var = Var
evalExpr :: Fractional r => Model r -> Expr r -> r
evalExpr m = f
where
f (Const x) = x
f (Var v) = m IM.! v
f (a :+: b) = f a + f b
f (a :*: b) = f a * f b
f (a :/: b) = f a / f b
type Atom c = Rel (Expr c)
evalAtom :: (Real r, Fractional r) => Model r -> Atom r -> Bool
evalAtom m (Rel a op b) = evalOp op (evalExpr m a) (evalExpr m b)
instance IsRel (Expr c) (Formula (Atom c)) where
rel op a b = Atom $ rel op a b
data SatResult r = Unknown | Unsat | Sat (Model r)
deriving (Show, Eq, Ord)