module Math.Programming.Dsl where
import Data.Bifunctor
import Data.List (sortOn)
import Math.Programming.Types
minimize :: LPMonad m => Expr m -> m (Objective m)
minimize objectiveExpr = do
objective <- addObjective objectiveExpr
setObjectiveSense objective Minimization
pure objective
maximize :: LPMonad m => Expr m -> m (Objective m)
maximize objectiveExpr = do
objective <- addObjective objectiveExpr
setObjectiveSense objective Maximization
pure objective
evalExpr :: LPMonad m => Expr m -> m (Numeric m)
evalExpr expr = traverse getVariableValue expr >>= return . eval
free :: LPMonad m => m (Variable m)
free = addVariable `within` Free
nonNeg :: LPMonad m => m (Variable m)
nonNeg = addVariable `within` NonNegativeReals
nonPos :: LPMonad m => m (Variable m)
nonPos = addVariable `within` NonPositiveReals
bounded :: LPMonad m => Numeric m -> Numeric m -> m (Variable m)
bounded lo hi = within addVariable (Interval lo hi)
within :: LPMonad m => m (Variable m) -> Bounds (Numeric m) -> m (Variable m)
within makeVar bounds = do
variable <- makeVar
setVariableBounds variable bounds
pure variable
integer :: IPMonad m => m (Variable m)
integer = addVariable `asKind` Integer
binary :: IPMonad m => m (Variable m)
binary = addVariable `asKind` Binary
nonNegInteger :: IPMonad m => m (Variable m)
nonNegInteger = addVariable `asKind` Integer `within` NonNegativeReals
nonPosInteger :: IPMonad m => m (Variable m)
nonPosInteger = addVariable `asKind` Integer `within` NonPositiveReals
asKind :: IPMonad m => m (Variable m) -> Domain -> m (Variable m)
asKind make domain = do
variable <- make
setVariableDomain variable domain
pure variable
named :: (Monad m, Nameable m a) => m a -> String -> m a
named make name = do
x <- make
setName x name
pure x
nameOf :: (Monad m, Nameable m a) => a -> m String
nameOf = getName
(#+@) :: Num a => a -> b -> LinearExpression a b
(#+.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
(@+#) :: Num a => b -> a -> LinearExpression a b
(@+@) :: Num a => b -> b -> LinearExpression a b
(@+.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
(.+#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
(.+@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
(.+.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
(#-@) :: Num a => a -> b -> LinearExpression a b
(#-.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
(@-#) :: Num a => b -> a -> LinearExpression a b
(@-@) :: Num a => b -> b -> LinearExpression a b
(@-.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
(.-#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
(.-@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
(.-.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
(#*.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
(.*#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
(#*@) :: Num a => a -> b -> LinearExpression a b
(@*#) :: Num a => b -> a -> LinearExpression a b
(@/#) :: Fractional a => b -> a -> LinearExpression a b
(./#) :: Fractional a => LinearExpression a b -> a -> LinearExpression a b
x #+@ y = con x .+. var y
x #+. y = con x .+. y
x @+# y = var x .+. con y
x @+@ y = var x .+. var y
x @+. y = var x .+. y
x .+@ y = x .+. var y
x .+# y = x .+. con y
x .+. y = x <> y
x #-@ y = con x .-. var y
x #-. y = con x .-. y
x @-# y = var x .-. con y
x @-@ y = var x .-. var y
x @-. y = var x .-. y
x .-# y = x .-. con y
x .-@ y = x .-. var y
x .-. y = x .+. (-1) #*. y
x #*@ y = var y .*# x
x #*. y = y .*# x
x @*# y = var x .*# y
x .*# y = first (* y) x
x @/# y = var x ./# y
x ./# y = first (/ y) x
infixl 6 #+@
infixl 6 #+.
infixl 6 @+#
infixl 6 @+@
infixl 6 @+.
infixl 6 .+#
infixl 6 .+@
infixl 6 .+.
infixl 6 #-@
infixl 6 #-.
infixl 6 @-#
infixl 6 @-@
infixl 6 @-.
infixl 6 .-#
infixl 6 .-@
infixl 6 .-.
infixl 7 #*@
infixl 7 #*.
infixl 7 @*#
infixl 7 .*#
infixl 7 @/#
infixl 7 ./#
simplify :: (Ord b, Num a) => LinearExpression a b -> LinearExpression a b
simplify (LinearExpression terms constant)
= LinearExpression (reduce (sortOn snd terms)) constant
where
reduce [] = []
reduce ((c, x): []) = [(c, x)]
reduce ((c, x): (c', x'): xs)
| x == x' = (c + c', x) : reduce xs
| otherwise = (c, x) : reduce ((c', x'): xs)
eval :: Num a => LinearExpression a a -> a
eval (LinearExpression terms constant) = constant + sum (map (uncurry (*)) terms)
var :: Num a => b -> LinearExpression a b
var x = LinearExpression [(1, x)] 0
con :: Num a => a -> LinearExpression a b
con x = LinearExpression [] x
exprSum :: Num a => [LinearExpression a b] -> LinearExpression a b
exprSum = mconcat
varSum :: Num a => [b] -> LinearExpression a b
varSum = mconcat . fmap var
(#<=@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
(#<=.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
(@<=#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
(@<=@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
(@<=.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
(.<=#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
(.<=@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
(.<=.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
(#>=@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
(#>=.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
(@>=#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
(@>=@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
(@>=.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
(.>=#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
(.>=@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
(.>=.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
(#==@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
(#==.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
(@==#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
(@==@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
(@==.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
(.==#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
(.==@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
(.==.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
x #<=@ y = addConstraint $ Inequality LT (con x) (var y)
x #<=. y = addConstraint $ Inequality LT (con x) y
x @<=# y = addConstraint $ Inequality LT (var x) (con y)
x @<=@ y = addConstraint $ Inequality LT (var x) (var y)
x @<=. y = addConstraint $ Inequality LT (var x) y
x .<=# y = addConstraint $ Inequality LT x (con y)
x .<=@ y = addConstraint $ Inequality LT x (var y)
x .<=. y = addConstraint $ Inequality LT x y
x #>=@ y = addConstraint $ Inequality GT (con x) (var y)
x #>=. y = addConstraint $ Inequality GT (con x) y
x @>=# y = addConstraint $ Inequality GT (var x) (con y)
x @>=@ y = addConstraint $ Inequality GT (var x) (var y)
x @>=. y = addConstraint $ Inequality GT (var x) y
x .>=# y = addConstraint $ Inequality GT x (con y)
x .>=@ y = addConstraint $ Inequality GT x (var y)
x .>=. y = addConstraint $ Inequality GT x y
x #==@ y = addConstraint $ Inequality EQ (con x) (var y)
x #==. y = addConstraint $ Inequality EQ (con x) y
x @==# y = addConstraint $ Inequality EQ (var x) (con y)
x @==@ y = addConstraint $ Inequality EQ (var x) (var y)
x @==. y = addConstraint $ Inequality EQ (var x) y
x .==# y = addConstraint $ Inequality EQ x (con y)
x .==@ y = addConstraint $ Inequality EQ x (var y)
x .==. y = addConstraint $ Inequality EQ x y
infix 4 #<=@
infix 4 #<=.
infix 4 @<=#
infix 4 @<=@
infix 4 @<=.
infix 4 .<=#
infix 4 .<=@
infix 4 .<=.
infix 4 #>=@
infix 4 #>=.
infix 4 @>=#
infix 4 @>=@
infix 4 @>=.
infix 4 .>=#
infix 4 .>=@
infix 4 .>=.
infix 4 #==@
infix 4 #==.
infix 4 @==#
infix 4 @==@
infix 4 @==.
infix 4 .==#
infix 4 .==@
infix 4 .==.