summaryrefslogtreecommitdiff
path: root/packages/glpk
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2010-02-23 18:22:57 +0000
committerAlberto Ruiz <aruiz@um.es>2010-02-23 18:22:57 +0000
commite0605467b60f65478d0f5cc8f82ba14a99168f7b (patch)
tree876e81ae0ee77f4cd01f5729ab35902ec9980789 /packages/glpk
parent5587a094afa3e24698cd38301c805e6ee5876c73 (diff)
error checking for simplex
Diffstat (limited to 'packages/glpk')
-rw-r--r--packages/glpk/examples/simplex1.hs5
-rw-r--r--packages/glpk/examples/simplex2.hs15
-rw-r--r--packages/glpk/examples/simplex3.hs10
-rw-r--r--packages/glpk/examples/simplex4.hs10
-rw-r--r--packages/glpk/lib/Numeric/LinearProgramming.hs98
5 files changed, 74 insertions, 64 deletions
diff --git a/packages/glpk/examples/simplex1.hs b/packages/glpk/examples/simplex1.hs
index 9639f37..ec72bdc 100644
--- a/packages/glpk/examples/simplex1.hs
+++ b/packages/glpk/examples/simplex1.hs
@@ -5,17 +5,16 @@ import Numeric.LinearProgramming
5objFun = Maximize [10, 6, 4] 5objFun = Maximize [10, 6, 4]
6 6
7constr = Dense [ [1,1,1] :<: 100 7constr = Dense [ [1,1,1] :<: 100
8 , [10,4,5] :<: 600 8 , [10,4,5] :<: 600
9 , [2,2,6] :<: 300 ] 9 , [2,2,6] :<: 300 ]
10 10
11-- default bounds 11-- default bounds
12bnds = [ 1 :>: 0 12bnds = [ 1 :>: 0
13 , 2 :>: 0 13 , 2 :>: 0
14 , 3 :>: 0 ] 14 , 3 :>: 0 ]
15 15
16main = do 16main = do
17 print $ simplex objFun constr [] 17 print $ simplex objFun constr []
18 print $ simplex objFun constr bnds 18 print $ simplex objFun constr bnds
19 print $ simplex objFun constr [Free 3] 19 print $ simplex objFun constr [Free 3]
20 print $ simplex objFun constr [ 2 :<: 50 ] 20 print $ simplex objFun constr [ 2 :<: 50 ]
21
diff --git a/packages/glpk/examples/simplex2.hs b/packages/glpk/examples/simplex2.hs
index 40e4bbd..0b865a6 100644
--- a/packages/glpk/examples/simplex2.hs
+++ b/packages/glpk/examples/simplex2.hs
@@ -1,17 +1,18 @@
1import Numeric.LinearProgramming 1import Numeric.LinearProgramming
2 2
3prob = Maximize [4, 3, -2, 7] 3prob = Maximize [4, -3, 2]
4 4
5constr1 = Sparse [ [1#1, 1#2] :<: 10 5constr1 = Sparse [ [2#1, 1#2] :<: 10
6 , [1#3, 1#4] :<: 10 6 , [1#2, 5#3] :<: 20
7 ] 7 ]
8 8
9constr2 = Dense [ [1,1,0,0] :<: 10 9constr2 = Dense [ [2,1,0] :<: 10
10 , [0,0,1,1] :<: 10 10 , [0,1,5] :<: 20
11 ] 11 ]
12 12
13main = do 13main = do
14 print $ simplex prob constr1 [] 14 print $ simplex prob constr1 []
15 print $ simplex prob constr2 [ 2 :>: 1, 4 :&: (2,7)] 15 print $ simplex prob constr2 []
16 print $ simplex prob constr2 [ Free 3 ] 16 print $ simplex prob constr2 [ 2 :>: 1, 3 :&: (2,7)]
17 print $ simplex prob constr2 [ Free 2 ]
17 18
diff --git a/packages/glpk/examples/simplex3.hs b/packages/glpk/examples/simplex3.hs
index 3a7e8e8..1df6b28 100644
--- a/packages/glpk/examples/simplex3.hs
+++ b/packages/glpk/examples/simplex3.hs
@@ -7,12 +7,12 @@ prob = Minimize [0.03, 0.08, 0.17, 0.12, 0.15, 0.21, 0.38]
7 7
8constr = Dense 8constr = Dense
9 [ [1,1,1,1,1,1,1] :==: 2000 9 [ [1,1,1,1,1,1,1] :==: 2000
10 , [0.15, 0.04, 0.02, 0.04, 0.2,0.01, 0.03] :<: 60 10 , [0.15, 0.04, 0.02, 0.04, 0.2,0.01, 0.03] :<: 60
11 , [0.03, 0.05, 0.08, 0.02, 0.06, 0.01, 0] :<: 100 11 , [0.03, 0.05, 0.08, 0.02, 0.06, 0.01, 0] :<: 100
12 , [0.02, 0.04, 0.01, 0.02, 0.02, 0, 0] :<: 40 12 , [0.02, 0.04, 0.01, 0.02, 0.02, 0, 0] :<: 40
13 , [0.02, 0.03, 0, 0, 0.01, 0, 0] :<: 30 13 , [0.02, 0.03, 0, 0, 0.01, 0, 0] :<: 30
14 , [0.7, 0.75, 0.8, 0.75, 0.8, 0.97, 0] :>: 1500 14 , [0.7, 0.75, 0.8, 0.75, 0.8, 0.97, 0] :>: 1500
15 , [0.02, 0.06, 0.08, 0.12, 0.02, 0.01, 0.97] :&: (250,300) 15 , [0.02, 0.06, 0.08, 0.12, 0.02, 0.01, 0.97] :&: (250,300)
16 ] 16 ]
17 17
18bounds = [ 1 :&: (0,200) 18bounds = [ 1 :&: (0,200)
diff --git a/packages/glpk/examples/simplex4.hs b/packages/glpk/examples/simplex4.hs
index 8496f6d..dd65002 100644
--- a/packages/glpk/examples/simplex4.hs
+++ b/packages/glpk/examples/simplex4.hs
@@ -7,12 +7,12 @@ prob = Minimize [0.03, 0.08, 0.17, 0.12, 0.15, 0.21, 0.38]
7 7
8constr = Sparse 8constr = Sparse
9 [ [1#1,1#2,1#3,1#4,1#5,1#6,1#7] :==: 2000 9 [ [1#1,1#2,1#3,1#4,1#5,1#6,1#7] :==: 2000
10 , [0.15#1, 0.04#2, 0.02#3, 0.04#4, 0.2#5,0.01#6, 0.03#7] :<: 60 10 , [0.15#1, 0.04#2, 0.02#3, 0.04#4, 0.2#5,0.01#6, 0.03#7] :<: 60
11 , [0.03#1, 0.05#2, 0.08#3, 0.02#4, 0.06#5, 0.01#6] :<: 100 11 , [0.03#1, 0.05#2, 0.08#3, 0.02#4, 0.06#5, 0.01#6] :<: 100
12 , [0.02#1, 0.04#2, 0.01#3, 0.02#4, 0.02#5] :<: 40 12 , [0.02#1, 0.04#2, 0.01#3, 0.02#4, 0.02#5] :<: 40
13 , [0.02#1, 0.03#2, 0.01#5] :<: 30 13 , [0.02#1, 0.03#2, 0.01#5] :<: 30
14 , [0.7#1, 0.75#2, 0.8#3, 0.75#4, 0.8#5, 0.97#6] :>: 1500 14 , [0.7#1, 0.75#2, 0.8#3, 0.75#4, 0.8#5, 0.97#6] :>: 1500
15 , [0.02#1, 0.06#2, 0.08#3, 0.12#4, 0.02#5, 0.01#6, 0.97#7] :&: (250,300) 15 , [0.02#1, 0.06#2, 0.08#3, 0.12#4, 0.02#5, 0.01#6, 0.97#7] :&: (250,300)
16 ] 16 ]
17 17
18bounds = [ 1 :&: (0,200) 18bounds = [ 1 :&: (0,200)
diff --git a/packages/glpk/lib/Numeric/LinearProgramming.hs b/packages/glpk/lib/Numeric/LinearProgramming.hs
index fff304f..a888214 100644
--- a/packages/glpk/lib/Numeric/LinearProgramming.hs
+++ b/packages/glpk/lib/Numeric/LinearProgramming.hs
@@ -10,13 +10,13 @@ Stability : provisional
10 10
11This module provides an interface to the standard simplex algorithm. 11This module provides an interface to the standard simplex algorithm.
12 12
13For example, the following linear programming problem 13For example, the following LP problem
14 14
15@maximize 4 x_1 + 3 x_2 - 2 x_3 + 7 x_4 15@maximize 4 x_1 - 3 x_2 + 2 x_3
16subject to 16subject to
17 17
18x_1 + x_2 <= 10 182 x_1 + x_2 <= 10
19x_3 + x_4 <= 10 19 x_3 + 5 x_4 <= 20
20 20
21and 21and
22 22
@@ -26,31 +26,33 @@ can be solved as follows:
26 26
27@import Numeric.LinearProgramming 27@import Numeric.LinearProgramming
28 28
29prob = Maximize [4, 3, -2, 7] 29prob = Maximize [4, -3, 2]
30 30
31constr1 = Sparse [ [1\#1, 1\#2] :<: 10 31constr1 = Sparse [ [2#1, 1#2] :<: 10
32 , [1\#3, 1\#4] :<: 10 32 , [1#2, 5#3] :<: 20
33 ] 33 ]
34
35 34
36\> simplex prob constr1 [] 35\> simplex prob constr1 []
37Optimal (110.0,[10.0,0.0,0.0,10.0])@ 36Optimal (28.0,[5.0,0.0,4.0])@
38 37
39The coefficients of the constraint matrix can also be given in dense format: 38The coefficients of the constraint matrix can also be given in dense format:
40 39
41@constr2 = Dense [ [1,1,0,0] :<: 10 40@constr2 = Dense [ [2,1,0] :<: 10
42 , [0,0,1,1] :<: 10 41 , [0,1,5] :<: 20
43 ]@ 42 ]@
44 43
45By default all variables are bounded as @x_i <= 0@, but this can be 44By default all variables are bounded as @x_i >= 0@, but this can be
46changed: 45changed:
47 46
48@\> simplex prob constr2 [2 :>: 1, 4 :&: (2,7)] 47@\> simplex prob constr2 [ 2 :>: 1, 3 :&: (2,7)]
49Optimal (88.0,[9.0,1.0,0.0,7.0]) 48Optimal (22.6,[4.5,1.0,3.8])
50 49
51\> simplex prob constr2 [Free 3] 50\> simplex prob constr2 [Free 2]
52Unbounded@ 51Unbounded@
53 52
53The given bound for a variable completely replaces the default,
54so @0 <= x_i <= b@ must be explicitly given as @i :&: (0,b)@.
55
54-} 56-}
55 57
56module Numeric.LinearProgramming( 58module Numeric.LinearProgramming(
@@ -94,7 +96,7 @@ data Solution = Undefined
94 | Optimal (Double, [Double]) 96 | Optimal (Double, [Double])
95 | Unbounded 97 | Unbounded
96 deriving Show 98 deriving Show
97 99
98data Constraints = Dense [ Bound [Double] ] 100data Constraints = Dense [ Bound [Double] ]
99 | Sparse [ Bound [(Double,Int)] ] 101 | Sparse [ Bound [(Double,Int)] ]
100 102
@@ -105,19 +107,25 @@ type Bounds = [Bound Int]
105 107
106simplex :: Optimization -> Constraints -> Bounds -> Solution 108simplex :: Optimization -> Constraints -> Bounds -> Solution
107 109
110simplex opt (Dense []) bnds = simplex opt (Sparse [Free [0#1]]) bnds
111simplex opt (Sparse []) bnds = simplex opt (Sparse [Free [0#1]]) bnds
112
108simplex opt (Dense constr) bnds = extract sg sol where 113simplex opt (Dense constr) bnds = extract sg sol where
109 sol = simplexDense (mkConstrD objfun constr) (mkBoundsD constr bnds) 114 sol = simplexDense (mkConstrD sz objfun constr) (mkBounds sz constr bnds)
110 (sg, objfun) = case opt of 115 (sz, sg, objfun) = adapt opt
111 Maximize x -> (1 ,x)
112 Minimize x -> (-1, (map negate x))
113 116
114simplex opt (Sparse constr) bnds = extract sg sol where 117simplex opt (Sparse constr) bnds = extract sg sol where
115 sol = simplexSparse m n (mkConstrS objfun constr) (mkBoundsS constr bnds) 118 sol = simplexSparse m n (mkConstrS sz objfun constr) (mkBounds sz constr bnds)
116 n = length objfun 119 n = length objfun
117 m = length constr 120 m = length constr
118 (sg, objfun) = case opt of 121 (sz, sg, objfun) = adapt opt
119 Maximize x -> (1 ,x) 122
120 Minimize x -> (-1, (map negate x)) 123adapt :: Optimization -> (Int, Double, [Double])
124adapt opt = case opt of
125 Maximize x -> (size x, 1 ,x)
126 Minimize x -> (size x, -1, (map negate x))
127 where size x | null x = error "simplex: objective function with zero variables"
128 | otherwise = length x
121 129
122extract :: Double -> Vector Double -> Solution 130extract :: Double -> Vector Double -> Solution
123extract sg sol = r where 131extract sg sol = r where
@@ -168,31 +176,33 @@ mkBound1 b = [tb b, lb b, ub b]
168mkBound2 :: Bound t -> (t, [Double]) 176mkBound2 :: Bound t -> (t, [Double])
169mkBound2 b = (obj b, mkBound1 b) 177mkBound2 b = (obj b, mkBound1 b)
170 178
171mkBoundsD :: [Bound [a]] -> [Bound Int] -> Matrix Double 179mkBounds :: Int -> [Bound [a]] -> [Bound Int] -> Matrix Double
172mkBoundsD b1 b2 = fromLists (cb++vb) where 180mkBounds n b1 b2 = fromLists (cb++vb) where
173 c = length (obj (head b1))
174 gv = map obj b2 181 gv = map obj b2
175 rv = [1..c] \\ gv 182 rv | null gv || minimum gv >= 0 && maximum gv <= n = [1..n] \\ gv
183 | otherwise = error $ "simplex: bounds: variables "++show gv++" not in 1.."++show n
176 vb = map snd $ sortBy (compare `on` fst) $ map (mkBound2 . (:>: 0)) rv ++ map mkBound2 b2 184 vb = map snd $ sortBy (compare `on` fst) $ map (mkBound2 . (:>: 0)) rv ++ map mkBound2 b2
177 cb = map mkBound1 b1 185 cb = map mkBound1 b1
178 186
179mkConstrD :: [Double] -> [Bound [Double]] -> Matrix Double 187mkConstrD :: Int -> [Double] -> [Bound [Double]] -> Matrix Double
180mkConstrD f b1 = fromLists (f : map obj b1) 188mkConstrD n f b1 | ok = fromLists (f : cs)
181 189 | otherwise = error $ "simplex: dense constraints require "++show n
182mkBoundsS :: [Bound [(Double, Int)]] -> [Bound Int] -> Matrix Double 190 ++" variables, given " ++ show ls
183mkBoundsS b1 b2 = fromLists (cb++vb) where 191 where
184 c = maximum $ map snd $ concatMap obj b1 192 cs | null b1 = error $ "simplex: dense: empty constraints"
185 gv = map obj b2 193 | otherwise = map obj b1
186 rv = [1..c] \\ gv 194 ls = map length cs
187 vb = map snd $ sortBy (compare `on` fst) $ map (mkBound2 . (:>: 0)) rv ++ map mkBound2 b2 195 ok = all (==n) ls
188 cb = map mkBound1 b1 196
189 197mkConstrS :: Int -> [Double] -> [Bound [(Double, Int)]] -> Matrix Double
190mkConstrS :: [Double] -> [Bound [(Double, Int)]] -> Matrix Double 198mkConstrS n objfun b1 = fromLists (ob ++ co) where
191mkConstrS objfun constr = fromLists (ob ++ co) where
192 ob = map (([0,0]++).return) objfun 199 ob = map (([0,0]++).return) objfun
193 co = concat $ zipWith f [1::Int ..] (map obj constr) 200 co = concat $ zipWith f [1::Int ..] cs
201 cs | null b1 = error $ "simplex: sparse: empty constraints"
202 | otherwise = map obj b1
194 f k = map (g k) 203 f k = map (g k)
195 g k (c,v) = [fromIntegral k, fromIntegral v,c] 204 g k (c,v) | v >=1 && v<= n = [fromIntegral k, fromIntegral v,c]
205 | otherwise = error $ "simplex: sparse constraints: variable "++show v++" not in 1.."++show n
196 206
197----------------------------------------------------- 207-----------------------------------------------------
198 208
@@ -262,6 +272,6 @@ bounds = (6><3)
262 , glpLO,0,0 272 , glpLO,0,0
263 , glpLO,0,0 273 , glpLO,0,0
264 , glpLO,0,0 ] 274 , glpLO,0,0 ]
265 275
266-} 276-}
267 277