summaryrefslogtreecommitdiff
path: root/packages/glpk/lib
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2010-02-21 18:26:23 +0000
committerAlberto Ruiz <aruiz@um.es>2010-02-21 18:26:23 +0000
commitf38b4a3076cfae023559ce61cb2a443c809b7a6f (patch)
tree022c127181fb65c34705cdcf44221b4ac89ba50b /packages/glpk/lib
parenta3d1bb34ae7b1f97b7e9900fc38f145094fe4777 (diff)
simple glpk interface
Diffstat (limited to 'packages/glpk/lib')
-rw-r--r--packages/glpk/lib/Numeric/LinearProgramming.hs211
-rw-r--r--packages/glpk/lib/Numeric/LinearProgramming/glpk.c147
2 files changed, 358 insertions, 0 deletions
diff --git a/packages/glpk/lib/Numeric/LinearProgramming.hs b/packages/glpk/lib/Numeric/LinearProgramming.hs
new file mode 100644
index 0000000..1b14080
--- /dev/null
+++ b/packages/glpk/lib/Numeric/LinearProgramming.hs
@@ -0,0 +1,211 @@
1{-# LANGUAGE ForeignFunctionInterface #-}
2
3module Numeric.LinearProgramming(
4 Optimization(..),
5 Bound(..),
6 (#),
7 Coeffs(..),
8 Solution(..),
9 simplex,
10) where
11
12import Numeric.LinearAlgebra
13import Data.Packed.Development
14import Foreign(Ptr,unsafePerformIO)
15import Foreign.C.Types(CInt)
16import Data.List((\\),sortBy)
17import Data.Function(on)
18
19--import Debug.Trace
20--debug x = trace (show x) x
21
22-----------------------------------------------------
23
24-- | Coefficient of a variable
25(#) :: Double -> Int -> (Double,Int)
26infixl 5 #
27(#) = (,)
28
29data Bound x = x :<: Double
30 | x :>: Double
31 | x :&: (Double,Double)
32 | x :==: Double
33 | Free x
34 deriving Show
35
36data Solution = Undefined
37 | Feasible (Double, [Double])
38 | Infeasible (Double, [Double])
39 | NoFeasible
40 | Optimal (Double, [Double])
41 | Unbounded
42 deriving Show
43
44data Coeffs = Dense [ Bound [Double] ]
45 | Sparse [ Bound [(Double,Int)] ]
46
47data Optimization = Maximize [Double]
48 | Minimize [Double]
49
50simplex :: Optimization -> Coeffs -> [Bound Int] -> Solution
51
52simplex opt (Dense constr) bnds = extract sg sol where
53 sol = simplexDense (mkConstrD objfun constr) (mkBoundsD constr bnds)
54 (sg, objfun) = case opt of
55 Maximize x -> (1 ,x)
56 Minimize x -> (-1, (map negate x))
57
58simplex opt (Sparse constr) bnds = extract sg sol where
59 sol = simplexSparse m n (mkConstrS objfun constr) (mkBoundsS constr bnds)
60 n = length objfun
61 m = length constr
62 (sg, objfun) = case opt of
63 Maximize x -> (1 ,x)
64 Minimize x -> (-1, (map negate x))
65
66extract :: Double -> Vector Double -> Solution
67extract sg sol = r where
68 z = sg * (sol@>1)
69 v = toList $ subVector 2 (dim sol -2) sol
70 r = case round(sol@>0)::Int of
71 1 -> Undefined
72 2 -> Feasible (z,v)
73 3 -> Infeasible (z,v)
74 4 -> NoFeasible
75 5 -> Optimal (z,v)
76 6 -> Unbounded
77 _ -> error "simplex: solution type unknown"
78
79-----------------------------------------------------
80
81obj :: Bound t -> t
82obj (x :<: _) = x
83obj (x :>: _) = x
84obj (x :&: _) = x
85obj (x :==: _) = x
86obj (Free x) = x
87
88tb :: Bound t -> Double
89tb (_ :<: _) = glpUP
90tb (_ :>: _) = glpLO
91tb (_ :&: _) = glpDB
92tb (_ :==: _) = glpFX
93tb (Free _) = glpFR
94
95lb :: Bound t -> Double
96lb (_ :<: _) = 0
97lb (_ :>: a) = a
98lb (_ :&: (a,_)) = a
99lb (_ :==: a) = a
100lb (Free _) = 0
101
102ub :: Bound t -> Double
103ub (_ :<: a) = a
104ub (_ :>: _) = 0
105ub (_ :&: (_,a)) = a
106ub (_ :==: a) = a
107ub (Free _) = 0
108
109mkBound1 :: Bound t -> [Double]
110mkBound1 b = [tb b, lb b, ub b]
111
112mkBound2 :: Bound t -> (t, [Double])
113mkBound2 b = (obj b, mkBound1 b)
114
115mkBoundsD :: [Bound [a]] -> [Bound Int] -> Matrix Double
116mkBoundsD b1 b2 = fromLists (cb++vb) where
117 c = length (obj (head b1))
118 gv = map obj b2
119 rv = [1..c] \\ gv
120 vb = map snd $ sortBy (compare `on` fst) $ map (mkBound2 . (:>: 0)) rv ++ map mkBound2 b2
121 cb = map mkBound1 b1
122
123mkConstrD :: [Double] -> [Bound [Double]] -> Matrix Double
124mkConstrD f b1 = fromLists (f : map obj b1)
125
126mkBoundsS :: [Bound [(Double, Int)]] -> [Bound Int] -> Matrix Double
127mkBoundsS b1 b2 = fromLists (cb++vb) where
128 c = maximum $ map snd $ concatMap obj b1
129 gv = map obj b2
130 rv = [1..c] \\ gv
131 vb = map snd $ sortBy (compare `on` fst) $ map (mkBound2 . (:>: 0)) rv ++ map mkBound2 b2
132 cb = map mkBound1 b1
133
134mkConstrS :: [Double] -> [Bound [(Double, Int)]] -> Matrix Double
135mkConstrS objfun constr = fromLists (ob ++ co) where
136 ob = map (([0,0]++).return) objfun
137 co = concat $ zipWith f [1::Int ..] (map obj constr)
138 f k = map (g k)
139 g k (c,v) = [fromIntegral k, fromIntegral v,c]
140
141-----------------------------------------------------
142
143foreign import ccall "c_simplex_dense" c_simplex_dense
144 :: CInt -> CInt -> Ptr Double -- coeffs
145 -> CInt -> CInt -> Ptr Double -- bounds
146 -> CInt -> Ptr Double -- result
147 -> IO CInt -- exit code
148
149simplexDense :: Matrix Double -> Matrix Double -> Vector Double
150simplexDense c b = unsafePerformIO $ do
151 s <- createVector (2+cols c)
152 app3 c_simplex_dense mat (cmat c) mat (cmat b) vec s "c_simplex_dense"
153 return s
154
155foreign import ccall "c_simplex_sparse" c_simplex_sparse
156 :: CInt -> CInt -- rows and cols
157 -> CInt -> CInt -> Ptr Double -- coeffs
158 -> CInt -> CInt -> Ptr Double -- bounds
159 -> CInt -> Ptr Double -- result
160 -> IO CInt -- exit code
161
162simplexSparse :: Int -> Int -> Matrix Double -> Matrix Double -> Vector Double
163simplexSparse m n c b = unsafePerformIO $ do
164 s <- createVector (2+n)
165 let fi = fromIntegral
166 app3 (c_simplex_sparse (fi m) (fi n)) mat (cmat c) mat (cmat b) vec s "c_simplex_sparse"
167 return s
168
169glpFR, glpLO, glpUP, glpDB, glpFX :: Double
170glpFR = 0
171glpLO = 1
172glpUP = 2
173glpDB = 3
174glpFX = 4
175
176{- Raw format of coeffs
177
178simplexDense
179
180((3+1) >< 3)
181 [ 10, 6, 4
182 , 1, 1, 1
183 , 10, 4, 5
184 , 2, 2, 6 :: Double]
185
186simplexSparse
187
188(12><3)
189 [ 0.0, 0.0, 10.0
190 , 0.0, 0.0, 6.0
191 , 0.0, 0.0, 4.0
192 , 1.0, 1.0, 1.0
193 , 1.0, 2.0, 1.0
194 , 1.0, 3.0, 1.0
195 , 2.0, 1.0, 10.0
196 , 2.0, 2.0, 4.0
197 , 2.0, 3.0, 5.0
198 , 3.0, 1.0, 2.0
199 , 3.0, 2.0, 2.0
200 , 3.0, 3.0, 6.0 ]
201
202bounds = (6><3)
203 [ glpUP,0,100
204 , glpUP,0,600
205 , glpUP,0,300
206 , glpLO,0,0
207 , glpLO,0,0
208 , glpLO,0,0 ]
209
210-}
211
diff --git a/packages/glpk/lib/Numeric/LinearProgramming/glpk.c b/packages/glpk/lib/Numeric/LinearProgramming/glpk.c
new file mode 100644
index 0000000..0f4ad79
--- /dev/null
+++ b/packages/glpk/lib/Numeric/LinearProgramming/glpk.c
@@ -0,0 +1,147 @@
1typedef struct { double r, i; } doublecomplex;
2
3#define DVEC(A) int A##n, double*A##p
4#define CVEC(A) int A##n, doublecomplex*A##p
5#define DMAT(A) int A##r, int A##c, double*A##p
6#define CMAT(A) int A##r, int A##c, doublecomplex*A##p
7
8#define AT(M,r,co) (M##p[(r)*M##c+(co)])
9
10/*-----------------------------------------------------*/
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <glpk.h>
15#include <math.h>
16
17int c_simplex_dense(DMAT(c), DMAT(b), DVEC(s)) {
18 glp_prob *lp;
19 lp = glp_create_prob();
20 glp_set_obj_dir(lp, GLP_MAX);
21
22 int m = cr-1;
23 int n = cc;
24 glp_add_rows(lp, m);
25 glp_add_cols(lp, n);
26 int * ia = malloc((1+m*n)*sizeof(int));
27 int * ja = malloc((1+m*n)*sizeof(int));
28 double * ar = malloc((1+m*n)*sizeof(double));
29 int i,j,k;
30 k=0;
31 for (i=1;i<=m;i++) {
32 for(j=1;j<=n;j++) {
33 k++;
34 ia[k] = i;
35 ja[k] = j;
36 ar[k] = AT(c,i,j-1);
37 //printf("%d %d %f\n",ia[k],ja[k],ar[k]);
38 }
39 }
40 glp_load_matrix(lp, k, ia, ja, ar);
41 for (j=1;j<=n;j++) {
42 glp_set_obj_coef(lp, j, AT(c,0,j-1));
43 }
44 int t;
45 for (i=1;i<=m;i++) {
46 switch((int)rint(AT(b,i-1,0))) {
47 case 0: { t = GLP_FR; break; }
48 case 1: { t = GLP_LO; break; }
49 case 2: { t = GLP_UP; break; }
50 case 3: { t = GLP_DB; break; }
51 default: { t = GLP_FX; break; }
52 }
53 glp_set_row_bnds(lp, i, t , AT(b,i-1,1), AT(b,i-1,2));
54 }
55 for (j=1;j<=n;j++) {
56 switch((int)rint(AT(b,m+j-1,0))) {
57 case 0: { t = GLP_FR; break; }
58 case 1: { t = GLP_LO; break; }
59 case 2: { t = GLP_UP; break; }
60 case 3: { t = GLP_DB; break; }
61 default: { t = GLP_FX; break; }
62 }
63 glp_set_col_bnds(lp, j, t , AT(b,m+j-1,1), AT(b,m+j-1,2));
64 }
65 glp_term_out(0);
66 glp_simplex(lp, NULL);
67 sp[0] = glp_get_status(lp);
68 sp[1] = glp_get_obj_val(lp);
69 for (k=1; k<=n; k++) {
70 sp[k+1] = glp_get_col_prim(lp, k);
71 }
72
73 glp_delete_prob(lp);
74 free(ia);
75 free(ja);
76 free(ar);
77
78 return 0;
79}
80
81/* ---------------------------------------------------- */
82
83int c_simplex_sparse(int m, int n, DMAT(c), DMAT(b), DVEC(s)) {
84 glp_prob *lp;
85 lp = glp_create_prob();
86 glp_set_obj_dir(lp, GLP_MAX);
87 int i,j,k;
88 int tot = cr - n;
89 glp_add_rows(lp, m);
90 glp_add_cols(lp, n);
91
92 //printf("%d %d\n",m,n);
93
94 // the first n values
95 for (k=1;k<=n;k++) {
96 glp_set_obj_coef(lp, k, AT(c, k-1, 2));
97 //printf("%d %f\n",k,AT(c, k-1, 2));
98 }
99
100 int * ia = malloc((1+tot)*sizeof(int));
101 int * ja = malloc((1+tot)*sizeof(int));
102 double * ar = malloc((1+tot)*sizeof(double));
103
104 for (k=1; k<= tot; k++) {
105 ia[k] = rint(AT(c,k-1+n,0));
106 ja[k] = rint(AT(c,k-1+n,1));
107 ar[k] = AT(c,k-1+n,2);
108 //printf("%d %d %f\n",ia[k],ja[k],ar[k]);
109 }
110 glp_load_matrix(lp, tot, ia, ja, ar);
111
112 int t;
113 for (i=1;i<=m;i++) {
114 switch((int)rint(AT(b,i-1,0))) {
115 case 0: { t = GLP_FR; break; }
116 case 1: { t = GLP_LO; break; }
117 case 2: { t = GLP_UP; break; }
118 case 3: { t = GLP_DB; break; }
119 default: { t = GLP_FX; break; }
120 }
121 glp_set_row_bnds(lp, i, t , AT(b,i-1,1), AT(b,i-1,2));
122 }
123 for (j=1;j<=n;j++) {
124 switch((int)rint(AT(b,m+j-1,0))) {
125 case 0: { t = GLP_FR; break; }
126 case 1: { t = GLP_LO; break; }
127 case 2: { t = GLP_UP; break; }
128 case 3: { t = GLP_DB; break; }
129 default: { t = GLP_FX; break; }
130 }
131 glp_set_col_bnds(lp, j, t , AT(b,m+j-1,1), AT(b,m+j-1,2));
132 }
133 glp_term_out(0);
134 glp_simplex(lp, NULL);
135 sp[0] = glp_get_status(lp);
136 sp[1] = glp_get_obj_val(lp);
137 for (k=1; k<=n; k++) {
138 sp[k+1] = glp_get_col_prim(lp, k);
139 }
140 glp_delete_prob(lp);
141 free(ia);
142 free(ja);
143 free(ar);
144
145 return 0;
146}
147