Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
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 GLPK.
Synopsis
- class (Monad m, Num (Numeric m)) => LPMonad m where
- type Numeric m :: *
- data Variable m :: *
- data Constraint m :: *
- data Objective m :: *
- addVariable :: m (Variable m)
- removeVariable :: Variable m -> m ()
- getVariableName :: Variable m -> m String
- setVariableName :: Variable m -> String -> m ()
- getVariableBounds :: Variable m -> m (Bounds (Numeric m))
- setVariableBounds :: Variable m -> Bounds (Numeric m) -> m ()
- getVariableValue :: Variable m -> m (Numeric m)
- addConstraint :: Inequality (LinearExpression (Numeric m) (Variable m)) -> m (Constraint m)
- removeConstraint :: Constraint m -> m ()
- getConstraintName :: Constraint m -> m String
- setConstraintName :: Constraint m -> String -> m ()
- getDualValue :: Constraint m -> m (Numeric m)
- addObjective :: LinearExpression (Numeric m) (Variable m) -> m (Objective m)
- getObjectiveName :: Objective m -> m String
- setObjectiveName :: Objective m -> String -> m ()
- getObjectiveSense :: Objective m -> m Sense
- setObjectiveSense :: Objective m -> Sense -> m ()
- getObjectiveValue :: Objective m -> m (Numeric m)
- getTimeout :: m Double
- setTimeout :: Double -> m ()
- optimizeLP :: m SolutionStatus
- writeFormulation :: FilePath -> m ()
- type Expr m = LinearExpression (Numeric m) (Variable m)
- data Bounds b
- = NonNegativeReals
- | NonPositiveReals
- | Interval b b
- | Free
- data SolutionStatus
- = Optimal
- | Feasible
- | Infeasible
- | Unbounded
- | Error
- data Sense
- class LPMonad m => IPMonad m where
- optimizeIP :: m SolutionStatus
- getVariableDomain :: Variable m -> m Domain
- setVariableDomain :: Variable m -> Domain -> m ()
- getRelativeMIPGap :: m Double
- setRelativeMIPGap :: Double -> m ()
- data Domain
- = Continuous
- | Integer
- | Binary
- free :: LPMonad m => m (Variable m)
- nonNeg :: LPMonad m => m (Variable m)
- nonPos :: LPMonad m => m (Variable m)
- bounded :: LPMonad m => Numeric m -> Numeric m -> m (Variable m)
- within :: LPMonad m => m (Variable m) -> Bounds (Numeric m) -> m (Variable m)
- integer :: IPMonad m => m (Variable m)
- binary :: IPMonad m => m (Variable m)
- nonNegInteger :: IPMonad m => m (Variable m)
- nonPosInteger :: IPMonad m => m (Variable m)
- asKind :: IPMonad m => m (Variable m) -> Domain -> m (Variable m)
- data LinearExpression a b = LinearExpression [(a, b)] a
- eval :: Num a => LinearExpression a a -> a
- simplify :: (Ord b, Num a) => LinearExpression a b -> LinearExpression a b
- var :: Num a => b -> LinearExpression a b
- con :: Num a => a -> LinearExpression a b
- exprSum :: Num a => [LinearExpression a b] -> LinearExpression a b
- varSum :: Num a => [b] -> LinearExpression a b
- (.+.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
- (@+@) :: Num a => b -> b -> LinearExpression a b
- (.+@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
- (@+.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
- (@+#) :: Num a => b -> a -> LinearExpression a b
- (#+@) :: Num a => 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 => LinearExpression a b -> LinearExpression a b -> LinearExpression a b
- (@-@) :: Num a => b -> b -> LinearExpression a b
- (.-@) :: Num a => LinearExpression a b -> b -> LinearExpression a b
- (@-.) :: Num a => b -> LinearExpression a b -> LinearExpression a b
- (@-#) :: Num a => b -> a -> LinearExpression a b
- (#-@) :: Num a => 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
- (#*.) :: Num a => a -> LinearExpression a b -> LinearExpression a b
- (.*#) :: Num a => LinearExpression a b -> a -> LinearExpression a b
- (@/#) :: Fractional a => b -> a -> LinearExpression a b
- (./#) :: Fractional a => LinearExpression a b -> a -> LinearExpression a b
- data Inequality a = Inequality Ordering a a
- (#<=@) :: 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)
- minimize :: LPMonad m => Expr m -> m (Objective m)
- maximize :: LPMonad m => Expr m -> m (Objective m)
- evalExpr :: LPMonad m => Expr m -> m (Numeric m)
- named :: (Monad m, Nameable m a) => m a -> String -> m a
- nameOf :: (Monad m, Nameable m a) => a -> m String
Math programs
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.
Linear programs
class (Monad m, Num (Numeric m)) => LPMonad m where Source #
A monad for formulating and solving linear programs.
We manipulate linear programs and their settings using the
Mutable
typeclass.
The numeric type used in the model.
The type of variables in the model. LPMonad
treats these as
opaque values, but instances may expose more details.
data Constraint m :: * Source #
The type of constraints in the model. LPMonad
treats these
as opaque values, but instances may expose more details.
data Objective m :: * Source #
The type of objectives in the model. LPMonad
treats these
as opaque values, but instances may expose more details.
addVariable :: m (Variable m) Source #
Create a new decision variable in the model.
This variable will be initialized to be a non-negative continuous variable.
removeVariable :: Variable m -> m () Source #
Remove a decision variable from the model.
The variable cannot be used after being deleted.
getVariableName :: Variable m -> m String Source #
Get the name of the variable.
setVariableName :: Variable m -> String -> m () Source #
Set the name of the variable.
getVariableBounds :: Variable m -> m (Bounds (Numeric m)) Source #
Get the allowed values of a variable.
setVariableBounds :: Variable m -> Bounds (Numeric m) -> m () Source #
Constrain a variable to take on certain values.
getVariableValue :: Variable m -> m (Numeric m) Source #
Get the value of a variable in the current solution.
addConstraint :: Inequality (LinearExpression (Numeric m) (Variable m)) -> m (Constraint m) Source #
Add a constraint to the model represented by an inequality.
removeConstraint :: Constraint m -> m () Source #
Remove a constraint from the model.
The constraint cannot used after being deleted.
getConstraintName :: Constraint m -> m String Source #
Get the name of the constraint.
setConstraintName :: Constraint m -> String -> m () Source #
Set the name of the constraint.
getDualValue :: Constraint m -> m (Numeric m) Source #
Get the value of the dual variable associated with the constraint in the current solution.
This value has no meaning if the current solution is not an LP solution.
addObjective :: LinearExpression (Numeric m) (Variable m) -> m (Objective m) Source #
Add a constraint to the model represented by an inequality.
getObjectiveName :: Objective m -> m String Source #
Get the name of the objective.
setObjectiveName :: Objective m -> String -> m () Source #
Set the name of the objective.
getObjectiveSense :: Objective m -> m Sense Source #
Whether the objective is to be minimized or maximized.
setObjectiveSense :: Objective m -> Sense -> m () Source #
Set whether the objective is to be minimized or maximized.
getObjectiveValue :: Objective m -> m (Numeric m) Source #
Get the value of the objective in the current solution.
getTimeout :: m Double Source #
Get the number of seconds the solver is allowed to run before halting.
setTimeout :: Double -> m () Source #
Set the number of seconds the solver is allowed to run before halting.
optimizeLP :: m SolutionStatus Source #
Optimize the continuous relaxation of the model.
writeFormulation :: FilePath -> m () Source #
Write out the formulation.
type Expr m = LinearExpression (Numeric m) (Variable m) Source #
A convient shorthand for the type of linear expressions used in a given model.
An interval of the real numbers.
NonNegativeReals | The non-negative reals. |
NonPositiveReals | The non-positive reals. |
Interval b b | Any closed interval of the reals. |
Free | Any real number. |
data SolutionStatus Source #
The outcome of an optimization.
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. |
Instances
Eq SolutionStatus Source # | |
Defined in Math.Programming.Types (==) :: SolutionStatus -> SolutionStatus -> Bool # (/=) :: SolutionStatus -> SolutionStatus -> Bool # | |
Ord SolutionStatus Source # | |
Defined in Math.Programming.Types compare :: SolutionStatus -> SolutionStatus -> Ordering # (<) :: SolutionStatus -> SolutionStatus -> Bool # (<=) :: SolutionStatus -> SolutionStatus -> Bool # (>) :: SolutionStatus -> SolutionStatus -> Bool # (>=) :: SolutionStatus -> SolutionStatus -> Bool # max :: SolutionStatus -> SolutionStatus -> SolutionStatus # min :: SolutionStatus -> SolutionStatus -> SolutionStatus # | |
Read SolutionStatus Source # | |
Defined in Math.Programming.Types readsPrec :: Int -> ReadS SolutionStatus # readList :: ReadS [SolutionStatus] # | |
Show SolutionStatus Source # | |
Defined in Math.Programming.Types showsPrec :: Int -> SolutionStatus -> ShowS # show :: SolutionStatus -> String # showList :: [SolutionStatus] -> ShowS # |
Whether a math program is minimizing or maximizing its objective.
Integer programs
class LPMonad m => IPMonad m where Source #
A (mixed) integer program.
In addition to the methods of the LPMonad
class, this monad
supports constraining variables to be either continuous or
discrete.
optimizeIP :: m SolutionStatus Source #
Optimize the mixed-integer program.
getVariableDomain :: Variable m -> m Domain Source #
Get the domain of a variable.
setVariableDomain :: Variable m -> Domain -> m () Source #
Set the domain of a variable.
getRelativeMIPGap :: m Double Source #
Get the allowed relative gap between LP and IP solutions.
setRelativeMIPGap :: Double -> m () Source #
Set the allowed relative gap between LP and IP solutions.
The type of values that a variable can take on.
Note that the Integer
constructor does not interfere with the
Integer
type, as the Integer
type does not define a constuctor
of the same name. The ambiguity is unfortunate, but other natural
nomenclature such as Integral
are similarly conflicted.
Continuous | The variable lies in the real numbers |
Integer | The variable lies in the integers |
Binary | The variable lies in the set |
Model-building DSL
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.
Creating 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.
Continuous variables
bounded :: LPMonad m => Numeric m -> Numeric m -> m (Variable m) Source #
Create a new variable bounded between two values.
within :: LPMonad m => m (Variable m) -> Bounds (Numeric m) -> m (Variable m) Source #
Constrain a variable to take on certain values.
This function is designed to be used as an infix operator, e.g.
addVariable
`within
`NonNegativeReals
Integer variables
nonNegInteger :: IPMonad m => m (Variable m) Source #
Create an integer-value variable that takes on non-negative values.
nonPosInteger :: IPMonad m => m (Variable m) Source #
Create an integer-value variable that takes on non-positive values.
asKind :: IPMonad m => m (Variable m) -> Domain -> m (Variable m) Source #
Set the type of a variable.
This function is designed to be used as an infix operator, e.g.
addVariable
`asKind
`Binary
Linear expressions
The module LinearExpression
provides operators
to build up LinearExpression
objects using declared variables.
data LinearExpression a b Source #
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
LinearExpression [(a, b)] a |
Instances
eval :: Num a => LinearExpression a a -> a Source #
Reduce an expression to its value.
simplify :: (Ord b, Num a) => LinearExpression a b -> LinearExpression a b Source #
Combine equivalent terms by summing their coefficients.
var :: Num a => b -> LinearExpression a b Source #
Construct an expression representing a variable.
con :: Num a => a -> LinearExpression a b Source #
Construct an expression representing a constant.
exprSum :: Num a => [LinearExpression a b] -> LinearExpression a b Source #
Construct an expression by summing expressions.
varSum :: Num a => [b] -> LinearExpression a b Source #
Construct an expression by summing variables.
Addition
We can summarize the addition operators with the table
Constant | Variable | Expression | |
Constant | + | #+@ | #+. |
Variable | @+# | @+@ | @+. |
Expression | .+# | .+@ | .+. |
(.+.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b infixl 6 Source #
(@+@) :: Num a => b -> b -> LinearExpression a b infixl 6 Source #
(.+@) :: Num a => LinearExpression a b -> b -> LinearExpression a b infixl 6 Source #
(@+.) :: Num a => b -> LinearExpression a b -> LinearExpression a b infixl 6 Source #
(@+#) :: Num a => b -> a -> LinearExpression a b infixl 6 Source #
(#+@) :: Num a => a -> b -> LinearExpression a b infixl 6 Source #
(#+.) :: Num a => a -> LinearExpression a b -> LinearExpression a b infixl 6 Source #
(.+#) :: Num a => LinearExpression a b -> a -> LinearExpression a b infixl 6 Source #
Subtraction
We can summarize the subtraction operators with the table
Constant | Variable | Expression | |
Constant | - | #-@ | #-. |
Variable | @-# | @-@ | @-. |
Expression | .-# | .-@ | .-. |
(.-.) :: Num a => LinearExpression a b -> LinearExpression a b -> LinearExpression a b infixl 6 Source #
(@-@) :: Num a => b -> b -> LinearExpression a b infixl 6 Source #
(.-@) :: Num a => LinearExpression a b -> b -> LinearExpression a b infixl 6 Source #
(@-.) :: Num a => b -> LinearExpression a b -> LinearExpression a b infixl 6 Source #
(@-#) :: Num a => b -> a -> LinearExpression a b infixl 6 Source #
(#-@) :: Num a => a -> b -> LinearExpression a b infixl 6 Source #
(#-.) :: Num a => a -> LinearExpression a b -> LinearExpression a b infixl 6 Source #
(.-#) :: Num a => LinearExpression a b -> a -> LinearExpression a b infixl 6 Source #
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 #*@
.
(#*@) :: Num a => a -> b -> LinearExpression a b infixl 7 Source #
(@*#) :: Num a => b -> a -> LinearExpression a b infixl 7 Source #
(#*.) :: Num a => a -> LinearExpression a b -> LinearExpression a b infixl 7 Source #
(.*#) :: Num a => LinearExpression a b -> a -> LinearExpression a b infixl 7 Source #
Division
We can summarize the multiplication operators with the table
Constant | Variable | Expression | |
Constant | / | ||
Variable | @/# | ||
Expression | ./# |
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 @/#
.
(@/#) :: Fractional a => b -> a -> LinearExpression a b infixl 7 Source #
(./#) :: Fractional a => LinearExpression a b -> a -> LinearExpression a b infixl 7 Source #
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.
data Inequality a Source #
Non-strict inequalities.
Inequality Ordering a a |
Instances
Less-than constraints
We can summarize the various inquality operators in the following table.
Constant | Variable | Expression | |
Constant | #<=@ | #<=. | |
Variable | @<=# | @<=@ | @<=. |
Expression | .<=# | .<=@ | .<=. |
Greater-than constraints
We can summarize the various inquality operators in the following table.
Constant | Variable | Expression | |
Constant | #>=@ | #>=. | |
Variable | @>=# | @>=@ | @>=. |
Expression | .>=# | .>=@ | .>=. |
Equality constraints
We can summarize the various inquality operators in the following table.
Constant | Variable | Expression | |
Constant | #==@ | #==. | |
Variable | @==# | @==@ | @==. |
Expression | .==# | .==@ | .==. |
Specifying objectives
Utilities
evalExpr :: LPMonad m => Expr m -> m (Numeric m) Source #
Get the value of a linear expression in the current solution.