aboutsummaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2012-08-07 07:09:21 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-02-12 06:49:40 -0500
commitf79777a2c66301c6b8f7ec757f02b4b13e640d94 (patch)
tree9e37d92fd2ba0e94241ac133352f1f469454580d /native
parentc2c3126de5fc548db5821081af265bb8cf69cebd (diff)
Add GLPK Integration
Add a bridge to the GLPK library. Availability is auto-discovered by the build system. Most of the code is solver-agnostic.
Diffstat (limited to 'native')
-rw-r--r--native/Makefile37
-rw-r--r--native/include/linprog/glpk.h8
-rw-r--r--native/include/linprog/solver.h15
-rw-r--r--native/include/lp_common.h2
-rw-r--r--native/src/blocking/linprog/lp_dflp.cpp4
-rw-r--r--native/src/blocking/linprog/lp_dpcp.cpp4
-rw-r--r--native/src/linprog/glpk.cpp206
-rw-r--r--native/src/testmain.cpp3
8 files changed, 267 insertions, 12 deletions
diff --git a/native/Makefile b/native/Makefile
index 6d2a144..36cb08f 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -55,15 +55,33 @@ ifneq ($(CPLEX),)
55# The CPLEX variable now contains the canonicalized path to the cplex 55# The CPLEX variable now contains the canonicalized path to the cplex
56# binary. From this, we can extract the include and library paths. 56# binary. From this, we can extract the include and library paths.
57CPLEX_DIR := ${realpath ${dir $(CPLEX)}/../..} 57CPLEX_DIR := ${realpath ${dir $(CPLEX)}/../..}
58CPLEX_PATH ?= $(CPLEX_DIR)
59endif
58 60
59${info Found CPLEX installation in $(CPLEX_DIR).} 61ifneq ($(CPLEX_PATH),)
60 62${info Linking with CPLEX installation in $(CPLEX_DIR).}
61# Add headers, libraries, and definitions. 63# Add headers, libraries, and definitions.
62INCLUDES += -I$(CPLEX_DIR)/include/ 64INCLUDES += -I$(CPLEX_PATH)/include/
63LIBS += -lilocplex -lcplex -lconcert 65LIBS += -lilocplex -lcplex -lconcert
64DEFS += -DCONFIG_HAVE_CPLEX 66DEFS += -DCONFIG_HAVE_CPLEX
65endif 67endif
66 68
69
70# #### GLPK Support ####
71
72GLPK := ${realpath ${shell which glpsol}}
73ifneq ($(GLPK),)
74GLPK_DIR :=${realpath ${dir $(GLPK)}/..}
75GLPK_PATH ?= $(GLPK_DIR)
76endif
77
78ifneq ($(GLPK_PATH),)
79${info Linking with GLPK installed at prefix=$(GLPK_DIR).}
80INCLUDES += -I$(GLPK_PATH)/include
81LIBS += -L$(GLPK_PATH)/lib -lglpk
82DEFS += -DCONFIG_HAVE_GLPK
83endif
84
67# #### Debug support #### 85# #### Debug support ####
68ifeq ($(DEBUG),y) 86ifeq ($(DEBUG),y)
69DEFS += -g -DDEBUG 87DEFS += -g -DDEBUG
@@ -99,9 +117,16 @@ SYNC_OBJ += rw-phase-fair.o rw-task-fair.o
99ALL = testmain _sched.so _locking.so _sim.so 117ALL = testmain _sched.so _locking.so _sim.so
100 118
101# Compile LP-based code only if we have a solver. 119# Compile LP-based code only if we have a solver.
102ifneq ($(CPLEX),) 120ifneq ($(CPLEX_PATH)$(GLPK_PATH),)
103LP_OBJ = lp_common.o lp_dflp.o lp_dpcp.o 121LP_OBJ = lp_common.o io.o lp_dflp.o lp_dpcp.o
104LP_OBJ += cplex.o io.o 122
123ifneq ($(CPLEX_PATH),)
124LP_OBJ += cplex.o
125endif
126
127ifneq ($(GLPK_PATH),)
128LP_OBJ += glpk.o
129endif
105 130
106ALL += _lp_analysis.so 131ALL += _lp_analysis.so
107endif 132endif
diff --git a/native/include/linprog/glpk.h b/native/include/linprog/glpk.h
new file mode 100644
index 0000000..fa2aec9
--- /dev/null
+++ b/native/include/linprog/glpk.h
@@ -0,0 +1,8 @@
1#ifndef LINPROG_GLPK_H
2#define LINPROG_GLPK_H
3
4#include "linprog/solver.h"
5
6Solution *glpk_solve(const LinearProgram& lp, unsigned int max_num_vars);
7
8#endif
diff --git a/native/include/linprog/solver.h b/native/include/linprog/solver.h
index 15e37e6..0129903 100644
--- a/native/include/linprog/solver.h
+++ b/native/include/linprog/solver.h
@@ -24,6 +24,21 @@ public:
24 } 24 }
25}; 25};
26 26
27#if defined(CONFIG_HAVE_GLPK)
27 28
29#include "linprog/glpk.h"
30#define linprog_solve(lp, vars) glpk_solve((lp), (vars))
31
32#elif defined(CONFIG_HAVE_CPLEX)
33
34#include "linprog/cplex.h"
35#define linprog_solve(lp, vars) cplex_solve((lp), (vars))
36
37#else
38
39#warning No LP solver available.
40#define linprog_solve(lp, vars) assert(0)
41
42#endif
28 43
29#endif 44#endif
diff --git a/native/include/lp_common.h b/native/include/lp_common.h
index d5a8a60..16aad8a 100644
--- a/native/include/lp_common.h
+++ b/native/include/lp_common.h
@@ -10,7 +10,7 @@
10#include "stl-hashmap.h" 10#include "stl-hashmap.h"
11 11
12#include "linprog/model.h" 12#include "linprog/model.h"
13#include "linprog/cplex.h" 13#include "linprog/solver.h"
14 14
15enum blocking_type 15enum blocking_type
16{ 16{
diff --git a/native/src/blocking/linprog/lp_dflp.cpp b/native/src/blocking/linprog/lp_dflp.cpp
index 6198825..0370358 100644
--- a/native/src/blocking/linprog/lp_dflp.cpp
+++ b/native/src/blocking/linprog/lp_dflp.cpp
@@ -153,7 +153,7 @@ static BlockingBounds* _lp_dflp_bounds(const ResourceSharingInfo& info,
153#endif 153#endif
154 154
155 // Solve the big, combined LP. 155 // Solve the big, combined LP.
156 Solution *sol = cplex_solve(lp, var_idx); 156 Solution *sol = linprog_solve(lp, var_idx);
157 157
158 assert(sol != NULL); 158 assert(sol != NULL);
159 159
@@ -225,7 +225,7 @@ static void apply_dflp_bounds_for_task(
225 solver_cost.start(); 225 solver_cost.start();
226#endif 226#endif
227 227
228 Solution *sol = cplex_solve(lp, vars.get_num_vars()); 228 Solution *sol = linprog_solve(lp, vars.get_num_vars());
229 229
230#if DEBUG_LP_OVERHEADS >=2 230#if DEBUG_LP_OVERHEADS >=2
231 solver_cost.stop(); 231 solver_cost.stop();
diff --git a/native/src/blocking/linprog/lp_dpcp.cpp b/native/src/blocking/linprog/lp_dpcp.cpp
index 1b1cf32..bec131b 100644
--- a/native/src/blocking/linprog/lp_dpcp.cpp
+++ b/native/src/blocking/linprog/lp_dpcp.cpp
@@ -371,7 +371,7 @@ static BlockingBounds* _lp_dpcp_bounds(const ResourceSharingInfo& info,
371#endif 371#endif
372 372
373 // Solve the big, combined LP. 373 // Solve the big, combined LP.
374 Solution *sol = cplex_solve(lp, var_idx); 374 Solution *sol = linprog_solve(lp, var_idx);
375 375
376 assert(sol != NULL); 376 assert(sol != NULL);
377 377
@@ -445,7 +445,7 @@ static void apply_dpcp_bounds_for_task(
445 solver_cost.start(); 445 solver_cost.start();
446#endif 446#endif
447 447
448 Solution *sol = cplex_solve(lp, vars.get_num_vars()); 448 Solution *sol = linprog_solve(lp, vars.get_num_vars());
449 449
450#if DEBUG_LP_OVERHEADS >= 2 450#if DEBUG_LP_OVERHEADS >= 2
451 solver_cost.stop(); 451 solver_cost.stop();
diff --git a/native/src/linprog/glpk.cpp b/native/src/linprog/glpk.cpp
new file mode 100644
index 0000000..9ddf2c6
--- /dev/null
+++ b/native/src/linprog/glpk.cpp
@@ -0,0 +1,206 @@
1#include <assert.h>
2#include <glpk.h>
3
4#include <iostream>
5
6#include "cpu_time.h"
7
8#include "linprog/glpk.h"
9
10class GLPKSolution : public Solution
11{
12private:
13 glp_prob *glpk;
14 const LinearProgram &linprog;
15 const unsigned int num_cols;
16 const unsigned int num_rows;
17 unsigned int num_coeffs;
18
19 bool solved;
20
21 void solve(double var_lb, double var_ub);
22 void set_objective();
23 void set_bounds(double col_lb, double col_ub);
24 void set_coefficients();
25public:
26
27 GLPKSolution(const LinearProgram &lp, unsigned int max_num_vars,
28 double var_lb = 0.0, double var_ub = 1.0);
29
30 ~GLPKSolution();
31
32 double get_value(unsigned int var) const
33 {
34 return glp_get_col_prim(glpk, var + 1);
35 }
36
37 bool is_solved() const
38 {
39 return solved;
40 }
41};
42
43GLPKSolution::GLPKSolution(const LinearProgram& lp, unsigned int max_num_vars,
44 double var_lb, double var_ub)
45 : glpk(glp_create_prob()),
46 linprog(lp),
47 num_cols(max_num_vars),
48 num_rows(lp.get_equalities().size() +
49 lp.get_inequalities().size()),
50 num_coeffs(0),
51 solved(false)
52{
53 if (num_cols)
54 solve(var_lb, var_ub);
55 else
56 // Trivial case: no variables.
57 // This can happen if a task set does not
58 // contain any shared resources.
59 solved = true;
60}
61
62void GLPKSolution::solve(double var_lb, double var_ub)
63{
64#if DEBUG_LP_OVERHEADS >= 3
65 static DEFINE_CPU_CLOCK(init_costs);
66 static DEFINE_CPU_CLOCK(model_costs);
67 static DEFINE_CPU_CLOCK(solver_costs);
68
69 init_costs.start();
70#endif
71 glp_term_out(GLP_OFF);
72 glp_set_obj_dir(glpk, GLP_MAX);
73 glp_add_cols(glpk, num_cols);
74 glp_add_rows(glpk, num_rows);
75
76#if DEBUG_LP_OVERHEADS >= 3
77 init_costs.stop();
78 model_costs.start();
79#endif
80
81 set_objective();
82 set_bounds(var_lb, var_ub);
83 set_coefficients();
84
85#if DEBUG_LP_OVERHEADS >= 3
86 model_costs.stop();
87 solver_costs.start();
88#endif
89
90 glp_smcp glpk_params;
91
92 glp_init_smcp(&glpk_params);
93
94 glpk_params.presolve = GLP_ON;
95
96 solved = glp_simplex(glpk, &glpk_params) == 0 &&
97 glp_get_status(glpk) == GLP_OPT;
98
99#if DEBUG_LP_OVERHEADS >= 3
100 solver_costs.stop();
101
102 std::cout << init_costs << std::endl
103 << model_costs << std::endl
104 << solver_costs << std::endl;
105#endif
106}
107
108GLPKSolution::~GLPKSolution()
109{
110 glp_delete_prob(glpk);
111}
112
113void GLPKSolution::set_objective()
114{
115 assert(linprog.get_objective()->get_terms().size() == num_cols);
116
117 foreach (linprog.get_objective()->get_terms(), term)
118 glp_set_obj_coef(glpk, term->second + 1, term->first);
119}
120
121
122void GLPKSolution::set_bounds(double col_lb, double col_ub)
123{
124 unsigned int r = 1;
125
126 foreach(linprog.get_equalities(), equ)
127 {
128 glp_set_row_bnds(glpk, r++, GLP_FX,
129 equ->second, equ->second);
130
131 num_coeffs += equ->first->get_terms().size();
132 }
133
134 foreach(linprog.get_inequalities(), inequ)
135 {
136 glp_set_row_bnds(glpk, r++, GLP_UP,
137 0, inequ->second);
138
139 num_coeffs += inequ->first->get_terms().size();
140 }
141
142 for (unsigned int c = 1; c <= num_cols; c++)
143 glp_set_col_bnds(glpk, c, GLP_DB, col_lb, col_ub);
144}
145
146void GLPKSolution::set_coefficients()
147{
148 int *row_idx, *col_idx;
149 double *coeff;
150
151 row_idx = new int[1 + num_coeffs];
152 col_idx = new int[1 + num_coeffs];
153 coeff = new double[1 + num_coeffs];
154
155 unsigned int r = 1, k = 1;
156
157 foreach(linprog.get_equalities(), equ)
158 {
159 foreach(equ->first->get_terms(), term)
160 {
161 assert(k <= num_coeffs);
162
163 row_idx[k] = r;
164 col_idx[k] = 1 + term->second;
165 coeff[k] = term->first;
166
167 k += 1;
168 }
169 r += 1;
170 }
171
172
173 foreach(linprog.get_inequalities(), inequ)
174 {
175 foreach(inequ->first->get_terms(), term)
176 {
177 assert(k <= num_coeffs);
178
179 row_idx[k] = r;
180 col_idx[k] = 1 + term->second;
181 coeff[k] = term->first;
182
183 k += 1;
184 }
185 r += 1;
186 }
187
188 glp_load_matrix(glpk, num_coeffs, row_idx, col_idx, coeff);
189
190 delete[] row_idx;
191 delete[] col_idx;
192 delete[] coeff;
193}
194
195
196Solution *glpk_solve(const LinearProgram& lp, unsigned int max_num_vars)
197{
198 GLPKSolution *sol = new GLPKSolution(lp, max_num_vars);
199 if (sol->is_solved())
200 return sol;
201 else
202 {
203 delete sol;
204 return NULL;
205 }
206}
diff --git a/native/src/testmain.cpp b/native/src/testmain.cpp
index 767af02..a68b786 100644
--- a/native/src/testmain.cpp
+++ b/native/src/testmain.cpp
@@ -930,7 +930,8 @@ int main(int argc, char** argv)
930 930
931 delete results; 931 delete results;
932 932
933#if defined(CONFIG_HAVE_CPLEX) 933
934#if defined(CONFIG_HAVE_CPLEX) || defined(CONFIG_HAVE_GLPK)
934 935
935 results = lp_dpcp_bounds(rsi, loc, false); 936 results = lp_dpcp_bounds(rsi, loc, false);
936 937