packages feed

math-programming 0.4.0 → 0.5.0

raw patch · 13 files changed

+705/−786 lines, 13 filesdep +QuickCheckdep +exceptionsdep +hspecdep −tastydep −tasty-discoverdep −tasty-hunitdep ~basedep ~containersdep ~mtlPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, exceptions, hspec, transformers

Dependencies removed: tasty, tasty-discover, tasty-hunit, tasty-quickcheck

Dependency ranges changed: base, containers, mtl, text

API changes (from Hackage documentation)

- Math.Programming: (#*.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- Math.Programming: (#*@) :: Num a => a -> b -> LinearExpression a b
- Math.Programming: (#+.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- Math.Programming: (#+@) :: Num a => a -> b -> LinearExpression a b
- Math.Programming: (#-.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- Math.Programming: (#-@) :: Num a => a -> b -> LinearExpression a b
- Math.Programming: (#<=.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
- Math.Programming: (#<=@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
- Math.Programming: (#==.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
- Math.Programming: (#==@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
- Math.Programming: (#>=.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
- Math.Programming: (#>=@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
- Math.Programming: (.*#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming: (.+#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming: (.+@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
- Math.Programming: (.-#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming: (.-@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
- Math.Programming: (./#) :: Fractional a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming: (.<=#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
- Math.Programming: (.<=@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
- Math.Programming: (.==#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
- Math.Programming: (.==@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
- Math.Programming: (.>=#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
- Math.Programming: (.>=@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
- Math.Programming: (@*#) :: Num a => b -> a -> LinearExpression a b
- Math.Programming: (@+#) :: Num a => b -> a -> LinearExpression a b
- Math.Programming: (@+.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
- Math.Programming: (@+@) :: Num a => b -> b -> LinearExpression a b
- Math.Programming: (@-#) :: Num a => b -> a -> LinearExpression a b
- Math.Programming: (@-.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
- Math.Programming: (@-@) :: Num a => b -> b -> LinearExpression a b
- Math.Programming: (@/#) :: Fractional a => b -> a -> LinearExpression a b
- Math.Programming: (@<=#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
- Math.Programming: (@<=.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
- Math.Programming: (@<=@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
- Math.Programming: (@==#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
- Math.Programming: (@==.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
- Math.Programming: (@==@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
- Math.Programming: (@>=#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
- Math.Programming: (@>=.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
- Math.Programming: (@>=@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
- Math.Programming: -- opaque values, but instances may expose more details.
- Math.Programming: -- | The type of objectives in the model. <a>LPMonad</a> treats these as
- Math.Programming: LinearExpression :: [(a, b)] -> a -> LinearExpression a b
- Math.Programming: class (LPMonad m) => IPMonad m
- Math.Programming: class (Monad m, Show (Numeric m), RealFrac (Numeric m)) => LPMonad m where {
- Math.Programming: data LinearExpression a b
- Math.Programming: data family Objective m :: *;
- Math.Programming: exprSum :: Num a => [LinearExpression a b] -> LinearExpression a b
- Math.Programming: getDualValue :: LPMonad m => Constraint m -> m (Numeric m)
- Math.Programming: nameOf :: (Monad m, Nameable m a) => a -> m String
- Math.Programming: named :: (Monad m, Nameable m a) => m a -> String -> m a
- Math.Programming: removeConstraint :: LPMonad m => Constraint m -> m ()
- Math.Programming: removeVariable :: LPMonad m => Variable m -> m ()
- Math.Programming: type family Numeric m :: *;
- Math.Programming: varSum :: Num a => [b] -> LinearExpression a b
- Math.Programming: }
- Math.Programming.Dsl: (#*.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (#*@) :: Num a => a -> b -> LinearExpression a b
- Math.Programming.Dsl: (#+.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (#+@) :: Num a => a -> b -> LinearExpression a b
- Math.Programming.Dsl: (#-.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (#-@) :: Num a => a -> b -> LinearExpression a b
- Math.Programming.Dsl: (#<=.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
- Math.Programming.Dsl: (#<=@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (#==.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
- Math.Programming.Dsl: (#==@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (#>=.) :: LPMonad m => Numeric m -> Expr m -> m (Constraint m)
- Math.Programming.Dsl: (#>=@) :: LPMonad m => Numeric m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (.*#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming.Dsl: (.+#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming.Dsl: (.+.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (.+@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
- Math.Programming.Dsl: (.-#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming.Dsl: (.-.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (.-@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
- Math.Programming.Dsl: (./#) :: Fractional a => LinearExpression a b -> a -> LinearExpression a b
- Math.Programming.Dsl: (.<=#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
- Math.Programming.Dsl: (.<=@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (.==#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
- Math.Programming.Dsl: (.==@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (.>=#) :: LPMonad m => Expr m -> Numeric m -> m (Constraint m)
- Math.Programming.Dsl: (.>=@) :: LPMonad m => Expr m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (@*#) :: Num a => b -> a -> LinearExpression a b
- Math.Programming.Dsl: (@+#) :: Num a => b -> a -> LinearExpression a b
- Math.Programming.Dsl: (@+.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (@+@) :: Num a => b -> b -> LinearExpression a b
- Math.Programming.Dsl: (@-#) :: Num a => b -> a -> LinearExpression a b
- Math.Programming.Dsl: (@-.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: (@-@) :: Num a => b -> b -> LinearExpression a b
- Math.Programming.Dsl: (@/#) :: Fractional a => b -> a -> LinearExpression a b
- Math.Programming.Dsl: (@<=#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
- Math.Programming.Dsl: (@<=.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
- Math.Programming.Dsl: (@<=@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (@==#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
- Math.Programming.Dsl: (@==.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
- Math.Programming.Dsl: (@==@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: (@>=#) :: LPMonad m => Variable m -> Numeric m -> m (Constraint m)
- Math.Programming.Dsl: (@>=.) :: LPMonad m => Variable m -> Expr m -> m (Constraint m)
- Math.Programming.Dsl: (@>=@) :: LPMonad m => Variable m -> Variable m -> m (Constraint m)
- Math.Programming.Dsl: con :: Num a => a -> LinearExpression a b
- Math.Programming.Dsl: eval :: Num a => LinearExpression a a -> a
- Math.Programming.Dsl: exprSum :: Num a => [LinearExpression a b] -> LinearExpression a b
- Math.Programming.Dsl: infixl 6 .-.
- Math.Programming.Dsl: infixl 7 ./#
- Math.Programming.Dsl: nameOf :: (Monad m, Nameable m a) => a -> m String
- Math.Programming.Dsl: named :: (Monad m, Nameable m a) => m a -> String -> m a
- Math.Programming.Dsl: simplify :: (Ord b, Num a) => LinearExpression a b -> LinearExpression a b
- Math.Programming.Dsl: var :: Num a => b -> LinearExpression a b
- Math.Programming.Dsl: varSum :: Num a => [b] -> LinearExpression a b
- Math.Programming.Types: -- opaque values, but instances may expose more details.
- Math.Programming.Types: -- | The type of objectives in the model. <a>LPMonad</a> treats these as
- Math.Programming.Types: LinearExpression :: [(a, b)] -> a -> LinearExpression a b
- Math.Programming.Types: class (LPMonad m) => IPMonad m
- Math.Programming.Types: class (Monad m, Show (Numeric m), RealFrac (Numeric m)) => LPMonad m where {
- Math.Programming.Types: class Nameable m a
- Math.Programming.Types: data LinearExpression a b
- Math.Programming.Types: data family Objective m :: *;
- Math.Programming.Types: getDualValue :: LPMonad m => Constraint m -> m (Numeric m)
- Math.Programming.Types: getName :: Nameable m a => a -> m String
- Math.Programming.Types: instance (GHC.Read.Read a, GHC.Read.Read b) => GHC.Read.Read (Math.Programming.Types.LinearExpression a b)
- Math.Programming.Types: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Math.Programming.Types.LinearExpression a b)
- Math.Programming.Types: instance Data.Bifunctor.Bifunctor Math.Programming.Types.LinearExpression
- Math.Programming.Types: instance Data.Foldable.Foldable (Math.Programming.Types.LinearExpression a)
- Math.Programming.Types: instance Data.Traversable.Traversable (Math.Programming.Types.LinearExpression a)
- Math.Programming.Types: instance GHC.Base.Functor (Math.Programming.Types.LinearExpression a)
- Math.Programming.Types: instance GHC.Num.Num a => GHC.Base.Monoid (Math.Programming.Types.LinearExpression a b)
- Math.Programming.Types: instance GHC.Num.Num a => GHC.Base.Semigroup (Math.Programming.Types.LinearExpression a b)
- Math.Programming.Types: instance GHC.Read.Read b => GHC.Read.Read (Math.Programming.Types.Bounds b)
- Math.Programming.Types: instance GHC.Show.Show b => GHC.Show.Show (Math.Programming.Types.Bounds b)
- Math.Programming.Types: instance Math.Programming.Types.LPMonad m => Math.Programming.Types.Nameable m (Math.Programming.Types.Constraint m)
- Math.Programming.Types: instance Math.Programming.Types.LPMonad m => Math.Programming.Types.Nameable m (Math.Programming.Types.Objective m)
- Math.Programming.Types: instance Math.Programming.Types.LPMonad m => Math.Programming.Types.Nameable m (Math.Programming.Types.Variable m)
- Math.Programming.Types: removeConstraint :: LPMonad m => Constraint m -> m ()
- Math.Programming.Types: removeVariable :: LPMonad m => Variable m -> m ()
- Math.Programming.Types: setName :: Nameable m a => a -> String -> m ()
- Math.Programming.Types: type family Numeric m :: *;
- Math.Programming.Types: }
+ Math.Programming: (*.) :: Num a => a -> b -> LinExpr a b
+ Math.Programming: (.*) :: Num a => b -> a -> LinExpr a b
+ Math.Programming: (./) :: Fractional a => b -> a -> LinExpr a b
+ Math.Programming: (.<=) :: MonadLP v c o m => Expr v -> Double -> m c
+ Math.Programming: (.==) :: MonadLP v c o m => Expr v -> Double -> m c
+ Math.Programming: (.>=) :: MonadLP v c o m => Expr v -> Double -> m c
+ Math.Programming: (<=.) :: MonadLP v c o m => Double -> Expr v -> m c
+ Math.Programming: (==.) :: MonadLP v c o m => Double -> Expr v -> m c
+ Math.Programming: (>=.) :: MonadLP v c o m => Double -> Expr v -> m c
+ Math.Programming: LinExpr :: ![(a, b)] -> !a -> LinExpr a b
+ Math.Programming: class MonadLP v c o m => MonadIP v c o m | m -> v c o
+ Math.Programming: class Monad m => MonadLP v c o m | m -> v c o
+ Math.Programming: data LinExpr a b
+ Math.Programming: deleteConstraint :: MonadLP v c o m => c -> m ()
+ Math.Programming: deleteObjective :: MonadLP v c o m => o -> m ()
+ Math.Programming: deleteVariable :: MonadLP v c o m => v -> m ()
+ Math.Programming: esum :: Num a => Foldable t => t (LinExpr a b) -> LinExpr a b
+ Math.Programming: formatExpr :: MonadLP v c o m => Expr v -> m Text
+ Math.Programming: getConstraintValue :: MonadLP v c o m => c -> m Double
+ Math.Programming: scale :: Num a => a -> LinExpr a b -> LinExpr a b
+ Math.Programming: vsum :: Num a => [b] -> LinExpr a b
+ Math.Programming: withConstraintName :: MonadLP v c o m => m c -> Text -> m c
+ Math.Programming: withObjectiveName :: MonadLP v c o m => m o -> Text -> m o
+ Math.Programming: withVariableName :: MonadLP v c o m => m v -> Text -> m v
+ Math.Programming.Dsl: (.<=) :: MonadLP v c o m => Expr v -> Double -> m c
+ Math.Programming.Dsl: (.==) :: MonadLP v c o m => Expr v -> Double -> m c
+ Math.Programming.Dsl: (.>=) :: MonadLP v c o m => Expr v -> Double -> m c
+ Math.Programming.Dsl: (<=.) :: MonadLP v c o m => Double -> Expr v -> m c
+ Math.Programming.Dsl: (==.) :: MonadLP v c o m => Double -> Expr v -> m c
+ Math.Programming.Dsl: (>=.) :: MonadLP v c o m => Double -> Expr v -> m c
+ Math.Programming.Dsl: formatExpr :: MonadLP v c o m => Expr v -> m Text
+ Math.Programming.Dsl: formatExpr' :: Monad m => (v -> m Text) -> Expr v -> m Text
+ Math.Programming.Dsl: withConstraintName :: MonadLP v c o m => m c -> Text -> m c
+ Math.Programming.Dsl: withObjectiveName :: MonadLP v c o m => m o -> Text -> m o
+ Math.Programming.Dsl: withVariableName :: MonadLP v c o m => m v -> Text -> m v
+ Math.Programming.LinExpr: (*.) :: Num a => a -> b -> LinExpr a b
+ Math.Programming.LinExpr: (.*) :: Num a => b -> a -> LinExpr a b
+ Math.Programming.LinExpr: (.+.) :: Num a => LinExpr a b -> LinExpr a b -> LinExpr a b
+ Math.Programming.LinExpr: (.-.) :: Num a => LinExpr a b -> LinExpr a b -> LinExpr a b
+ Math.Programming.LinExpr: (./) :: Fractional a => b -> a -> LinExpr a b
+ Math.Programming.LinExpr: LinExpr :: ![(a, b)] -> !a -> LinExpr a b
+ Math.Programming.LinExpr: con :: a -> LinExpr a b
+ Math.Programming.LinExpr: data LinExpr a b
+ Math.Programming.LinExpr: esum :: Num a => Foldable t => t (LinExpr a b) -> LinExpr a b
+ Math.Programming.LinExpr: eval :: Num a => LinExpr a a -> a
+ Math.Programming.LinExpr: infixl 6 .-.
+ Math.Programming.LinExpr: infixl 7 ./
+ Math.Programming.LinExpr: instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Math.Programming.LinExpr.LinExpr a b)
+ Math.Programming.LinExpr: instance (GHC.Read.Read a, GHC.Read.Read b) => GHC.Read.Read (Math.Programming.LinExpr.LinExpr a b)
+ Math.Programming.LinExpr: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Math.Programming.LinExpr.LinExpr a b)
+ Math.Programming.LinExpr: instance Data.Foldable.Foldable (Math.Programming.LinExpr.LinExpr a)
+ Math.Programming.LinExpr: instance Data.Traversable.Traversable (Math.Programming.LinExpr.LinExpr a)
+ Math.Programming.LinExpr: instance GHC.Base.Functor (Math.Programming.LinExpr.LinExpr a)
+ Math.Programming.LinExpr: instance GHC.Num.Num a => GHC.Base.Monoid (Math.Programming.LinExpr.LinExpr a b)
+ Math.Programming.LinExpr: instance GHC.Num.Num a => GHC.Base.Semigroup (Math.Programming.LinExpr.LinExpr a b)
+ Math.Programming.LinExpr: scale :: Num a => a -> LinExpr a b -> LinExpr a b
+ Math.Programming.LinExpr: simplify :: (Num a, Ord b) => LinExpr a b -> LinExpr a b
+ Math.Programming.LinExpr: var :: Num a => b -> LinExpr a b
+ Math.Programming.LinExpr: vsum :: Num a => [b] -> LinExpr a b
+ Math.Programming.Types: class MonadLP v c o m => MonadIP v c o m | m -> v c o
+ Math.Programming.Types: class Monad m => MonadLP v c o m | m -> v c o
+ Math.Programming.Types: compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
+ Math.Programming.Types: deleteConstraint :: MonadLP v c o m => c -> m ()
+ Math.Programming.Types: deleteObjective :: MonadLP v c o m => o -> m ()
+ Math.Programming.Types: deleteVariable :: MonadLP v c o m => v -> m ()
+ Math.Programming.Types: getConstraintValue :: MonadLP v c o m => c -> m Double
+ Math.Programming.Types: instance (Math.Programming.Types.MonadLP v c o m, GHC.Base.Monoid w) => Math.Programming.Types.MonadLP v c o (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
+ Math.Programming.Types: instance (Math.Programming.Types.MonadLP v c o m, GHC.Base.Monoid w) => Math.Programming.Types.MonadLP v c o (Control.Monad.Trans.Writer.Lazy.WriterT w m)
+ Math.Programming.Types: instance GHC.Read.Read Math.Programming.Types.Bounds
+ Math.Programming.Types: instance GHC.Show.Show Math.Programming.Types.Bounds
+ Math.Programming.Types: instance Math.Programming.Types.MonadIP v c o m => Math.Programming.Types.MonadIP v c o (Control.Monad.Trans.Reader.ReaderT r m)
+ Math.Programming.Types: instance Math.Programming.Types.MonadIP v c o m => Math.Programming.Types.MonadIP v c o (Control.Monad.Trans.State.Lazy.StateT s m)
+ Math.Programming.Types: instance Math.Programming.Types.MonadLP v c o m => Math.Programming.Types.MonadLP v c o (Control.Monad.Trans.Reader.ReaderT r m)
+ Math.Programming.Types: instance Math.Programming.Types.MonadLP v c o m => Math.Programming.Types.MonadLP v c o (Control.Monad.Trans.State.Lazy.StateT s m)
+ Math.Programming.Types: lift2 :: (MonadTrans t, Monad m) => (a -> b -> m c) -> a -> b -> t m c
- Math.Programming: (.+.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
+ Math.Programming: (.+.) :: Num a => LinExpr a b -> LinExpr a b -> LinExpr a b
- Math.Programming: (.-.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
+ Math.Programming: (.-.) :: Num a => LinExpr a b -> LinExpr a b -> LinExpr a b
- Math.Programming: (.<=.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
+ Math.Programming: (.<=.) :: MonadLP v c o m => Expr v -> Expr v -> m c
- Math.Programming: (.==.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
+ Math.Programming: (.==.) :: MonadLP v c o m => Expr v -> Expr v -> m c
- Math.Programming: (.>=.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
+ Math.Programming: (.>=.) :: MonadLP v c o m => Expr v -> Expr v -> m c
- Math.Programming: Free :: Bounds b
+ Math.Programming: Free :: Bounds
- Math.Programming: Interval :: b -> b -> Bounds b
+ Math.Programming: Interval :: Double -> Double -> Bounds
- Math.Programming: NonNegativeReals :: Bounds b
+ Math.Programming: NonNegativeReals :: Bounds
- Math.Programming: NonPositiveReals :: Bounds b
+ Math.Programming: NonPositiveReals :: Bounds
- Math.Programming: addConstraint :: LPMonad m => Inequality (LinearExpression (Numeric m) (Variable m)) -> m (Constraint m)
+ Math.Programming: addConstraint :: MonadLP v c o m => Inequality (Expr v) -> m c
- Math.Programming: addObjective :: LPMonad m => LinearExpression (Numeric m) (Variable m) -> m (Objective m)
+ Math.Programming: addObjective :: MonadLP v c o m => Expr v -> m o
- Math.Programming: addVariable :: LPMonad m => m (Variable m)
+ Math.Programming: addVariable :: MonadLP v c o m => m v
- Math.Programming: asKind :: IPMonad m => m (Variable m) -> Domain -> m (Variable m)
+ Math.Programming: asKind :: MonadIP v c o m => m v -> Domain -> m v
- Math.Programming: binary :: IPMonad m => m (Variable m)
+ Math.Programming: binary :: MonadIP v c o m => m v
- Math.Programming: bounded :: LPMonad m => Numeric m -> Numeric m -> m (Variable m)
+ Math.Programming: bounded :: MonadLP v c o m => Double -> Double -> m v
- Math.Programming: con :: Num a => a -> LinearExpression a b
+ Math.Programming: con :: a -> LinExpr a b
- Math.Programming: data Bounds b
+ Math.Programming: data Bounds
- Math.Programming: eval :: Num a => LinearExpression a a -> a
+ Math.Programming: eval :: Num a => LinExpr a a -> a
- Math.Programming: evalExpr :: LPMonad m => Expr m -> m (Numeric m)
+ Math.Programming: evalExpr :: MonadLP v c o m => Expr v -> m Double
- Math.Programming: free :: LPMonad m => m (Variable m)
+ Math.Programming: free :: MonadLP v c o m => m v
- Math.Programming: getConstraintName :: LPMonad m => Constraint m -> m String
+ Math.Programming: getConstraintName :: MonadLP v c o m => c -> m Text
- Math.Programming: getObjectiveName :: LPMonad m => Objective m -> m String
+ Math.Programming: getObjectiveName :: MonadLP v c o m => o -> m Text
- Math.Programming: getObjectiveSense :: LPMonad m => Objective m -> m Sense
+ Math.Programming: getObjectiveSense :: MonadLP v c o m => o -> m Sense
- Math.Programming: getObjectiveValue :: LPMonad m => Objective m -> m (Numeric m)
+ Math.Programming: getObjectiveValue :: MonadLP v c o m => o -> m Double
- Math.Programming: getRelativeMIPGap :: IPMonad m => m Double
+ Math.Programming: getRelativeMIPGap :: MonadIP v c o m => m Double
- Math.Programming: getTimeout :: LPMonad m => m Double
+ Math.Programming: getTimeout :: MonadLP v c o m => m Double
- Math.Programming: getVariableBounds :: LPMonad m => Variable m -> m (Bounds (Numeric m))
+ Math.Programming: getVariableBounds :: MonadLP v c o m => v -> m Bounds
- Math.Programming: getVariableDomain :: IPMonad m => Variable m -> m Domain
+ Math.Programming: getVariableDomain :: MonadIP v c o m => v -> m Domain
- Math.Programming: getVariableName :: LPMonad m => Variable m -> m String
+ Math.Programming: getVariableName :: MonadLP v c o m => v -> m Text
- Math.Programming: getVariableValue :: LPMonad m => Variable m -> m (Numeric m)
+ Math.Programming: getVariableValue :: MonadLP v c o m => v -> m Double
- Math.Programming: infix 4 .==.
+ Math.Programming: infix 4 .>=
- Math.Programming: infixl 6 .-#
+ Math.Programming: infixl 6 .-.
- Math.Programming: infixl 7 ./#
+ Math.Programming: infixl 7 ./
- Math.Programming: integer :: IPMonad m => m (Variable m)
+ Math.Programming: integer :: MonadIP v c o m => m v
- Math.Programming: maximize :: LPMonad m => Expr m -> m (Objective m)
+ Math.Programming: maximize :: MonadLP v c o m => Expr v -> m o
- Math.Programming: minimize :: LPMonad m => Expr m -> m (Objective m)
+ Math.Programming: minimize :: MonadLP v c o m => Expr v -> m o
- Math.Programming: nonNeg :: LPMonad m => m (Variable m)
+ Math.Programming: nonNeg :: MonadLP v c o m => m v
- Math.Programming: nonNegInteger :: IPMonad m => m (Variable m)
+ Math.Programming: nonNegInteger :: MonadIP v c o m => m v
- Math.Programming: nonPos :: LPMonad m => m (Variable m)
+ Math.Programming: nonPos :: MonadLP v c o m => m v
- Math.Programming: nonPosInteger :: IPMonad m => m (Variable m)
+ Math.Programming: nonPosInteger :: MonadIP v c o m => m v
- Math.Programming: optimizeIP :: IPMonad m => m SolutionStatus
+ Math.Programming: optimizeIP :: MonadIP v c o m => m SolutionStatus
- Math.Programming: optimizeLP :: LPMonad m => m SolutionStatus
+ Math.Programming: optimizeLP :: MonadLP v c o m => m SolutionStatus
- Math.Programming: setConstraintName :: LPMonad m => Constraint m -> String -> m ()
+ Math.Programming: setConstraintName :: MonadLP v c o m => c -> Text -> m ()
- Math.Programming: setObjectiveName :: LPMonad m => Objective m -> String -> m ()
+ Math.Programming: setObjectiveName :: MonadLP v c o m => o -> Text -> m ()
- Math.Programming: setObjectiveSense :: LPMonad m => Objective m -> Sense -> m ()
+ Math.Programming: setObjectiveSense :: MonadLP v c o m => o -> Sense -> m ()
- Math.Programming: setRelativeMIPGap :: IPMonad m => Double -> m ()
+ Math.Programming: setRelativeMIPGap :: MonadIP v c o m => Double -> m ()
- Math.Programming: setTimeout :: LPMonad m => Double -> m ()
+ Math.Programming: setTimeout :: MonadLP v c o m => Double -> m ()
- Math.Programming: setVariableBounds :: LPMonad m => Variable m -> Bounds (Numeric m) -> m ()
+ Math.Programming: setVariableBounds :: MonadLP v c o m => v -> Bounds -> m ()
- Math.Programming: setVariableDomain :: IPMonad m => Variable m -> Domain -> m ()
+ Math.Programming: setVariableDomain :: MonadIP v c o m => v -> Domain -> m ()
- Math.Programming: setVariableName :: LPMonad m => Variable m -> String -> m ()
+ Math.Programming: setVariableName :: MonadLP v c o m => v -> Text -> m ()
- Math.Programming: simplify :: (Ord b, Num a) => LinearExpression a b -> LinearExpression a b
+ Math.Programming: simplify :: (Num a, Ord b) => LinExpr a b -> LinExpr a b
- Math.Programming: type Expr m = LinearExpression (Numeric m) (Variable m)
+ Math.Programming: type Expr = LinExpr Double
- Math.Programming: var :: Num a => b -> LinearExpression a b
+ Math.Programming: var :: Num a => b -> LinExpr a b
- Math.Programming: within :: LPMonad m => m (Variable m) -> Bounds (Numeric m) -> m (Variable m)
+ Math.Programming: within :: MonadLP v c o m => m v -> Bounds -> m v
- Math.Programming.Dsl: (.<=.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
+ Math.Programming.Dsl: (.<=.) :: MonadLP v c o m => Expr v -> Expr v -> m c
- Math.Programming.Dsl: (.==.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
+ Math.Programming.Dsl: (.==.) :: MonadLP v c o m => Expr v -> Expr v -> m c
- Math.Programming.Dsl: (.>=.) :: LPMonad m => Expr m -> Expr m -> m (Constraint m)
+ Math.Programming.Dsl: (.>=.) :: MonadLP v c o m => Expr v -> Expr v -> m c
- Math.Programming.Dsl: asKind :: IPMonad m => m (Variable m) -> Domain -> m (Variable m)
+ Math.Programming.Dsl: asKind :: MonadIP v c o m => m v -> Domain -> m v
- Math.Programming.Dsl: binary :: IPMonad m => m (Variable m)
+ Math.Programming.Dsl: binary :: MonadIP v c o m => m v
- Math.Programming.Dsl: bounded :: LPMonad m => Numeric m -> Numeric m -> m (Variable m)
+ Math.Programming.Dsl: bounded :: MonadLP v c o m => Double -> Double -> m v
- Math.Programming.Dsl: evalExpr :: LPMonad m => Expr m -> m (Numeric m)
+ Math.Programming.Dsl: evalExpr :: MonadLP v c o m => Expr v -> m Double
- Math.Programming.Dsl: free :: LPMonad m => m (Variable m)
+ Math.Programming.Dsl: free :: MonadLP v c o m => m v
- Math.Programming.Dsl: infix 4 .==.
+ Math.Programming.Dsl: infix 4 .==
- Math.Programming.Dsl: integer :: IPMonad m => m (Variable m)
+ Math.Programming.Dsl: integer :: MonadIP v c o m => m v
- Math.Programming.Dsl: maximize :: LPMonad m => Expr m -> m (Objective m)
+ Math.Programming.Dsl: maximize :: MonadLP v c o m => Expr v -> m o
- Math.Programming.Dsl: minimize :: LPMonad m => Expr m -> m (Objective m)
+ Math.Programming.Dsl: minimize :: MonadLP v c o m => Expr v -> m o
- Math.Programming.Dsl: nonNeg :: LPMonad m => m (Variable m)
+ Math.Programming.Dsl: nonNeg :: MonadLP v c o m => m v
- Math.Programming.Dsl: nonNegInteger :: IPMonad m => m (Variable m)
+ Math.Programming.Dsl: nonNegInteger :: MonadIP v c o m => m v
- Math.Programming.Dsl: nonPos :: LPMonad m => m (Variable m)
+ Math.Programming.Dsl: nonPos :: MonadLP v c o m => m v
- Math.Programming.Dsl: nonPosInteger :: IPMonad m => m (Variable m)
+ Math.Programming.Dsl: nonPosInteger :: MonadIP v c o m => m v
- Math.Programming.Dsl: within :: LPMonad m => m (Variable m) -> Bounds (Numeric m) -> m (Variable m)
+ Math.Programming.Dsl: within :: MonadLP v c o m => m v -> Bounds -> m v
- Math.Programming.Types: Free :: Bounds b
+ Math.Programming.Types: Free :: Bounds
- Math.Programming.Types: Interval :: b -> b -> Bounds b
+ Math.Programming.Types: Interval :: Double -> Double -> Bounds
- Math.Programming.Types: NonNegativeReals :: Bounds b
+ Math.Programming.Types: NonNegativeReals :: Bounds
- Math.Programming.Types: NonPositiveReals :: Bounds b
+ Math.Programming.Types: NonPositiveReals :: Bounds
- Math.Programming.Types: addConstraint :: LPMonad m => Inequality (LinearExpression (Numeric m) (Variable m)) -> m (Constraint m)
+ Math.Programming.Types: addConstraint :: MonadLP v c o m => Inequality (Expr v) -> m c
- Math.Programming.Types: addObjective :: LPMonad m => LinearExpression (Numeric m) (Variable m) -> m (Objective m)
+ Math.Programming.Types: addObjective :: MonadLP v c o m => Expr v -> m o
- Math.Programming.Types: addVariable :: LPMonad m => m (Variable m)
+ Math.Programming.Types: addVariable :: MonadLP v c o m => m v
- Math.Programming.Types: data Bounds b
+ Math.Programming.Types: data Bounds
- Math.Programming.Types: getConstraintName :: LPMonad m => Constraint m -> m String
+ Math.Programming.Types: getConstraintName :: MonadLP v c o m => c -> m Text
- Math.Programming.Types: getObjectiveName :: LPMonad m => Objective m -> m String
+ Math.Programming.Types: getObjectiveName :: MonadLP v c o m => o -> m Text
- Math.Programming.Types: getObjectiveSense :: LPMonad m => Objective m -> m Sense
+ Math.Programming.Types: getObjectiveSense :: MonadLP v c o m => o -> m Sense
- Math.Programming.Types: getObjectiveValue :: LPMonad m => Objective m -> m (Numeric m)
+ Math.Programming.Types: getObjectiveValue :: MonadLP v c o m => o -> m Double
- Math.Programming.Types: getRelativeMIPGap :: IPMonad m => m Double
+ Math.Programming.Types: getRelativeMIPGap :: MonadIP v c o m => m Double
- Math.Programming.Types: getTimeout :: LPMonad m => m Double
+ Math.Programming.Types: getTimeout :: MonadLP v c o m => m Double
- Math.Programming.Types: getVariableBounds :: LPMonad m => Variable m -> m (Bounds (Numeric m))
+ Math.Programming.Types: getVariableBounds :: MonadLP v c o m => v -> m Bounds
- Math.Programming.Types: getVariableDomain :: IPMonad m => Variable m -> m Domain
+ Math.Programming.Types: getVariableDomain :: MonadIP v c o m => v -> m Domain
- Math.Programming.Types: getVariableName :: LPMonad m => Variable m -> m String
+ Math.Programming.Types: getVariableName :: MonadLP v c o m => v -> m Text
- Math.Programming.Types: getVariableValue :: LPMonad m => Variable m -> m (Numeric m)
+ Math.Programming.Types: getVariableValue :: MonadLP v c o m => v -> m Double
- Math.Programming.Types: optimizeIP :: IPMonad m => m SolutionStatus
+ Math.Programming.Types: optimizeIP :: MonadIP v c o m => m SolutionStatus
- Math.Programming.Types: optimizeLP :: LPMonad m => m SolutionStatus
+ Math.Programming.Types: optimizeLP :: MonadLP v c o m => m SolutionStatus
- Math.Programming.Types: setConstraintName :: LPMonad m => Constraint m -> String -> m ()
+ Math.Programming.Types: setConstraintName :: MonadLP v c o m => c -> Text -> m ()
- Math.Programming.Types: setObjectiveName :: LPMonad m => Objective m -> String -> m ()
+ Math.Programming.Types: setObjectiveName :: MonadLP v c o m => o -> Text -> m ()
- Math.Programming.Types: setObjectiveSense :: LPMonad m => Objective m -> Sense -> m ()
+ Math.Programming.Types: setObjectiveSense :: MonadLP v c o m => o -> Sense -> m ()
- Math.Programming.Types: setRelativeMIPGap :: IPMonad m => Double -> m ()
+ Math.Programming.Types: setRelativeMIPGap :: MonadIP v c o m => Double -> m ()
- Math.Programming.Types: setTimeout :: LPMonad m => Double -> m ()
+ Math.Programming.Types: setTimeout :: MonadLP v c o m => Double -> m ()
- Math.Programming.Types: setVariableBounds :: LPMonad m => Variable m -> Bounds (Numeric m) -> m ()
+ Math.Programming.Types: setVariableBounds :: MonadLP v c o m => v -> Bounds -> m ()
- Math.Programming.Types: setVariableDomain :: IPMonad m => Variable m -> Domain -> m ()
+ Math.Programming.Types: setVariableDomain :: MonadIP v c o m => v -> Domain -> m ()
- Math.Programming.Types: setVariableName :: LPMonad m => Variable m -> String -> m ()
+ Math.Programming.Types: setVariableName :: MonadLP v c o m => v -> Text -> m ()
- Math.Programming.Types: type Expr m = LinearExpression (Numeric m) (Variable m)
+ Math.Programming.Types: type Expr = LinExpr Double

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for math-programming +## [0.5.0] -- 18 January 2023+### Changed++- The API has been made more consistent.+ ## [0.4.0] -- 5 July 2020 ### Added 
LICENSE view
@@ -1,4 +1,4 @@-Copyright Patrick Steele (c) 2018+Copyright (c) 2018-2023, Patrick Steele  All rights reserved. 
− README.md
@@ -1,11 +0,0 @@-# math-programming--A math programming library.--This library is designed to formulate and solve math programs, in-particular linear programs and mixed-integer linear programs.--This library alone is not sufficient to solve math programs; to do so,-a solver backend implementing the `LPMonad` or `IPMonad` classes is-required, such as the [GLPK-backend](https://github.com/prsteele/math-programming-glpk).
math-programming.cabal view
@@ -1,60 +1,50 @@-cabal-version:      1.12-name:               math-programming-version:            0.4.0-license:            BSD3-license-file:       LICENSE-copyright:          2018 Patrick Steele-maintainer:         steele.pat@gmail.com-author:             Patrick Steele-homepage:           https://github.com/prsteele/math-programming#readme-bug-reports:        https://github.com/prsteele/math-programming/issues-synopsis:           A library for formulating and solving math programs.-description:-    Please see the README on GitHub at <https://github.com/prsteele/math-programming#readme>--category:           Math-build-type:         Simple-extra-source-files:-    README.md-    ChangeLog.md+cabal-version:       2.4+name:                math-programming+version:             0.5.0+synopsis:            A library for formulating and solving math programs.+description:         Please see the <https://github.com/prsteele/math-programming/blob/main/README.md README on GitHub>.+bug-reports:         https://github.com/prsteele/math-programming/issues+license:             BSD-3-Clause+license-file:        LICENSE+author:              Patrick Steele+maintainer:          steele.pat@gmail.com+copyright:           2018-2023, Patrick Steele+category:            Math+build-type:          Simple+extra-source-files:  ChangeLog.md  source-repository head-    type:     git-    location: https://github.com/prsteele/math-programming+  type:     git+  location: https://github.com/prsteele/math-programming  library-    exposed-modules:-        Math.Programming-        Math.Programming.Dsl-        Math.Programming.Types--    hs-source-dirs:   src-    other-modules:    Paths_math_programming-    default-language: Haskell2010-    ghc-options:      -Wall-    build-depends:-        base >=4.7 && <5,-        containers >=0.6.0.1 && <0.7,-        mtl >=2.2.2 && <2.3,-        text >=1.2.3.1 && <1.3--test-suite math-programming-test-    type:             exitcode-stdio-1.0-    main-is:          Driver.hs-    hs-source-dirs:   test-    other-modules:-        Math.Programming.TestLinearExpression-        Paths_math_programming+  default-language:  Haskell2010+  hs-source-dirs:    src+  exposed-modules:   Math.Programming+                   , Math.Programming.Types+                   , Math.Programming.Dsl+                   , Math.Programming.LinExpr+  other-modules:+  ghc-options:       -Wall+  -- Restrictions on transformers due to https://hub.darcs.net/ross/transformers/issue/90+  build-depends:     base         <5+                   , containers   ^>=0.6+                   , exceptions   ^>=0.10+                   , mtl          ^>=2.2+                   , text         ^>=1.2+                   , transformers ^>=0.5 -    default-language: Haskell2010-    ghc-options:      -threaded -rtsopts -with-rtsopts=-N -Wall-    build-depends:-        base >=4.7 && <5,-        containers >=0.6.0.1 && <0.7,-        math-programming -any,-        mtl >=2.2.2 && <2.3,-        tasty >=1.2.3 && <1.3,-        tasty-discover >=4.2.1 && <4.3,-        tasty-hunit >=0.10.0.2 && <0.11,-        tasty-quickcheck >=0.10.1.1 && <0.11,-        text >=1.2.3.1 && <1.3+test-suite math-programming-test-suite+  default-language:  Haskell2010+  type:              exitcode-stdio-1.0+  main-is:           Spec.hs+  hs-source-dirs:    test+  ghc-options:       -threaded -with-rtsopts=-N -Wall+  other-modules:     Math.Programming.LinExprSpec+                   , Math.Programming.DslSpec+  build-depends:     math-programming+                   , base       <5+                   , hspec      ^>=2.8+                   , mtl        ^>=2.2+                   , QuickCheck ^>=2.14+                   , text       ^>=1.2
src/Math/Programming.hs view
@@ -1,273 +1,140 @@-{-| A library for modeling and solving linear and integer programs.--This library is merely a frontend to various solver backends. At the-time this was written, the only known supported backend is-<https://github.com/prsteele/math-programming-glpk GLPK>.--}+-- | A library for modeling and solving linear and integer programs.+--+-- This library is merely a frontend to various solver backends. At+-- the time this was written, the only known supported backend is+-- <https://github.com/prsteele/math-programming/blob/main/math-programming-glpk/README.md GLPK>.+--+-- This page includes a high-level overview of the model building DSL,+-- as well as a deeper dive into the core monadic interface. module Math.Programming-  ( -- * Math programs-    -- $mathprograms--    -- ** Linear programs-    LPMonad (..)-  , Expr-  , Bounds (..)-  , SolutionStatus (..)-  , Sense (..)--    -- ** Integer programs-  , IPMonad (..)-  , Domain (..)--    -- * Model-building DSL+  ( -- * Model-building DSL     -- $models      -- ** Creating variables-    -- $variables      -- *** Continuous variables-  , free-  , nonNeg-  , nonPos-  , bounded-  , within--    -- *** Integer variables-  , integer-  , binary-  , nonNegInteger-  , nonPosInteger-  , asKind--    -- ** Linear expressions-    -- $expressions-  , LinearExpression (..)-  , eval-  , simplify-  , var-  , con-  , exprSum-  , varSum--    -- *** Addition-    -- $addition-  , (.+.)-  , (@+@)-  , (.+@)-  , (@+.)-  , (@+#)-  , (#+@)-  , (#+.)-  , (.+#)--    -- *** Subtraction-    -- $subtraction-  , (.-.)-  , (@-@)-  , (.-@)-  , (@-.)-  , (@-#)-  , (#-@)-  , (#-.)-  , (.-#)+    free,+    bounded,+    nonNeg,+    nonPos, -    -- *** Multiplication-    -- $multiplication-  , (#*@)-  , (@*#)-  , (#*.)-  , (.*#)+    -- *** Discrete variables+    integer,+    binary,+    nonNegInteger,+    nonPosInteger, -    -- *** Division-    -- $division-  , (@/#)-  , (./#)+    -- *** Modifying variables+    -- $modifiers+    within,+    asKind, -    -- ** Constraints+    -- ** Creating constraints     -- $constraints-  , Inequality (..) +    -- *** Equality constraints+    (.==.),+    (==.),+    (.==),+     -- *** Less-than constraints-    -- $lt-  , (#<=@)-  , (#<=.)-  , (@<=#)-  , (@<=@)-  , (@<=.)-  , (.<=#)-  , (.<=@)-  , (.<=.)+    (.<=.),+    (<=.),+    (.<=),      -- *** Greater-than constraints-    -- $gt-  , (#>=@)-  , (#>=.)-  , (@>=#)-  , (@>=@)-  , (@>=.)-  , (.>=#)-  , (.>=@)-  , (.>=.)+    (.>=.),+    (>=.),+    (.>=), -  -- *** Equality constraints-  -- $eq-  , (#==@)-  , (#==.)-  , (@==#)-  , (@==@)-  , (@==.)-  , (.==#)-  , (.==@)-  , (.==.)+    -- ** Creating objectives+    minimize,+    maximize, -    -- ** Specifying objectives-  , minimize-  , maximize+    -- ** Creating linear expressions+    -- $expressions+    var,+    con,+    (.*),+    (*.),+    (.+.),+    (.-.),+    (./),+    eval,+    simplify,+    vsum,+    esum,+    scale, -    -- ** Utilities-  , evalExpr-  , named-  , nameOf-  ) where+    -- * Math programs+    -- $mathprograms -import           Math.Programming.Dsl-import           Math.Programming.Types+    -- ** Linear programs+    MonadLP (..), --- $mathprograms------ The 'LPMonad' provides all the primitives necessary to formulate--- and solve linear programs; the 'IPMonad' provides the same for--- integer programs. However, you should not often need to use these--- APIs directly, as we provide more user-friendly functions wrapping--- these low-level functions below.+    -- ** Integer programs+    MonadIP (..),+    Domain (..), --- $models------ The functions in the 'LPMonad' and 'IPMonad' typeclasses are--- designed to interface with low-level solver backends. We provide a--- cleaner interface in the following sections.+    -- * Other types and functions+    evalExpr,+    formatExpr,+    Expr,+    Bounds (..),+    SolutionStatus (..),+    Sense (..),+    Inequality (..),+    LinExpr (..), --- $variables------ 'LPMonad' provides 'addVariable' and 'setVariableBounds', and--- 'IPMonad' additionally provides 'setVariableDomain'. While--- sufficient to create your programs, you are encouraged to use the--- more natural functions below.+    -- * Naming model attributes+    withVariableName,+    withConstraintName,+    withObjectiveName,+  )+where --- $expressions------ The module 'Math.Programming.LinearExpression' provides operators--- to build up 'LinearExpression' objects using declared variables.+import Math.Programming.Dsl+import Math.Programming.LinExpr+import Math.Programming.Types --- $addition------ We can summarize the addition operators with the table+-- $introduction ----- +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         | '+'    | '#+@'  | '#+.'            |--- +-----------------+--------+--------+------------------+--- |Variable         | '@+#'  | '@+@'  | '@+.'            |--- +-----------------+--------+--------+------------------+--- |Expression       | '.+#'  | '.+@'  | '.+.'            |--- +-----------------+--------+--------+------------------++-- This library provides a monadic interface for building and solving+-- linear and integer programs. --- $subtraction------ We can summarize the subtraction operators with the table+-- $models ----- +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         | '-'    | '#-@'  | '#-.'            |--- +-----------------+--------+--------+------------------+--- |Variable         | '@-#'  | '@-@'  | '@-.'            |--- +-----------------+--------+--------+------------------+--- |Expression       | '.-#'  | '.-@'  | '.-.'            |--- +-----------------+--------+--------+------------------++-- We provide a monadic DSL for specifying math programs. This DSL+-- builds up programs statefully, rather than building some pure,+-- abstract representation of a math program. --- $multiplication------ We can summarize the multiplication operators with the table------ +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         | '*'    | '#*@'  | '#*.'            |--- +-----------------+--------+--------+------------------+--- |Variable         | '@*#'  |        |                  |--- +-----------------+--------+--------+------------------+--- |Expression       | '.*#'  |        |                  |--- +-----------------+--------+--------+------------------+------ As there are few possibilities for valid multiplication, it can be--- convenient to define e.g. @.*@ or some other short operator as an--- alias for '#*@'.+-- $modifiers+-- Regardless of the helper functions used above to create a+-- variable, you can modify its behavior using the following+-- modifiers. --- $division------ We can summarize the multiplication operators with the table------ +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         | '/'    |        |                  |--- +-----------------+--------+--------+------------------+--- |Variable         | '@/#'  |        |                  |--- +-----------------+--------+--------+------------------+--- |Expression       | './#'  |        |                  |--- +-----------------+--------+--------+------------------++-- $expressions ----- As there are few possibilities for valid division, it--- can be convenient to define e.g. @./@ or some other short operator--- as an alias for '@/#'.+-- A @'LinExpr' a b@ is a linear expression over variables of type @b@+-- with coefficients of type @a@ (typically 'Double'.) We provide a+-- number of operators to build up linear expressions naturally. The+-- mnemonic is that @.@ characters point to expressions.  -- $constraints ----- The 'LPMonad' provides the 'addConstraint' function. However, you--- will typically use the operators below to directly apply--- constraints to the model. We follow the same conventions as with--- our arithmetic operators.---- $lt------ We can summarize the various inquality operators in the following table.------ +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         |        | '#<=@' | '#<=.'           |--- +-----------------+--------+--------+------------------+--- |Variable         | '@<=#' | '@<=@' | '@<=.'           |--- +-----------------+--------+--------+------------------+--- |Expression       | '.<=#' | '.<=@' | '.<=.'           |--- +-----------------+--------+--------+------------------+---- $gt------ We can summarize the various inquality operators in the following table.+-- An @'Inequality' a@ is an inequality over the type @a@, which in+-- turn is typically an @'Expr' v@ for some variable type @v@. Despite+-- the name, 'Inequality' can also represent equality constraints+-- directly. ----- +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         |        | '#>=@' | '#>=.'           |--- +-----------------+--------+--------+------------------+--- |Variable         | '@>=#' | '@>=@' | '@>=.'           |--- +-----------------+--------+--------+------------------+--- |Expression       | '.>=#' | '.>=@' | '.>=.'           |--- +-----------------+--------+--------+------------------++-- As an alternative to constructing an inequality and passing it to+-- 'addConstraint', we can use the convenience operators below. Since+-- linear programming constraints often involve constant bounds, we+-- offer operators specialized for both expressions and constants. The+-- mnemonic is that @.@ characters point to expressions --- $eq------ We can summarize the various inquality operators in the following table.+-- $mathprograms ----- +-----------------+--------+--------+------------------+--- |                 |Constant|Variable|    Expression    |--- +-----------------+--------+--------+------------------+--- |Constant         |        | '#==@' | '#==.'           |--- +-----------------+--------+--------+------------------+--- |Variable         | '@==#' | '@==@' | '@==.'           |--- +-----------------+--------+--------+------------------+--- |Expression       | '.==#' | '.==@' | '.==.'           |--- +-----------------+--------+--------+------------------++-- The 'MonadLP' and 'MonadIP' classes provide low-level APIs for+-- defining linear and integer programs, respectively, although the+-- high-level DSL will typically be easier to work with.
src/Math/Programming/Dsl.hs view
@@ -1,42 +1,47 @@-module Math.Programming.Dsl where+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-} -import           Data.Bifunctor-import           Data.List              (sortOn)+module Math.Programming.Dsl where -import           Math.Programming.Types+import Data.Functor+import qualified Data.Text as T+import Math.Programming.LinExpr+import Math.Programming.Types+import Text.Printf  -- | Create an objective to be minimized.-minimize :: LPMonad m => Expr m -> m (Objective m)+minimize :: MonadLP v c o m => Expr v -> m o minimize objectiveExpr = do   objective <- addObjective objectiveExpr   setObjectiveSense objective Minimization   pure objective  -- | Create an objective to be maximized.-maximize :: LPMonad m => Expr m -> m (Objective m)+maximize :: MonadLP v c o m => Expr v -> m o maximize objectiveExpr = do   objective <- addObjective objectiveExpr   setObjectiveSense objective Maximization   pure objective  -- | Get the value of a linear expression in the current solution.-evalExpr :: LPMonad m => Expr m -> m (Numeric m)-evalExpr expr = traverse getVariableValue expr >>= return . eval+evalExpr :: MonadLP v c o m => Expr v -> m Double+evalExpr expr = traverse getVariableValue expr <&> eval  -- | Create a new free variable.-free :: LPMonad m => m (Variable m)+free :: MonadLP v c o m => m v free = addVariable `within` Free  -- | Create a new non-negative variable.-nonNeg :: LPMonad m => m (Variable m)+nonNeg :: MonadLP v c o m => m v nonNeg = addVariable `within` NonNegativeReals  -- | Create a new non-positive variable.-nonPos :: LPMonad m => m (Variable m)+nonPos :: MonadLP v c o m => m v nonPos = addVariable `within` NonPositiveReals  -- | Create a new variable bounded between two values.-bounded :: LPMonad m => Numeric m -> Numeric m -> m (Variable m)+bounded :: MonadLP v c o m => Double -> Double -> m v bounded lo hi = within addVariable (Interval lo hi)  -- | Constrain a variable to take on certain values.@@ -44,28 +49,31 @@ -- This function is designed to be used as an infix operator, e.g. -- -- @--- 'addVariable' \``within`\` 'NonNegativeReals'+-- 'integer' \``within`\` 'Interval 3 7' -- @-within :: LPMonad m => m (Variable m) -> Bounds (Numeric m) -> m (Variable m)+--+-- creates an integer variable that can take on values 3, 4, 5, 6, or+-- 7.+within :: MonadLP v c o m => m v -> Bounds -> m v within makeVar bounds = do   variable <- makeVar   setVariableBounds variable bounds   pure variable  -- | Create an integer-valued variable.-integer :: IPMonad m => m (Variable m)-integer = addVariable `asKind` Integer+integer :: MonadIP v c o m => m v+integer = addVariable `asKind` Integer `within` Free  -- | Create a binary variable.-binary :: IPMonad m => m (Variable m)+binary :: MonadIP v c o m => m v binary = addVariable `asKind` Binary  -- | Create an integer-value variable that takes on non-negative values.-nonNegInteger :: IPMonad m => m (Variable m)+nonNegInteger :: MonadIP v c o m => m v nonNegInteger = addVariable `asKind` Integer `within` NonNegativeReals  -- | Create an integer-value variable that takes on non-positive values.-nonPosInteger :: IPMonad m => m (Variable m)+nonPosInteger :: MonadIP v c o m => m v nonPosInteger = addVariable `asKind` Integer `within` NonPositiveReals  -- | Set the type of a variable.@@ -73,202 +81,91 @@ -- This function is designed to be used as an infix operator, e.g. -- -- @--- 'addVariable' \``asKind`\` 'Binary'+-- 'free' \``asKind`\` 'Binary' -- @-asKind :: IPMonad m => m (Variable m) -> Domain -> m (Variable m)-asKind make domain = do+asKind :: MonadIP v c o m => m v -> Domain -> m v+asKind make dom = do   variable <- make-  setVariableDomain variable domain+  setVariableDomain variable dom   pure variable --- | Name a variable, constraint, or objective.------ This function is designed to be used as an infix operator, e.g.------ @--- 'free' \``named`\` "X_1"--- @-named :: (Monad m, Nameable m a) => m a -> String -> m a-named make name = do-  x <- make-  setName x name-  pure x+-- | A less-than or equal-to constraint+(.<=.) :: MonadLP v c o m => Expr v -> Expr v -> m c+(.<=.) x y = addConstraint $ Inequality LT x y --- | Retrieve the name of a variable, constraint, or objective.-nameOf :: (Monad m, Nameable m a) => a -> m String-nameOf = getName+-- | A less-than or equal-to constraint with a numeric left-hand side+(<=.) :: MonadLP v c o m => Double -> Expr v -> m c+(<=.) x y = con x .<=. y -(#+@) :: 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+-- | A less-than or equal-to constraint with a numeric right-hand side+(.<=) :: MonadLP v c o m => Expr v -> Double -> m c+(.<=) x y = x .<=. con 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     .+. 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+-- | A greater-than or equal-to constraint+(.>=.) :: MonadLP v c o m => Expr v -> Expr v -> m c+(.>=.) x y = addConstraint $ Inequality GT x y -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 ./#+-- | A greater-than or equal-to constraint with a numeric left-hand side+(>=.) :: MonadLP v c o m => Double -> Expr v -> m c+(>=.) x y = con x .>=. y --- | Combine equivalent terms by summing their coefficients.-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)+-- | A greater-than or equal-to constraint with a numeric right-hand side+(.>=) :: MonadLP v c o m => Expr v -> Double -> m c+(.>=) x y = x .>=. con y --- | Reduce an expression to its value.-eval :: Num a => LinearExpression a a -> a-eval (LinearExpression terms constant) = constant + sum (map (uncurry (*)) terms)+-- | An equality constraint+(.==.) :: MonadLP v c o m => Expr v -> Expr v -> m c+(.==.) x y = addConstraint $ Inequality EQ x y --- | Construct an expression representing a variable.-var :: Num a => b -> LinearExpression a b-var x = LinearExpression [(1, x)] 0+-- | An equality constraint with a numeric left-hand side+(==.) :: MonadLP v c o m => Double -> Expr v -> m c+(==.) x y = con x .==. y --- | Construct an expression representing a constant.-con :: Num a => a -> LinearExpression a b-con x = LinearExpression [] x+-- | An equality constraint with a numeric right-hand side+(.==) :: MonadLP v c o m => Expr v -> Double -> m c+(.==) x y = x .==. con y --- | Construct an expression by summing expressions.-exprSum :: Num a => [LinearExpression a b] -> LinearExpression a b-exprSum = mconcat+infix 4 <=. --- | Construct an expression by summing variables.-varSum :: Num a => [b] -> LinearExpression a b-varSum = mconcat . fmap var+infix 4 .<= -(#<=@) :: 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)+infix 4 .<=. -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 .==#-infix 4 .==@++infix 4 ==.++infix 4 .==+ infix 4 .==.++formatExpr :: MonadLP v c o m => Expr v -> m T.Text+formatExpr = formatExpr' getVariableName++formatExpr' :: Monad m => (v -> m T.Text) -> Expr v -> m T.Text+formatExpr' nameOf (LinExpr terms coef) = do+  names <- mapM (traverse nameOf) terms+  let strTerms = fmap (T.pack . uncurry (printf "%f * %s")) names+  pure $ T.intercalate " + " (strTerms <> [T.pack (show coef)])++withVariableName :: MonadLP v c o m => m v -> T.Text -> m v+withVariableName mv name = do+  v <- mv+  setVariableName v name+  pure v++withConstraintName :: MonadLP v c o m => m c -> T.Text -> m c+withConstraintName mc name = do+  c <- mc+  setConstraintName c name+  pure c++withObjectiveName :: MonadLP v c o m => m o -> T.Text -> m o+withObjectiveName mo name = do+  o <- mo+  setObjectiveName o name+  pure o
+ src/Math/Programming/LinExpr.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE TupleSections #-}++-- | Linear expressions of variables.+module Math.Programming.LinExpr where++import Data.List (foldl', sortOn)++-- | A linear expression.+--+-- Linear expressions contain symbolic variables of type @b@ and+-- numeric coefficients of type @a@. Often @a@ will be 'Double', and+-- @b@ will be whatever variable type your linear program uses.+data LinExpr a b+  = LinExpr ![(a, b)] !a+  deriving (Eq, Read, Show, Functor, Foldable, Traversable)++instance Num a => Semigroup (LinExpr a b) where+  (<>) = (.+.)++instance Num a => Monoid (LinExpr a b) where+  mempty = con 0++-- | Construct a term in a linear expression by multiplying a constant+-- by a variable.+(*.) :: Num a => a -> b -> LinExpr a b+(*.) x y = LinExpr [(x, y)] 0++infixl 7 .*++-- | Construct a term in a linear expression by multiplying a variable+-- by a constant.+(.*) :: Num a => b -> a -> LinExpr a b+(.*) = flip (*.)++infixl 7 *.++-- | Construct a term in a linear expression by dividing a variable by+-- a constant.+(./) :: Fractional a => b -> a -> LinExpr a b+(./) x y = x .* (1 / y)++infixl 7 ./++-- | Multiplication of linear expressions by a constant.+scale :: Num a => a -> LinExpr a b -> LinExpr a b+scale coef (LinExpr terms constant) = LinExpr terms' constant'+  where+    terms' = [(c * coef, x) | (c, x) <- terms]+    constant' = constant * coef++-- | Addition of linear expressions.+(.+.) :: Num a => LinExpr a b -> LinExpr a b -> LinExpr a b+(.+.) (LinExpr terms constant) (LinExpr terms' constant') =+  LinExpr (terms <> terms') (constant + constant')++infixl 6 .+.++-- | The difference of linear expressions.+(.-.) :: Num a => LinExpr a b -> LinExpr a b -> LinExpr a b+(.-.) x y = x .+. scale (-1) y++infixl 6 .-.++-- | A linear expression with a single variable term.+var :: Num a => b -> LinExpr a b+var x = LinExpr [(1, x)] 0++-- | A linear expression with only a constant term.+con :: a -> LinExpr a b+con = LinExpr []++-- | The sum of variable terms with coefficients of unity.+vsum :: Num a => [b] -> LinExpr a b+vsum = flip LinExpr 0 . fmap (1,)++-- | The sum of linear expressions.+esum :: Num a => Foldable t => t (LinExpr a b) -> LinExpr a b+esum = foldl' (.+.) mempty++-- | Reduce an expression to its value.+eval :: Num a => LinExpr a a -> a+eval (LinExpr terms constant) = constant + sum' (map (uncurry (*)) terms)+  where+    sum' = foldl' (+) 0++-- | Simplify an expression by grouping like terms.+simplify :: (Num a, Ord b) => LinExpr a b -> LinExpr a b+simplify (LinExpr terms constant) =+  LinExpr (foldr f [] (sortOn snd terms)) constant+  where+    f (c, x) [] = [(c, x)]+    f (c, x) ((c', x') : xs) =+      if x == x'+        then (c + c', x) : xs+        else (c, x) : (c', x') : xs
src/Math/Programming/Types.hs view
@@ -1,178 +1,287 @@-{-# LANGUAGE FlexibleContexts       #-}-{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses  #-}-{-# LANGUAGE TypeFamilies           #-}-module Math.Programming.Types where+{-# LANGUAGE UndecidableInstances #-} -import           Data.Bifunctor-import           Data.Traversable (fmapDefault, foldMapDefault)+-- | Data and class definitions for the core math programming+-- interface.+module Math.Programming.Types where --- | A convient shorthand for the type of linear expressions used in a--- given model.-type Expr m = LinearExpression (Numeric m) (Variable m)+import Control.Monad.Trans.Class+import Control.Monad.Trans.RWS+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State+import Control.Monad.Trans.Writer+import qualified Data.Text as T+import Math.Programming.LinExpr --- | A monad for formulating and solving linear programs.+-- | A linear program. ----- We manipulate linear programs and their settings using the--- 'Mutable' typeclass.-class (Monad m, Show (Numeric m), RealFrac (Numeric m)) => LPMonad m where-  -- | The numeric type used in the model.-  type Numeric m :: *--  -- | The type of variables in the model. 'LPMonad' treats these as-  -- opaque values, but instances may expose more details.-  data Variable m :: *--  -- | The type of constraints in the model. 'LPMonad' treats these-  -- as opaque values, but instances may expose more details.-  data Constraint m :: *--  -- | The type of objectives in the model. 'LPMonad' treats these-  -- as opaque values, but instances may expose more details.-  data Objective m :: *--  -- | Create a new decision variable in the model.+-- This is a monadic context for formulating and solving linear+-- programs. The types @v@, @c@, and @o@ refer to the types of+-- variables, constraints, and objectives, respectively, used by a+-- particular solver backend.+class Monad m => MonadLP v c o m | m -> v c o where+  -- | Add a new (free) variable to the model.   ---  -- This variable will be initialized to be a non-negative continuous-  -- variable.-  addVariable :: m (Variable m)+  -- See 'Math.Programming.Dsl.free', 'Math.Programming.Dsl.bounded',+  -- 'Math.Programming.Dsl.nonNeg', and 'Math.Programming.Dsl.nonPos'+  -- as higher-level alternatives.+  addVariable :: m v -  -- | Remove a decision variable from the model.-  ---  -- The variable cannot be used after being deleted.-  removeVariable :: Variable m -> m ()+  -- | Remove a variable from the model.+  deleteVariable :: v -> m () -  -- | Get the name of the variable.-  getVariableName :: Variable m -> m String+  -- | Get the name of a variable.+  getVariableName :: v -> m T.Text -  -- | Set the name of the variable.-  setVariableName :: Variable m -> String -> m ()+  -- | Set a name for a variable.+  setVariableName :: v -> T.Text -> m () -  -- | Get the allowed values of a variable.-  getVariableBounds :: Variable m -> m (Bounds (Numeric m))+  -- | Retrieve the current bounds associated with a variable.+  getVariableBounds :: v -> m Bounds -  -- | Constrain a variable to take on certain values.-  setVariableBounds :: Variable m -> Bounds (Numeric m) -> m ()+  -- | Apply bounds to a variable.+  --+  -- See 'Math.Programming.Dsl.within' as a higher-level alternative.+  setVariableBounds :: v -> Bounds -> m ()    -- | Get the value of a variable in the current solution.-  getVariableValue :: Variable m -> m (Numeric m)+  --+  -- This value could be arbitrary if no solve has been completed, or+  -- a solve produced an infeasible or unbounded solution.+  getVariableValue :: v -> m Double -  -- | Add a constraint to the model represented by an inequality.-  addConstraint :: Inequality (LinearExpression (Numeric m) (Variable m)) -> m (Constraint m)+  -- | Add a constraint representing the given inequality to the model.+  --+  -- See the 'Math.Programming.Dsl..==.', 'Math.Programming.Dsl..==#',+  -- 'Math.Programming.Dsl.==.', 'Math.Programming.Dsl..>=.',+  -- 'Math.Programming.Dsl..>=', 'Math.Programming.Dsl.>=.',+  -- 'Math.Programming.Dsl..<=.', 'Math.Programming.Dsl..<=', and+  -- 'Math.Programming.Dsl.<=.' functions as higher-level+  -- alternatives.+  addConstraint :: Inequality (Expr v) -> m c    -- | Remove a constraint from the model.-  ---  -- The constraint cannot used after being deleted.-  removeConstraint :: Constraint m -> m ()+  deleteConstraint :: c -> m () -  -- | Get the name of the constraint.-  getConstraintName :: Constraint m -> m String+  -- | Get the name of a constraint.+  getConstraintName :: c -> m T.Text -  -- | Set the name of the constraint.-  setConstraintName :: Constraint m -> String -> m ()+  -- | Set a name for a constraint.+  setConstraintName :: c -> T.Text -> m () -  -- | Get the value of the dual variable associated with the-  -- constraint in the current solution.+  -- | Get the dual value associated with a constraint.+  getConstraintValue :: c -> m Double++  -- | Add an objective to the problem.   ---  -- This value has no meaning if the current solution is not an LP-  -- solution.-  getDualValue :: Constraint m -> m (Numeric m)+  -- Depending on the solver backend, this might replace an existing objective.+  addObjective :: Expr v -> m o -  -- | Add a constraint to the model represented by an inequality.-  addObjective :: LinearExpression (Numeric m) (Variable m) -> m (Objective m)+  -- | Remove an objective from the model.+  deleteObjective :: o -> m () -  -- | Get the name of the objective.-  getObjectiveName :: Objective m -> m String+  -- | Get the name of a objective.+  getObjectiveName :: o -> m T.Text -  -- | Set the name of the objective.-  setObjectiveName :: Objective m -> String -> m ()+  -- | Set a name for a objective.+  setObjectiveName :: o -> T.Text -> m () -  -- | Whether the objective is to be minimized or maximized.-  getObjectiveSense :: Objective m -> m Sense+  -- | Get the sense of an objective.+  getObjectiveSense :: o -> m Sense -  -- | Set whether the objective is to be minimized or maximized.-  setObjectiveSense :: Objective m -> Sense -> m ()+  -- | Set the sense of an objective.+  setObjectiveSense :: o -> Sense -> m () -  -- | Get the value of the objective in the current solution.-  getObjectiveValue :: Objective m -> m (Numeric m)+  -- | Get the value of an objective.+  getObjectiveValue :: o -> m Double -  -- | Get the number of seconds the solver is allowed to run before-  -- halting.+  -- | Get the timeout associated with a problem.   getTimeout :: m Double -  -- | Set the number of seconds the solver is allowed to run before-  -- halting.+  -- | Set the timeout associated with a problem.   setTimeout :: Double -> m () -  -- | Optimize the continuous relaxation of the model.+  -- | Compute an LP-optimal solution.   optimizeLP :: m SolutionStatus +-- | Function composition involving a 2-argument function.+compose2 :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)+compose2 = fmap fmap fmap++-- | Monadic lifting  involving a 2-argument function.+lift2 :: (MonadTrans t, Monad m) => (a -> b -> m c) -> (a -> b -> t m c)+lift2 = compose2 lift++instance (MonadLP v c o m) => MonadLP v c o (ReaderT r m) where+  addVariable = lift addVariable+  deleteVariable = lift . deleteVariable+  getVariableName = lift . getVariableName+  setVariableName = lift2 setVariableName+  getVariableValue = lift . getVariableValue+  getVariableBounds = lift . getVariableBounds+  setVariableBounds = lift2 setVariableBounds+  addConstraint = lift . addConstraint+  deleteConstraint = lift . deleteConstraint+  getConstraintName = lift . getConstraintName+  setConstraintName = lift2 setConstraintName+  getConstraintValue = lift . getConstraintValue+  addObjective = lift . addObjective+  deleteObjective = lift . deleteObjective+  getObjectiveName = lift . getObjectiveName+  setObjectiveName = lift2 setObjectiveName+  getObjectiveValue = lift . getObjectiveValue+  getObjectiveSense = lift . getObjectiveSense+  setObjectiveSense = lift2 setObjectiveSense+  getTimeout = lift getTimeout+  setTimeout = lift . setTimeout+  optimizeLP = lift optimizeLP++instance (MonadLP v c o m, Monoid w) => MonadLP v c o (WriterT w m) where+  addVariable = lift addVariable+  deleteVariable = lift . deleteVariable+  getVariableName = lift . getVariableName+  setVariableName = lift2 setVariableName+  getVariableValue = lift . getVariableValue+  getVariableBounds = lift . getVariableBounds+  setVariableBounds = lift2 setVariableBounds+  addConstraint = lift . addConstraint+  deleteConstraint = lift . deleteConstraint+  getConstraintName = lift . getConstraintName+  setConstraintName = lift2 setConstraintName+  getConstraintValue = lift . getConstraintValue+  addObjective = lift . addObjective+  deleteObjective = lift . deleteObjective+  getObjectiveName = lift . getObjectiveName+  setObjectiveName = lift2 setObjectiveName+  getObjectiveValue = lift . getObjectiveValue+  getObjectiveSense = lift . getObjectiveSense+  setObjectiveSense = lift2 setObjectiveSense+  getTimeout = lift getTimeout+  setTimeout = lift . setTimeout+  optimizeLP = lift optimizeLP++instance (MonadLP v c o m, Monoid w) => MonadLP v c o (RWST r w s m) where+  addVariable = lift addVariable+  deleteVariable = lift . deleteVariable+  getVariableName = lift . getVariableName+  setVariableName = lift2 setVariableName+  getVariableValue = lift . getVariableValue+  getVariableBounds = lift . getVariableBounds+  setVariableBounds = lift2 setVariableBounds+  addConstraint = lift . addConstraint+  deleteConstraint = lift . deleteConstraint+  getConstraintName = lift . getConstraintName+  setConstraintName = lift2 setConstraintName+  getConstraintValue = lift . getConstraintValue+  addObjective = lift . addObjective+  deleteObjective = lift . deleteObjective+  getObjectiveName = lift . getObjectiveName+  setObjectiveName = lift2 setObjectiveName+  getObjectiveValue = lift . getObjectiveValue+  getObjectiveSense = lift . getObjectiveSense+  setObjectiveSense = lift2 setObjectiveSense+  getTimeout = lift getTimeout+  setTimeout = lift . setTimeout+  optimizeLP = lift optimizeLP++instance MonadLP v c o m => MonadLP v c o (StateT s m) where+  addVariable = lift addVariable+  deleteVariable = lift . deleteVariable+  getVariableValue = lift . getVariableValue+  getVariableName = lift . getVariableName+  setVariableName = lift2 setVariableName+  getVariableBounds = lift . getVariableBounds+  setVariableBounds = lift2 setVariableBounds+  addConstraint = lift . addConstraint+  deleteConstraint = lift . deleteConstraint+  getConstraintName = lift . getConstraintName+  setConstraintName = lift2 setConstraintName+  getConstraintValue = lift . getConstraintValue+  addObjective = lift . addObjective+  deleteObjective = lift . deleteObjective+  getObjectiveName = lift . getObjectiveName+  setObjectiveName = lift2 setObjectiveName+  getObjectiveValue = lift . getObjectiveValue+  getObjectiveSense = lift . getObjectiveSense+  setObjectiveSense = lift2 setObjectiveSense+  getTimeout = lift getTimeout+  setTimeout = lift . setTimeout+  optimizeLP = lift optimizeLP+ -- | A (mixed) integer program. ----- In addition to the methods of the 'LPMonad' class, this monad+-- In addition to the methods of the 'MonadLP' class, this monad -- supports constraining variables to be either continuous or -- discrete.-class ( LPMonad m-      ) => IPMonad m where-  -- | Optimize the mixed-integer program.-  optimizeIP :: m SolutionStatus+class MonadLP v c o m => MonadIP v c o m | m -> v c o where+  getVariableDomain :: v -> m Domain+  setVariableDomain :: v -> Domain -> m () -  -- | Get the domain of a variable.-  getVariableDomain :: Variable m -> m Domain+  getRelativeMIPGap :: m Double+  setRelativeMIPGap :: Double -> m () -  -- | Set the domain of a variable.-  setVariableDomain :: Variable m -> Domain -> m ()+  optimizeIP :: m SolutionStatus -  -- | Get the allowed relative gap between LP and IP solutions.-  getRelativeMIPGap :: m Double+instance MonadIP v c o m => MonadIP v c o (ReaderT r m) where+  getVariableDomain = lift . getVariableDomain+  setVariableDomain = lift2 setVariableDomain+  getRelativeMIPGap = lift getRelativeMIPGap+  setRelativeMIPGap = lift . setRelativeMIPGap+  optimizeIP = lift optimizeIP -  -- | Set the allowed relative gap between LP and IP solutions.-  setRelativeMIPGap :: Double -> m ()+instance MonadIP v c o m => MonadIP v c o (StateT s m) where+  getVariableDomain = lift . getVariableDomain+  setVariableDomain = lift2 setVariableDomain+  getRelativeMIPGap = lift getRelativeMIPGap+  setRelativeMIPGap = lift . setRelativeMIPGap+  optimizeIP = lift optimizeIP  -- | Whether a math program is minimizing or maximizing its objective. data Sense = Minimization | Maximization   deriving-    ( Eq-    , Ord-    , Read-    , Show+    ( Eq,+      Ord,+      Read,+      Show     )  -- | The outcome of an optimization. data SolutionStatus-  = Optimal-  -- ^ An optimal solution has been found.-  | Feasible-  -- ^ A feasible solution has been found. The result may or may not-  -- be optimal.-  | Infeasible-  -- ^ The model has been proven to be infeasible.-  | Unbounded-  -- ^ The model has been proven to be unbounded.-  | Error-  -- ^ An error was encountered during the solve. Instance-specific-  -- methods should be used to determine what occurred.+  = -- | An optimal solution has been found.+    Optimal+  | -- | A feasible solution has been found. The result may or may not+    -- be optimal.+    Feasible+  | -- | The model has been proven to be infeasible.+    Infeasible+  | -- | The model has been proven to be unbounded.+    Unbounded+  | -- | An error was encountered during the solve. Instance-specific+    -- methods should be used to determine what occurred.+    Error   deriving-    ( Eq-    , Ord-    , Read-    , Show+    ( Eq,+      Ord,+      Read,+      Show     )  -- | An interval of the real numbers.-data Bounds b-  = NonNegativeReals-  -- ^ The non-negative reals.-  | NonPositiveReals-  -- ^ The non-positive reals.-  | Interval b b-  -- ^ Any closed interval of the reals.-  | Free-  -- ^ Any real number.+data Bounds+  = -- | The non-negative reals.+    NonNegativeReals+  | -- | The non-positive reals.+    NonPositiveReals+  | -- | Any closed interval of the reals.+    Interval Double Double+  | -- | Any real number.+    Free   deriving-    ( Read-    , Show+    ( Read,+      Show     )  -- | The type of values that a variable can take on.@@ -182,89 +291,28 @@ -- of the same name. The ambiguity is unfortunate, but other natural -- nomenclature such as @Integral@ are similarly conflicted. data Domain-  = Continuous-  -- ^ The variable lies in the real numbers-  | Integer-  -- ^ The variable lies in the integers-  | Binary-  -- ^ The variable lies in the set @{0, 1}@.-  deriving-    ( Read-    , Show-    )--class Nameable m a where-  getName :: a -> m String-  setName :: a -> String -> m ()--instance LPMonad m => Nameable m (Variable m) where-  getName = getVariableName-  setName = setVariableName--instance LPMonad m => Nameable m (Constraint m) where-  getName = getConstraintName-  setName = setConstraintName--instance LPMonad m => Nameable m (Objective m) where-  getName = getObjectiveName-  setName = setObjectiveName---- | A linear expression containing symbolic variables of type @b@ and--- numeric coefficients of type @a@.------ Using 'String's to denote variables and 'Double's as our numeric--- type, we could express /3 x + 2 y + 1/ as------ @---   LinearExpression [(3, "x"), (2, "y")] 1--- @-data LinearExpression a b-  = LinearExpression [(a, b)] a+  = -- | The variable lies in the real numbers+    Continuous+  | -- | The variable lies in the integers+    Integer+  | -- | The variable lies in the set @{0, 1}@.+    Binary   deriving-    ( Read-    , Show+    ( Read,+      Show     ) --- | Implements addition of 'LinearExpression a b' terms-instance Num a => Semigroup (LinearExpression a b) where-  (LinearExpression termsLhs constantLhs) <> (LinearExpression termsRhs constantRhs)-    = LinearExpression (termsLhs <> termsRhs) (constantLhs + constantRhs)---- | Using '0' as the identity element-instance Num a => Monoid (LinearExpression a b) where-  mempty = LinearExpression [] 0--instance Functor (LinearExpression a) where-  fmap = fmapDefault--instance Bifunctor LinearExpression where-  first f (LinearExpression terms constant)-    = LinearExpression (fmap (first f) terms) (f constant)-  second f (LinearExpression terms constant)-    = LinearExpression (fmap (fmap f) terms) constant--instance Foldable (LinearExpression a) where-  foldMap = foldMapDefault---- | Useful for substituting values in a monadic/applicative context-instance Traversable (LinearExpression a) where-  traverse f (LinearExpression terms constant)-    = LinearExpression <$> traverse (traverse f) terms <*> pure constant- -- | Non-strict inequalities. data Inequality a   = Inequality Ordering a a   deriving-    ( Read-    , Show+    ( Read,+      Show,+      Functor,+      Foldable,+      Traversable     ) -instance Functor Inequality where-  fmap = fmapDefault--instance Foldable Inequality where-  foldMap = foldMapDefault--instance Traversable Inequality where-  traverse f (Inequality sense lhs rhs)-    = Inequality sense <$> f lhs <*> f rhs+-- | A convient shorthand for the type of linear expressions used in+-- models.+type Expr = LinExpr Double
− test/Driver.hs
@@ -1,10 +0,0 @@-{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --ignores="*~" #-}-{-|-Module : Main--The entry point for tests. We use tasty-discover to automatically-discover test functions in this directory, so simply preface tasty-tests with test_ for tasty TestTrees, or prop_ for QuickCheck-properties.--}-module Main where
+ test/Math/Programming/DslSpec.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedStrings #-}++module Math.Programming.DslSpec where++import Control.Monad.Identity+import qualified Data.Text as T+import Math.Programming+import Math.Programming.Dsl+import Test.Hspec++spec :: Spec+spec = do+  describe "formatExpr" $ do+    it "formats expressions correctly" $ do+      let ex :: Expr T.Text+          ex = 2 *. "x" .+. 3 *. "y" .+. con 1+      formatExpr' pure ex `shouldBe` Identity "2.0 * x + 3.0 * y + 1.0"++      let ex2 :: Expr T.Text+          ex2 = con 0+      formatExpr' pure ex2 `shouldBe` Identity "0.0"
+ test/Math/Programming/LinExprSpec.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Math.Programming.LinExprSpec where++import Control.Monad+import Data.Ratio+import Math.Programming+import Test.Hspec+import Test.Hspec.QuickCheck+import Test.QuickCheck++spec :: Spec+spec = do+  describe "algebraic properties" $ do+    prop "satisfies addititive commutivity" commutativityProp+    prop "satisfies addititive associativity" additiveAssociativityProp+    prop "satisfies coefficient commutativity" coefficientCommutativityProp+  describe "simplification" $ do+    simplifyRegressions+    prop "simplification preserves value" simplifyProp++type ExactExpr = LinExpr (Ratio Integer) (Ratio Integer)++instance Arbitrary ExactExpr where+  arbitrary = LinExpr <$> arbitrary <*> arbitrary++-- | A pair of linear expressions, differing only by the ordering of+-- the summands.+newtype ShuffledAndUnshuffled+  = ShuffledAndUnshuffled (ExactExpr, ExactExpr)+  deriving+    ( Show+    )++instance Arbitrary ShuffledAndUnshuffled where+  arbitrary = do+    unshuffled@(LinExpr terms constant) <- arbitrary+    shuffledTerms <- shuffle terms+    let shuffled = LinExpr shuffledTerms constant+    return $ ShuffledAndUnshuffled (unshuffled, shuffled)++-- | Addition should be commutative.+commutativityProp :: ShuffledAndUnshuffled -> Bool+commutativityProp (ShuffledAndUnshuffled (shuffled, unshuffled)) =+  eval shuffled == eval unshuffled++-- | A pair of linear expressions, differing only by the ordering of+-- the coefficients of the summands.+newtype ShuffledCoefficients+  = ShuffledCoefficients (ExactExpr, ExactExpr)+  deriving+    ( Show+    )++instance Arbitrary ShuffledCoefficients where+  arbitrary = do+    unshuffled@(LinExpr terms constant) <- arbitrary+    terms' <- forM terms $ \(x, y) -> do+      flipped <- arbitrary+      return $+        if flipped+          then (y, x)+          else (x, y)+    let shuffled = LinExpr terms' constant+    return $ ShuffledCoefficients (shuffled, unshuffled)++coefficientCommutativityProp :: ShuffledCoefficients -> Bool+coefficientCommutativityProp (ShuffledCoefficients (shuffled, unshuffled)) =+  eval shuffled == eval unshuffled++additiveAssociativityProp :: ExactExpr -> ExactExpr -> ExactExpr -> Bool+additiveAssociativityProp x y z =+  eval ((x .+. y) .+. z) == eval (x .+. (y .+. z))++simplifyProp :: ExactExpr -> Bool+simplifyProp x = eval x == eval (simplify x)++simplifyRegressions :: Spec+simplifyRegressions = do+  it "simplifies x + x - x" $+    let terms :: [(Int, Int)]+        coef :: Int+        (LinExpr terms coef) = simplify $ LinExpr [(1, 0), (1, 0), (-1, 0)] 0+     in do+          coef `shouldBe` 0+          terms `shouldBe` [(1, 0)]
− test/Math/Programming/TestLinearExpression.hs
@@ -1,74 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE FlexibleInstances #-}-module Math.Programming.TestLinearExpression where--import           Control.Monad-import           Data.Ratio--import           Test.Tasty-import           Test.Tasty.QuickCheck--import           Math.Programming--test_tree :: TestTree-test_tree = testGroup "LinearExpression tests"-  [ testProperty "Additive commutativity" commutativityProp-  , testProperty "Additive associativity" additiveAssociativityProp-  , testProperty "Coefficient commutativity" coefficientCommutativityProp-  , testProperty "Simplification" simplifyProp-  ]--type ExactExpr = LinearExpression (Ratio Integer) (Ratio Integer)--instance Arbitrary ExactExpr where-  arbitrary = LinearExpression <$> arbitrary <*> arbitrary---- | A pair of linear expressions, differing only by the ordering of--- the summands.-newtype ShuffledAndUnshuffled-  = ShuffledAndUnshuffled (ExactExpr, ExactExpr)-  deriving-    ( Show-    )--instance Arbitrary ShuffledAndUnshuffled where-  arbitrary = do-    unshuffled@(LinearExpression terms constant) <- arbitrary-    shuffledTerms <- shuffle terms-    let shuffled = LinearExpression shuffledTerms constant-    return $ ShuffledAndUnshuffled (unshuffled, shuffled)---- | Addition should be commutative.-commutativityProp :: ShuffledAndUnshuffled -> Bool-commutativityProp (ShuffledAndUnshuffled (shuffled, unshuffled))-  = eval shuffled == eval unshuffled---- | A pair of linear expressions, differing only by the ordering of--- the coefficients of the summands.-newtype ShuffledCoefficients-  = ShuffledCoefficients (ExactExpr, ExactExpr)-  deriving-    ( Show-    )--instance Arbitrary ShuffledCoefficients where-  arbitrary = do-    unshuffled@(LinearExpression terms constant) <- arbitrary-    terms' <- forM terms $ \(x, y) -> do-      flipped <- arbitrary-      return $ if flipped-               then (y, x)-               else (x, y)-    let shuffled = LinearExpression terms' constant-    return $ ShuffledCoefficients (shuffled, unshuffled)--coefficientCommutativityProp :: ShuffledCoefficients -> Bool-coefficientCommutativityProp (ShuffledCoefficients (shuffled, unshuffled))-  = eval shuffled == eval unshuffled--additiveAssociativityProp :: ExactExpr -> ExactExpr -> ExactExpr -> Bool-additiveAssociativityProp x y z-  = eval ((x .+. y) .+. z) == eval (x .+. (y .+. z))--simplifyProp :: ExactExpr -> Bool-simplifyProp x = eval x == eval (simplify x)
+ test/Spec.hs view
@@ -0,0 +1,3 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}++module Spec where