Gröbner basis project
Codebase for research into Gröbner basis computation
glpk_solver.cpp
1 #ifndef __GLPK_SOLVER_CPP_
2 #define __GLPK_SOLVER_CPP_
3 
4 /*****************************************************************************\
5 * This file is part of DynGB. *
6 * *
7 * DynGB is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * Foobar is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with DynGB. If not, see <http://www.gnu.org/licenses/>. *
19 \*****************************************************************************/
20 
21 #include <cmath>
22 
23 #include "glpk_solver.hpp"
24 
25 #define MIN_X 0.01
26 
27 GLPK_Solver::GLPK_Solver(NVAR_TYPE nx) {
28  dirty = true;
29  n = nx; m = 0;
30  lp = glp_create_prob();
31  glp_set_obj_dir(lp, GLP_MIN);
32  glp_add_cols(lp, n);
33  for (NVAR_TYPE i = 1; i <= n; ++i) {
34  glp_set_col_bnds(lp, i, GLP_LO, MIN_X, 0.0);
35  glp_set_obj_coef(lp, i, 1.0);
36  }
37  glp_init_smcp(&smcp);
38  glp_term_out(GLP_OFF);
39  smcp.msg_lev = GLP_MSG_OFF;
40  smcp.presolve = GLP_ON;
41  row_data = new double[1+n]; // GLPK wants to start from index 1
42  row_indx = new int[1+n];
43  ray_data = new RAYENT_TYPE[n];
44 }
45 
47  dirty = other.dirty;
48  m = other.m; n = other.n;
49  row_data = new double[1+n];
50  row_indx = new int[1+n];
51  ray_data = new RAYENT_TYPE[n];
52  lp = glp_create_prob();
53  glp_copy_prob(lp, other.lp, GLP_OFF);
54  smcp = other.smcp;
55  rays = other.rays;
56 }
57 
58 bool GLPK_Solver::copy(const LP_Solver * old_solver) {
59  const GLPK_Solver * other = dynamic_cast<const GLPK_Solver *>(old_solver);
60  if (other != nullptr) {
61  dirty = other->dirty;
62  if (n != other->n) {
63  delete [] row_data; delete [] row_indx; delete [] ray_data;
64  row_data = new double[1+n];
65  row_indx = new int[1+n];
66  ray_data = new RAYENT_TYPE[n];
67  }
68  m = other->m; n = other->n;
69  glp_delete_prob(lp);
70  lp = glp_create_prob();
71  glp_copy_prob(lp, other->lp, GLP_OFF);
72  smcp = other->smcp;
73  rays = other->rays;
74  }
75  return (other != nullptr);
76 }
77 
78 GLPK_Solver::~GLPK_Solver() {
79  delete [] row_indx;
80  delete [] row_data;
81  delete [] ray_data;
82  glp_delete_prob(lp);
83 }
84 
85 bool GLPK_Solver::solve(vector<constraint> & newvecs) {
86  dirty = true;
87  int glp_result = 0;
88  int new_m = newvecs.size();
89  if (new_m > 0) {
90  glp_add_rows(lp, new_m);
91  for (int i = 0; i < new_m; ++i) {
92  int num_valid = 0;
93  for (int k = 0; k < n; ++k) {
94  if (newvecs[i][k] != 0) {
95  ++num_valid;
96  row_indx[num_valid] = 1 + k;
97  row_data[num_valid] = newvecs[i][k];
98  }
99  }
100  glp_set_mat_row(lp, 1 + m + i, num_valid, row_indx, row_data);
101  glp_set_row_bnds(lp, 1 + m + i, GLP_LO, MIN_X, 0.0);
102  }
103  if (m != 0) {
104  smcp.presolve = GLP_OFF;
105  glp_warm_up(lp);
106  }
107  m += new_m;
108  glp_result = glp_simplex(lp, &smcp);
109  if (glp_result == 0)
110  glp_result = glp_exact(lp, nullptr);
111  }
112  int status = glp_get_status(lp);
113  return (glp_result == 0 and (status == GLP_OPT or status == GLP_FEAS));
114 }
115 
117  dirty = true;
118  glp_add_rows(lp, 1);
119  int num_valid = 0;
120  for (int k = 0; k < n; ++k) {
121  if (newvec[k] != 0) {
122  ++num_valid;
123  row_indx[num_valid] = 1 + k;
124  row_data[num_valid] = newvec[k];
125  }
126  }
127  glp_set_mat_row(lp, 1 + m, num_valid, row_indx, row_data);
128  glp_set_row_bnds(lp, 1 + m, GLP_LO, MIN_X, 0.0);
129  if (m != 0) {
130  smcp.presolve = GLP_OFF;
131  glp_warm_up(lp);
132  }
133  m += 1;
134  int glp_result = glp_simplex(lp, &smcp);
135  smcp.presolve = GLP_OFF;
136  if (glp_result == 0)
137  glp_result = glp_exact(lp, nullptr);
138  int status = glp_get_status(lp);
139  return (glp_result == 0 and (status == GLP_OPT or status == GLP_FEAS));
140 }
141 
142 const set<ray> & GLPK_Solver::get_rays() {
143  if (dirty) {
144  rays.clear();
145  // the next few lines add a row
146  // that pushes the solution beyond the actual minimum
147  double curr_min = glp_get_obj_val(lp);
148  glp_add_rows(lp, 1);
149  for (NVAR_TYPE i = 0; i < n; ++i) {
150  row_indx[1+i] = 1+i;
151  row_data[1+i] = 1.0;
152  }
153  glp_set_mat_row(lp, 1 + m, n, row_indx, row_data);
154  glp_set_row_bnds(lp, 1 + m, GLP_DB, curr_min + 1, curr_min + 2);
155  // now we vary the objective function to minimize each variable
156  for (int i = 0; i < n; ++i)
157  glp_set_obj_coef(lp, 1 + i, 0.0);
158  for (int i = 0; i < n; ++i) {
159  glp_set_obj_coef(lp, 1 + i, 1.0);
160  if (i > 0)
161  glp_set_obj_coef(lp, i, 0.0);
162  // minimize first
163  glp_simplex(lp, &smcp);
164  glp_get_status(lp);
165  glp_exact(lp, nullptr);
166  for (NVAR_TYPE j = 0; j < n; ++j)
167  ray_data[j] = static_cast<RAYENT_TYPE>(
168  round(1/MIN_X * glp_get_col_prim(lp, 1 + j))
169  );
170  rays.emplace(n, ray_data);
171  //now maximize
172  glp_set_obj_dir(lp, GLP_MAX);
173  glp_simplex(lp, &smcp);
174  glp_get_status(lp);
175  glp_exact(lp, nullptr);
176  for (NVAR_TYPE j = 0; j < n; ++j)
177  ray_data[j] = static_cast<RAYENT_TYPE>(
178  round(1/MIN_X * glp_get_col_prim(lp, 1 + j))
179  );
180  rays.emplace(n, ray_data);
181  glp_set_obj_dir(lp, GLP_MIN);
182  }
183  // fix the objective function
184  for (unsigned i = 0; i < n; ++i)
185  glp_set_obj_coef(lp, 1 + i, 1.0);
186  // delete the row we added
187  row_indx[1] = 1 + m;
188  glp_set_row_stat(lp, 1 + m, GLP_BS);
189  glp_del_rows(lp, 1, row_indx);
190  glp_std_basis(lp);
191  dirty = false;
192  }
193  return rays;
194 }
195 
196 #endif
virtual bool copy(const LP_Solver *)
performs a deep copy, similar to a copy constructor
Definition: glpk_solver.cpp:58
set< ray > rays
Definition: lp_solver.hpp:602
approximate skeleton of a polyhedral cone, using GLPK linear solver
Definition: glpk_solver.hpp:37
a constraint
Definition: lp_solver.hpp:53
exact or approximate polyhedral cone solution, with methods allowing definition and refinement ...
Definition: lp_solver.hpp:504
GLPK_Solver(NVAR_TYPE n)
initializes solver for variables
Definition: glpk_solver.cpp:27
virtual const set< ray > & get_rays()
Returns the rays that define the skeleton.
virtual bool solve(constraint &)
Adds the indicated constraint (singular!) and re-computes the solution.