packages feed

glpk-hs 0.3.5 → 0.5

raw patch · 14 files changed

+85/−399 lines, 14 filesdep +gaspPVP ok

version bump matches the API change (PVP)

Dependencies added: gasp

API changes (from Hackage documentation)

- Data.Algebra: (*#) :: Ring r => r -> r -> r
- Data.Algebra: (*&) :: (Ord v, Ring c) => c -> v -> LinFunc v c
- Data.Algebra: (*^) :: Module r m => r -> m -> m
- Data.Algebra: (/#) :: Field f => f -> f -> f
- Data.Algebra: (^+^) :: Group g => g -> g -> g
- Data.Algebra: (^-^) :: Group g => g -> g -> g
- Data.Algebra: class Ring f => Field f where inv x = one /# x a /# b = a *# inv b
- Data.Algebra: class Group g where a ^+^ b = a ^-^ neg b a ^-^ b = a ^+^ neg b neg a = zero ^-^ a
- Data.Algebra: class (Ring r, Group m) => Module r m
- Data.Algebra: class Group r => Ring r
- Data.Algebra: class (Module f v, Field f) => VectorSpace f v
- Data.Algebra: combination :: Module r m => [(r, m)] -> m
- Data.Algebra: evalPoly :: (Module r m, Ring m) => Poly r -> m -> m
- Data.Algebra: gsum :: Group g => [g] -> g
- Data.Algebra: inv :: Field f => f -> f
- Data.Algebra: linCombination :: (Ord v, Num r) => [(r, v)] -> LinFunc v r
- Data.Algebra: neg :: Group g => g -> g
- Data.Algebra: one :: Ring r => r
- Data.Algebra: type GroupRing r g = Map g r
- Data.Algebra: type LinFunc = Map
- Data.Algebra: type Poly = []
- Data.Algebra: var :: (Ord v, Ring c) => v -> LinFunc v c
- Data.Algebra: varPoly :: Ring r => Poly r
- Data.Algebra: varSum :: (Ord v, Ring c) => [v] -> LinFunc v c
- Data.Algebra: zero :: Group g => g
- Data.LinearProgram.LinExpr: instance (GHC.Classes.Ord v, Data.Algebra.Group.Group c) => Data.Algebra.Group.Group (Data.LinearProgram.LinExpr.LinExpr v c)
- Data.LinearProgram.LinExpr: instance (GHC.Classes.Ord v, Data.Algebra.Module.Module r c) => Data.Algebra.Module.Module r (Data.LinearProgram.LinExpr.LinExpr v c)
+ Data.LinearProgram.Common: linCombination :: (Ord v, Additive r) => [(r, v)] -> LinFunc v r
+ Data.LinearProgram.Common: type LinFunc = Map
+ Data.LinearProgram.LinExpr: instance (GHC.Classes.Ord v, Algebra.Classes.AbelianAdditive c) => Algebra.Classes.AbelianAdditive (Data.LinearProgram.LinExpr.LinExpr v c)
+ Data.LinearProgram.LinExpr: instance (GHC.Classes.Ord v, Algebra.Classes.Additive c) => Algebra.Classes.Additive (Data.LinearProgram.LinExpr.LinExpr v c)
+ Data.LinearProgram.LinExpr: instance (GHC.Classes.Ord v, Algebra.Classes.Group c) => Algebra.Classes.Group (Data.LinearProgram.LinExpr.LinExpr v c)
+ Data.LinearProgram.LinExpr: instance (GHC.Classes.Ord v, Algebra.Classes.Ring c) => Algebra.Classes.Module c (Data.LinearProgram.LinExpr.LinExpr v c)
- Control.Monad.LPMonad: addWeightedObjective :: (Ord v, Module r c, MonadState (LP v c) m) => r -> LinFunc v c -> m ()
+ Control.Monad.LPMonad: addWeightedObjective :: (Ord v, Ring c, MonadState (LP v c) m) => c -> LinFunc v c -> m ()

Files

Control/Monad/LPMonad/Internal.hs view
@@ -44,6 +44,7 @@ --         newVariables'         ) where +import Prelude hiding ((-),(+)) import Control.Monad.State.Strict import Control.Monad.Identity @@ -51,7 +52,7 @@  import Data.LinearProgram.Common --- | A simple monad for constructing linear programs.  This library is intended to be able to link to +-- | A simple monad for constructing linear programs.  This library is intended to be able to link to -- a variety of different linear programming implementations. type LPM v c = LPT v c Identity @@ -92,13 +93,13 @@ {-# SPECIALIZE geq :: (Ord v, Group c) => LinFunc v c -> LinFunc v c -> LPM v c (),         (Ord v, Group c, Monad m) => LinFunc v c -> LinFunc v c -> LPT v c m () #-} -- | Specifies the relationship between two functions in the variables.  So, for example,--- +-- -- > equal (f ^+^ g) h--- +-- -- constrains the value of @h@ to be equal to the value of @f@ plus the value of @g@. equal, leq, geq :: (Ord v, Group c, MonadState (LP v c) m) => LinFunc v c -> LinFunc v c -> m ()-equal f g = equalTo (f ^-^ g) zero-leq f g = leqTo (f ^-^ g) zero+equal f g = equalTo (f - g) zero+leq f g = leqTo (f - g) zero geq = flip leq  {-# SPECIALIZE equal' :: (Ord v, Group c) => String -> LinFunc v c -> LinFunc v c -> LPM v c (),@@ -109,8 +110,8 @@         (Ord v, Group c, Monad m) => String -> LinFunc v c -> LinFunc v c -> LPT v c m () #-} -- | Specifies the relationship between two functions in the variables, with a label on the constraint. equal', leq', geq' :: (Ord v, Group c, MonadState (LP v c) m) => String -> LinFunc v c -> LinFunc v c -> m ()-equal' lab f g = equalTo' lab (f ^-^ g) zero-leq' lab f g = leqTo' lab (f ^-^ g) zero+equal' lab f g = equalTo' lab (f - g) zero+leq' lab f g = leqTo' lab (f - g) zero geq' = flip . leq'  {-# SPECIALIZE equalTo :: LinFunc v c -> c -> LPM v c (), Monad m => LinFunc v c -> c -> LPT v c m () #-}@@ -150,7 +151,7 @@ --                                 Nothing        -> return $ take k [toEnum 0..] --                                 Just ((start, _), _) --                                         -> return $ take k $ tail [start..]---                                         +-- -- {-# SPECIALIZE newVariables' :: (Ord v, Enum v) => LPM v c [v], --         (Ord v, Enum v, Monad m) => LPT v c m [v] #-} -- -- | Returns an infinite list of unused variables.  If the program is currently empty,@@ -218,13 +219,15 @@ -- | Adds this function to the objective function. addObjective :: (Ord v, Group c, MonadState (LP v c) m) => LinFunc v c -> m () addObjective obj = modify addObj where-        addObj lp@LP{..} = lp {objective = obj ^+^ objective}+        addObj lp@LP{..} = lp {objective = obj + objective} -{-# SPECIALIZE addWeightedObjective :: (Ord v, Module r c) => r -> LinFunc v c -> LPM v c (),-        (Ord v, Module r c, Monad m) => r -> LinFunc v c -> LPT v c m () #-}+{-# SPECIALIZE addWeightedObjective ::+        (Ord v, Ring c) => c -> LinFunc v c -> LPM v c (),+        (Ord v, Ring c, Monad m) => c -> LinFunc v c -> LPT v c m () #-} -- | Adds this function to the objective function, with the specified weight.  Equivalent to -- @'addObjective' (wt '*^' obj)@.-addWeightedObjective :: (Ord v, Module r c, MonadState (LP v c) m) => r -> LinFunc v c -> m ()+addWeightedObjective :: (Ord v, Ring c, MonadState (LP v c) m) =>+                        c -> LinFunc v c -> m () addWeightedObjective wt obj = addObjective (wt *^ obj)  {-# SPECIALIZE setVarBounds :: (Ord v, Ord c) => v -> Bounds c -> LPM v c (),
− Data/Algebra.hs
@@ -1,35 +0,0 @@--- | Common library for algebraic structures.  Has the advantage of automatically inferring lots of useful structure, especially--- in the writing of linear programs.  For example, here are several ways of writing @3 x - 4 y + z@:--- --- > gsum [3 *& x, (-4) *^ var y, var z]--- > linCombination [(3, x), (-4, y), (1, z)]--- > 3 *& x ^-^ 4 *& y ^+^ var z--- --- In addition, if we have two functions @f@ and @g@, we can construct linear combinations of those functions, using --- exactly the same syntax.  Moreover, we can multiply functions with 'Double' coefficients by 'Rational' values successfully.--- This module is intended to offer as much generality as possible without getting in your way.-module Data.Algebra (-	-- * Algebraic structures-	Group(..),-	Ring(..),-	Field(..),-	Module(..),-	VectorSpace(..),-	Poly,-	varPoly,-	GroupRing,-	LinFunc,-	-- * Algebraic functions-	gsum,-	combination,-	evalPoly,-	-- ** Specialized methods on linear functions-	var,-	varSum,-	(*&),-	linCombination) where--import Data.Algebra.Group-import Data.Algebra.Ring-import Data.Algebra.Field-import Data.Algebra.Module
− Data/Algebra/Field.hs
@@ -1,24 +0,0 @@-{-# LANGUAGE UndecidableInstances, FlexibleInstances, MultiParamTypeClasses #-}--module Data.Algebra.Field where--import Data.Ratio--import Data.Algebra.Ring-import Data.Algebra.Module--class Ring f => Field f where-	inv :: f -> f-	(/#) :: f -> f -> f-	inv x = one /# x-	a /# b = a *# inv b--instance Field Double where-	inv = recip--instance Integral a => Field (Ratio a) where-	{-# SPECIALIZE instance Field Rational #-}-	inv = recip--class (Module f v, Field f) => VectorSpace f v-instance (Module f v, Field f) => VectorSpace f v
− Data/Algebra/Group.hs
@@ -1,102 +0,0 @@-{-# LANGUAGE TypeSynonymInstances #-}-module Data.Algebra.Group where--import Control.Applicative-import qualified Data.Map as M-import qualified Data.IntMap as IM-import Data.Ratio--type Poly = []--infixr 4 ^+^-infixr 4 ^-^---- | The algebraic structure of a group.  Written additively.  Required functions: 'zero' and ('^-^' or ('^+^' and 'neg')).-class Group g where-	zero :: g-	(^+^) :: g -> g -> g-	(^-^) :: g -> g -> g-	neg :: g -> g-	-	a ^+^ b = a ^-^ neg b-	a ^-^ b = a ^+^ neg b-	neg a = zero ^-^ a--instance Group Bool where-	zero = False-	(^+^) = (/=)-	(^-^) = (/=)-	neg = id--instance Group Int where-	zero = 0-	(^+^) = (+)-	(^-^) = (-)-	neg = negate--instance Group Integer where-	zero = 0-	(^+^) = (+)-	(^-^) = (-)-	neg = negate--instance Group Double where-	zero = 0-	(^+^) = (+)-	(^-^) = (-)-	neg = negate--instance Integral a => Group (Ratio a) where-	{-# SPECIALIZE instance Group Rational #-}-	zero = 0-	(^+^) = (+)-	(^-^) = (-)-	neg = negate--instance Group g => Group (a -> g) where-	zero = const zero-	(^+^) = liftA2 (^+^)-	(^-^) = liftA2 (^-^)-	neg = fmap neg--instance (Ord k, Group g) => Group (M.Map k g) where-	zero = M.empty-	(^+^) = M.unionWith (^+^)-	neg = fmap neg--instance Group g => Group (IM.IntMap g) where-	zero = IM.empty-	(^+^) = IM.unionWith (^+^)-	neg = fmap neg--instance Group g => Group (Poly g) where-	zero = []-	[] ^+^ p = p-	p ^+^ [] = p-	(a:as) ^+^ (b:bs) = (a ^+^ b):(as ^+^ bs)--instance (Group g1, Group g2) => Group (g1, g2) where-	{-# SPECIALIZE instance Group g => Group (g, g) #-}-	zero = (zero, zero)-	(x1, y1) ^+^ (x2, y2) = (x1 ^+^ x2, y1 ^+^ y2)-	(x1, y1) ^-^ (x2, y2) = (x1 ^-^ x2, y1 ^-^ y2)-	neg (x, y) = (neg x, neg y)--instance (Group g1, Group g2, Group g3) => Group (g1, g2, g3) where-	{-# SPECIALIZE instance Group g => Group (g, g, g) #-}-	zero = (zero, zero, zero)-	(x1, y1, z1) ^+^ (x2, y2, z2) = (x1 ^+^ x2, y1 ^+^ y2, z1 ^+^ z2)-	(x1, y1, z1) ^-^ (x2, y2, z2) = (x1 ^-^ x2, y1 ^-^ y2, z1 ^-^ z2)-	neg (x, y, z) = (neg x, neg y, neg z)--instance (Group g1, Group g2, Group g3, Group g4) => Group (g1, g2, g3, g4) where-	{-# SPECIALIZE instance Group g => Group (g, g, g, g) #-}-	zero = (zero, zero, zero, zero)-	(x1, y1, z1, w1) ^+^ (x2, y2, z2, w2) = (x1 ^+^ x2, y1 ^+^ y2, z1 ^+^ z2, w1 ^+^ w2)-	(x1, y1, z1, w1) ^-^ (x2, y2, z2, w2) = (x1 ^-^ x2, y1 ^-^ y2, z1 ^-^ z2, w1 ^-^ w2)-	neg (x, y, z, w) = (neg x, neg y, neg z, neg w)--{-# INLINE gsum #-}--- | Does a summation over the elements of a group.-gsum :: Group g => [g] -> g-gsum = foldr (^+^) zero
− Data/Algebra/Module.hs
@@ -1,109 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, IncoherentInstances, TypeSynonymInstances #-}--module Data.Algebra.Module where--import Data.Ratio-import qualified Data.Map as M-import qualified Data.IntMap as IM--import Data.Algebra.Group-import Data.Algebra.Ring---- | The algebraic structure of a module.  A vector space is a module with coefficients in a field.-class (Ring r, Group m) => Module r m where-	(*^) :: r -> m -> m--instance Module Int Int where-	(*^) = (*)--instance Module Integer Integer where-	(*^) = (*)--instance Module Int Integer where-	(*^) = (*) . fromIntegral--instance Integral a => Module Int (Ratio a) where-	{-# SPECIALIZE instance Module Int Rational #-}-	(*^) = (*) . fromIntegral--instance Integral a => Module Integer (Ratio a) where-	{-# SPECIALIZE instance Module Integer Rational #-}-	(*^) = (*) . fromIntegral--instance Integral a => Module (Ratio a) (Ratio a) where-	{-# SPECIALIZE instance Module Rational Rational #-}-	(*^) = (*)--instance Module Int Double where-	(*^) = (*) . fromIntegral--instance Module Integer Double where-	(*^) = (*) . fromIntegral--instance Integral a => Module (Ratio a) Double where-	{-# SPECIALIZE instance Module Rational Double #-}-	(*^) = (*) . realToFrac--instance Module Double Double where-	(*^) = (*)--instance (Ord g, Group g, Ring r) => Module (GroupRing r g) (GroupRing r g) where-	(*^) = (*#)--instance Module r m => Module r (a -> m) where-	(*^) = fmap . (*^)--instance (Ord k, Module r m) => Module r (M.Map k m) where-	(*^) = fmap . (*^)--instance Module r m => Module r (IM.IntMap m) where-	(*^) = fmap . (*^)--instance (Module r m1, Module r m2) => Module r (m1, m2) where-	{-# SPECIALIZE instance Module r m => Module r (m, m) #-}-	r *^ (a, b) = (r *^ a, r *^ b)--instance (Module r m1, Module r m2, Module r m3) => Module r (m1, m2, m3) where-	{-# SPECIALIZE instance Module r m => Module r (m, m, m) #-}-	r *^ (a, b, c) = (r *^ a, r *^ b, r *^ c)--instance (Module r m1, Module r m2, Module r m3, Module r m4) => Module r (m1, m2, m3, m4) where-	{-# SPECIALIZE instance Module r m => Module r (m, m, m, m) #-}-	r *^ (a, b, c, d) = (r *^ a, r *^ b, r *^ c, r *^ d)---- | @'LinFunc' v c@ is a linear combination of variables of type @v@ with coefficients--- from @c@.  Formally, this is the free @c@-module on @v@.  -type LinFunc = M.Map---- | Given a variable @v@, returns the function equivalent to @v@.-var :: (Ord v, Ring c) => v -> LinFunc v c-var v = M.singleton v one---- | @c '*&' v@ is equivalent to @c '*^' 'var' v@.-(*&) :: (Ord v, Ring c) => c -> v -> LinFunc v c-c *& v = M.singleton v c---- | Equivalent to @'vsum' . 'map' 'var'@.-varSum :: (Ord v, Ring c) => [v] -> LinFunc v c-varSum vs = M.fromList [(v, one) | v <- vs]---- | Given a collection of vectors and scaling coefficients, returns this--- linear combination.-combination :: Module r m => [(r, m)] -> m-combination xs = gsum [r *^ m | (r, m) <- xs]--{-# INLINE linCombination #-}--- | Given a set of basic variables and coefficients, returns the linear combination obtained--- by summing.-linCombination :: (Ord v, Num r) => [(r, v)] -> LinFunc v r-linCombination xs = M.fromListWith (+) [(v, r) | (r, v) <- xs]---- | Substitution into a polynomial.-evalPoly :: (Module r m, Ring m) => Poly r -> m -> m-evalPoly f x = foldr (\ c z -> (c *^ one) ^+^ (x *# z)) zero f--{-# RULES-	"zero/*^" forall m . zero *^ m = zero;-	"*^/zero" forall r . r *^ zero = zero;-	"one/*^" forall m . one *^ m = m;-	#-}
− Data/Algebra/Ring.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE TypeSynonymInstances #-}-module Data.Algebra.Ring where--import Control.Applicative--import Data.Ratio-import qualified Data.Map as M--import Data.Algebra.Group--infixr 6 *#---- | A way of forming a ring from functions.  See <http://en.wikipedia.org/wiki/Group_ring>.-type GroupRing r g = M.Map g r---- | The algebraic structure of a unital ring.  Assumes that the additive operation forms an abelian group,--- that the multiplication operation forms a group, and that multiplication distributes.-class Group r => Ring r where-	one :: r-	(*#) :: r -> r -> r--instance Ring Bool where-	one = True-	(*#) = (&&)--instance Ring Int where-	one = 1-	(*#) = (*)--instance Ring Integer where-	one = 1-	(*#) = (*)--instance Ring Double where-	one = 1-	(*#) = (*)--instance Integral a => Ring (Ratio a) where-	{-# SPECIALIZE instance Ring Rational #-}-	one = 1-	(*#) = (*)---- | The polynomial ring.-instance Ring r => Ring (Poly r) where-	one = [one]-	(p:ps) *# (q:qs) = (p *# q):(ps *# (q:qs) ^+^ map (p *#) qs)-	_ *# _ = []---- | The function ring.-instance Ring r => Ring (a -> r) where-	one = const one-	(*#) = liftA2 (*#)---- | The group ring.-instance (Ord g, Group g, Ring r) => Ring (GroupRing r g) where-	one = M.singleton zero one-	m *# n = M.fromListWith (^+^) [(u ^+^ v, f *# g) | (u, f) <- M.assocs m, (v, g) <- M.assocs n]---- | Returns the polynomial @p(x) = x@.-varPoly :: Ring r => Poly r-varPoly = [zero, one]
Data/LinearProgram/Common.hs view
@@ -2,11 +2,11 @@ -- linear programming libraries are made, this will be common to them all. module Data.LinearProgram.Common ( 	module Data.LinearProgram.Spec,-	module Data.Algebra,+	module Algebra.Classes, 	module Data.LinearProgram.Types) where  import Data.LinearProgram.Spec-import Data.Algebra+import Algebra.Classes import Data.LinearProgram.Types  import Data.Map
Data/LinearProgram/GLPK/IO/Internal.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE ForeignFunctionInterface #-}  module Data.LinearProgram.GLPK.IO.Internal (readGLPLP, writeGLPLP) where-+import Prelude hiding ((+)) import Control.Monad import Control.Monad.Trans (liftIO, lift) @@ -83,7 +83,7 @@ 		3	-> liftM UBound (ub i) 		4	-> liftM2 Bound (lb i) (ub i) 		_	-> liftM Equ (lb i)-		+ getObjCoef :: Int -> GLPK Double getObjCoef = getCDouble glpGetObjCoef @@ -118,7 +118,7 @@ 	sequence_ [do 		bds <- lift $ rowBounds i 		name <- lift $ getRowName i-		maybe constrain constrain' name +		maybe constrain constrain' name 			(linCombination [(v, names ! j) | (j, v) <- row]) bds 			| (i, row) <- rowContents] 	obj <- lift $ sequence [do
Data/LinearProgram/GLPK/Internal.hs view
@@ -7,7 +7,7 @@ 	setObjCoef, setObjectiveDirection, setRowBounds, setRowName, solveSimplex) where-}  import Control.Monad-+import Prelude hiding ((+),(*)) import Foreign.Ptr import Foreign.C import Foreign.Marshal.Array@@ -36,7 +36,7 @@ foreign import ccall unsafe "c_glp_get_row_prim" glpGetRowPrim :: Ptr GlpProb -> CInt -> IO CDouble foreign import ccall unsafe "c_glp_get_col_prim" glpGetColPrim :: Ptr GlpProb -> CInt -> IO CDouble foreign import ccall unsafe "c_glp_set_col_kind" glpSetColKind :: Ptr GlpProb -> CInt -> CInt -> IO ()-foreign import ccall unsafe "c_glp_mip_solve" glpMipSolve :: +foreign import ccall unsafe "c_glp_mip_solve" glpMipSolve :: 	Ptr GlpProb -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> CDouble -> CInt -> IO CInt foreign import ccall unsafe "c_glp_mip_obj_val" glpMIPObjVal :: Ptr GlpProb -> IO CDouble foreign import ccall unsafe "c_glp_mip_row_val" glpMIPRowVal :: Ptr GlpProb -> CInt -> IO CDouble@@ -78,7 +78,7 @@  {-# SPECIALIZE setMatRow :: Int -> [(Int, Double)] -> GLPK (), Int -> [(Int, Int)] -> GLPK () #-} setMatRow :: Real a => Int -> [(Int, a)] -> GLPK ()-setMatRow i row = GLP $ \ lp -> +setMatRow i row = GLP $ \ lp -> 	allocaArray (len+1) $ \ (ixs :: Ptr CInt) -> allocaArray (len+1) $ \ (coeffs :: Ptr CDouble) -> do 		pokeArray ixs (0:map (fromIntegral . fst) row) 		pokeArray coeffs (0:map (realToFrac . snd) row)
Data/LinearProgram/LinExpr.hs view
@@ -1,17 +1,16 @@ {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} module Data.LinearProgram.LinExpr (LinExpr(..), solve, substituteExpr, simplifyExpr, 	constTerm, coeffTerm, funcToExpr) where- import Control.Monad  import Data.LinearProgram.Types-import Data.Algebra+import Algebra.Classes import Data.Functor import Data.Foldable  import Data.Map -import Prelude hiding (lookup, filter, foldr)+import Prelude hiding (lookup, filter, foldr, Num(..), recip)  constTerm :: LinExpr v c -> c constTerm (LinExpr _ c) = c@@ -24,31 +23,35 @@  data LinExpr v c = LinExpr (LinFunc v c) c deriving (Eq, Read, Show) -instance (Ord v, Group c) => Group (LinExpr v c) where+instance (Ord v, Additive c) => Additive (LinExpr v c) where 	zero = LinExpr zero zero-	LinExpr a1 c1 ^+^ LinExpr a2 c2 = LinExpr (a1 ^+^ a2) (c1 ^+^ c2)-	LinExpr a1 c1 ^-^ LinExpr a2 c2 = LinExpr (a1 ^-^ a2) (c1 ^-^ c2)-	neg (LinExpr a c) = LinExpr (neg a) (neg c)+	LinExpr a1 c1 + LinExpr a2 c2 = LinExpr (a1 + a2) (c1 + c2) -instance (Ord v, Module r c) => Module r (LinExpr v c) where-	k *^ LinExpr a c = LinExpr (k *^ a) (k *^ c)+instance (Ord v, Group c) => Group (LinExpr v c) where+	LinExpr a1 c1 - LinExpr a2 c2 = LinExpr (a1 - a2) (c1 - c2)+	negate (LinExpr a c) = LinExpr (negate a) (negate c) +instance (Ord v,AbelianAdditive c) => AbelianAdditive (LinExpr v c)++instance (Ord v, Ring c) => Module c (LinExpr v c) where+	k *^ LinExpr a c = LinExpr (k *^ a) (k * c)+ substituteExpr :: (Ord v, Module c c) => v -> LinExpr v c -> LinExpr v c -> LinExpr v c substituteExpr v expV expr@(LinExpr a c) = case lookup v a of 	Nothing	-> expr-	Just k	-> LinExpr (delete v a) c ^+^ (k *^ expV)+	Just k	-> LinExpr (delete v a) c + (k *^ expV)  simplifyExpr :: (Ord v, Module c c) => LinExpr v c -> Map v (LinExpr v c) -> LinExpr v c simplifyExpr (LinExpr a c) sol =-	foldrWithKey (const (^+^)) (LinExpr (difference a sol) c) (intersectionWith (*^) a sol)+	foldrWithKey (const (+)) (LinExpr (difference a sol) c) (intersectionWith (*^) a sol)  solve :: (Ord v, Eq c, VectorSpace c c) => [(LinFunc v c, c)] -> Maybe (Map v (LinExpr v c))-solve equs = solve' [LinExpr a (neg c) | (a, c) <- equs]+solve equs = solve' [LinExpr a (negate c) | (a, c) <- equs]  solve' :: (Ord v, Eq c, VectorSpace c c) => [LinExpr v c] -> Maybe (Map v (LinExpr v c)) solve' (LinExpr a c:equs) = case minViewWithKey (filter (/= zero) a) of 	Nothing	-> guard (c == zero) >> solve' equs-	Just ((x, a0), a') -> let expX = neg (inv a0 *^ LinExpr a' c) in+	Just ((x, a0), a') -> let expX = negate (recip a0 *^ LinExpr a' c) in 		liftM (simplifyExpr expX >>= insert x) (solve' (substituteExpr x expX <$> equs)) solve' [] = return empty 
Data/LinearProgram/Spec.hs view
@@ -1,17 +1,18 @@ {-# LANGUAGE TupleSections, RecordWildCards, DeriveFunctor #-} module Data.LinearProgram.Spec (Constraint(..), VarTypes, ObjectiveFunc, VarBounds, LP(..),-        mapVars, mapVals, allVars) where+        mapVars, mapVals, allVars, linCombination) where +import Prelude hiding (negate, (+)) import Control.DeepSeq import Control.Monad- import Data.Char (isSpace) import Data.Map hiding (map, foldl)  import Text.ParserCombinators.ReadP -import Data.Algebra+import Algebra.Classes import Data.LinearProgram.Types+import qualified Data.Map as M  -- | Representation of a linear constraint on the variables, possibly labeled. -- The function may be bounded both above and below.@@ -30,6 +31,9 @@ data LP v c = LP {direction :: Direction, objective :: ObjectiveFunc v c, constraints :: [Constraint v c],                   varBounds :: VarBounds v c, varTypes :: VarTypes v} deriving (Read, Show, Functor) +linCombination :: (Ord v, Additive r) => [(r, v)] -> LinFunc v r+linCombination xs = M.fromListWith (+) [(v, r) | (r, v) <- xs]+ allVars :: Ord v => LP v c -> Map v () allVars LP{..} = foldl union ((() <$ objective) `union` (() <$ varBounds) `union` (() <$ varTypes))         [() <$ f | Constr _ f _ <- constraints]@@ -42,27 +46,27 @@         UBound x -> expr ++ " <= " ++ show x         Bound l u -> show l ++ " <= " ++ expr ++ " <= " ++ show u -showFunc :: (Show v, Num c, Ord c, Show c) => LinFunc v c -> String+showFunc :: (Show v, Ord c, Show c, Num c, Group c) => LinFunc v c -> String showFunc func = case assocs func of         []      -> "0"         ((v,c):vcs) ->-                show c ++ " " ++ map replaceSpace (show v) ++ +                show c ++ " " ++ map replaceSpace (show v) ++                         concatMap showTerm vcs         where   showTerm (v, c) = case compare c 0 of                         EQ      -> ""                         GT      -> " + " ++ show c ++ " " ++ show v                         LT      -> " - " ++ show (negate c) ++ " " ++ show v-                + replaceSpace :: Char -> Char replaceSpace c         | isSpace c     = '_'         | otherwise     = c -instance (Show v, Num c, Ord c, Show c) => Show (Constraint v c) where+instance (Show v, Ord c, Show c, Num c, Group c) => Show (Constraint v c) where         show (Constr lab func bds) = maybe "" (++ ": ") lab ++                 showBds (showFunc func) bds -instance (Read v, Ord v, Read c, Ord c, Num c) => Read (Constraint v c) where+instance (Read v, Ord v, Read c, Ord c, Num c, Group c) => Read (Constraint v c) where         readsPrec _= readP_to_S $ liftM toConstr (lab <++ nolab) where                 toConstr (l, f, bds) = Constr l (fromList f) bds                 lab = do        skipSpaces@@ -76,8 +80,8 @@                 readConst = readS_to_P reads                 readVar = readS_to_P reads -readCoef :: Num c => ReadP c -> ReadP c-readCoef readC = between skipSpaces skipSpaces $ +readCoef :: (Num c, Group c) => ReadP c -> ReadP c+readCoef readC = between skipSpaces skipSpaces $         (do     char '+'                 skipSpaces                 readC') <++@@ -121,7 +125,7 @@ -- | Applies the specified function to the variables in the linear program. -- If multiple variables in the original program are mapped to the same variable in the new program, -- in general, we set those variables to all be equal, as follows.--- +-- -- * In linear functions, including the objective function and the constraints, --      coefficients will be added together.  For instance, if @v1,v2@ are mapped to the same --      variable @v'@, then a linear function of the form @c1 *& v1 ^+^ c2 *& v2@ will be mapped to@@ -129,12 +133,12 @@ -- -- * In variable bounds, bounds will be combined.  An error will be thrown if the bounds --      are mutually contradictory.--- +-- -- * In variable kinds, the most restrictive kind will be retained. mapVars :: (Ord v', Ord c, Group c) => (v -> v') -> LP v c -> LP v' c-mapVars f LP{..} =  -        LP{objective = mapKeysWith (^+^) f objective, -                constraints = [Constr lab (mapKeysWith (^+^) f func) bd | Constr lab func bd <- constraints],+mapVars f LP{..} =+        LP{objective = mapKeysWith (+) f objective,+                constraints = [Constr lab (mapKeysWith (+) f func) bd | Constr lab func bd <- constraints],                 varBounds = mapKeysWith mappend f varBounds,                 varTypes = mapKeysWith mappend f varTypes, ..} 
Data/LinearProgram/Types.hs view
@@ -1,9 +1,13 @@ {-# LANGUAGE DeriveFunctor, DeriveGeneric #-}-module Data.LinearProgram.Types (VarKind(..), Direction(..), Bounds(..)) where+module Data.LinearProgram.Types (LinFunc, VarKind(..), Direction(..), Bounds(..)) where  import Control.DeepSeq import Data.Monoid import GHC.Generics+import Data.Map++type LinFunc = Map+  data VarKind = ContVar | IntVar | BinVar deriving (Eq, Ord, Enum, Show, Read, Generic) 
examples/example1.hs view
@@ -1,21 +1,29 @@+import Prelude hiding (Num(..)) -import Data.LinearProgram.LPMonad+import Algebra.Classes+import Control.Monad.LPMonad+import Data.LinearProgram.Common import Data.LinearProgram import Data.LinearProgram.GLPK+import qualified Data.Map as M+import Data.LinearProgram.LinExpr  objFun :: LinFunc String Int objFun = linCombination [(10, "x1"), (6, "x2"), (4, "x3")] +n *& v = linCombination [(n,v)]+ lp :: LP String Int-lp = execLPM $ do	setDirection Max-			setObjective objFun-			leqTo (varSum ["x1", "x2", "x3"]) 100-			leqTo (10 *^ var "x1" ^+^ 4 *& "x2" ^+^ 5 *^ var "x3") 600-			leqTo (linCombination [(2, "x1"), (2, "x2"), (6, "x3")]) 300-			varGeq "x1" 0-			varBds "x2" 0 50-			varGeq "x3" 0-			setVarKind "x1" IntVar-			setVarKind "x2" ContVar+lp = execLPM $ do+  setDirection Max+  setObjective objFun+  leqTo (add $ map (1 *&) ["x1", "x2", "x3"]) 100+  leqTo (10 *& "x1" + 4 *& "x2" + 5 *& "x3") 600+  leqTo (linCombination [(2, "x1"), (2, "x2"), (6, "x3")]) 300+  varGeq "x1" 0+  varBds "x2" 0 50+  varGeq "x3" 0+  setVarKind "x1" IntVar+  setVarKind "x2" ContVar  main = print =<< glpSolveVars mipDefaults lp
glpk-hs.cabal view
@@ -1,5 +1,5 @@ Name:           glpk-hs-Version:        0.3.5+Version:        0.5 Author:         Louis Wasserman License:        BSD3 License-file:   LICENSE@@ -27,14 +27,13 @@   location: https://github.com/jyp/glpk-hs  library-  Build-Depends:    base >= 4 && < 5, array, containers, mtl, deepseq+  Build-Depends:    base >= 4 && < 5, array, containers, mtl, deepseq, gasp   Exposed-modules:  Data.LinearProgram,                     Data.LinearProgram.Common,                     Data.LinearProgram.LinExpr,                     Data.LinearProgram.GLPK,                     Data.LinearProgram.GLPK.Solver,                     Data.LinearProgram.GLPK.IO,-                    Data.Algebra,                     Control.Monad.LPMonad,                     Control.Monad.LPMonad.Supply,                     Control.Monad.LPMonad.Supply.Class@@ -44,10 +43,6 @@                     Data.LinearProgram.GLPK.IO.Internal,                     Control.Monad.LPMonad.Internal,                     Data.LinearProgram.Spec,-                    Data.LinearProgram.Types,-                    Data.Algebra.Group,-                    Data.Algebra.Ring,-                    Data.Algebra.Module,-                    Data.Algebra.Field+                    Data.LinearProgram.Types   c-sources:        glpk/glpk.c   extra-libraries:  glpk