Gröbner basis project
Codebase for research into Gröbner basis computation
lp_solver.cpp
1 #ifndef __LP_SOLVER_CPP_
2 #define __LP_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 "lp_solver.hpp"
22 
23 constraint::constraint(NVAR_TYPE num_variables, CONSTR_TYPE coeffs [])
24 {
25  nvars = num_variables;
26  coefficients = new CONSTR_TYPE[nvars];
27  for (NVAR_TYPE i = 0; i < nvars; ++i)
28  coefficients[i] = coeffs[i];
29 }
30 
31 constraint::constraint(vector<CONSTR_TYPE> &coeffs)
32 {
33  nvars = coeffs.size();
34  coefficients = new CONSTR_TYPE[nvars];
35  for (NVAR_TYPE i = 0; i < nvars; ++i)
36  coefficients[i] = coeffs[i];
37 }
38 
39 constraint::constraint(const constraint &old_constraint)
40 {
41  nvars = old_constraint.nvars;
42  coefficients = new CONSTR_TYPE[nvars];
43  for (NVAR_TYPE i = 0; i < nvars; ++i)
44  coefficients[i] = old_constraint.coefficients[i];
45 }
46 
47 // ordering is lexicographic
48 bool operator < (const constraint &first, const constraint &second)
49 {
50  bool result = !(first == second);
51  bool checking = result;
52  for (NVAR_TYPE i = 0; checking and i < first.nvars; ++i)
53  if (first[i] != second[i])
54  {
55  checking = false;
56  result = first[i] < second[i];
57  }
58  return result;
59 }
60 
61 bool operator == (const constraint &first, const constraint &second)
62 {
63  bool result = true;
64  for (NVAR_TYPE i = 0; result and i < first.get_number_of_variables(); ++i) {
65  if (first[i] != second[i])
66  result = false;
67  }
68  return result;
69 }
70 
71 bool operator != (constraint &first, constraint &second)
72 {
73  bool result = true;
74  for (NVAR_TYPE i = 0; result and i < first.get_number_of_variables(); ++i)
75  if (first[i] != second[i])
76  result = false;
77  return !result;
78 }
79 
80 // formatted as sum of products of coefficients and variables
81 ostream & operator<<(ostream & ostr, const constraint &c)
82 {
83  bool first = true;
84  ostr << "0 ≤ ";
85  for (NVAR_TYPE i = 0; i < c.nvars; ++i)
86  {
87  if (c[i] < 0)
88  {
89  if (first) { ostr << '-'; first = false; } else ostr << "- ";
90  if (c[i] != -1)
91  ostr << -c[i] << 'x' << i << ' ';
92  else
93  ostr << 'x' << i << ' ';
94  }
95  else if (c[i] > 0)
96  {
97  if (first) { first = false; } else ostr << "+ ";
98  if (c[i] != 1)
99  ostr << c[i] << 'x' << i << ' ';
100  else
101  ostr << 'x' << i << ' ';
102  }
103  else
104  {
105  // do nothing when c[i] == 0
106  }
107  }
108  return ostr;
109 }
110 
112 {
113  delete [] coefficients;
114 }
115 
123 
124 unsigned invocations = 0;
125 
126 inline DEG_TYPE * ray_data_allocation(NVAR_TYPE n) {
127  invocations++;
128  if (doda == nullptr) doda = new Grading_Order_Data_Allocator<DEG_TYPE>(n);
129  return doda->get_new_block();
130 }
131 
132 ray::ray(NVAR_TYPE dimension, long direction)
133 {
134  dim = dimension;
135  //coords = new RAYENT_TYPE[dim];
136  coords = ray_data_allocation(dim);
137  for (NVAR_TYPE i = 0; i < dim; ++i) coords[i] = 0;
138  if (direction >= 0) {
139  coords[direction] = 1;
140  }
141 }
142 
143 ray::ray(NVAR_TYPE dimension, const RAYENT_TYPE entries [])
144 {
145  dim = dimension;
146  //coords = new RAYENT_TYPE[dim];
147  coords = ray_data_allocation(dim);
148  for (NVAR_TYPE i = 0; i < dim; ++i)
149  coords[i] = entries[i];
150 }
151 
152 ray::ray(NVAR_TYPE dimension, const EXP_TYPE entries [])
153 {
154  dim = dimension;
155  //coords = new RAYENT_TYPE[dim];
156  coords = ray_data_allocation(dim);
157  for (NVAR_TYPE i = 0; i < dim; ++i)
158  coords[i] = entries[i];
159 }
160 
161 ray::ray(const vector<RAYENT_TYPE> &entries)
162 {
163  dim = entries.size();
164  //coords = new RAYENT_TYPE[dim];
165  coords = ray_data_allocation(dim);
166  for (NVAR_TYPE i = 0; i < dim; ++i)
167  coords[i] = entries[i];
168 }
169 
170 ray::ray(const ray &old_ray)
171  : dim(old_ray.dim)
172 {
173  //coords = new RAYENT_TYPE[dim];
174  static unsigned long invocations;
175  coords = ray_data_allocation(dim);
176  for (RAYENT_TYPE i = 0; i < dim; ++i)
177  coords[i] = old_ray.coords[i];
178 }
179 
181 {
182  //delete [] coords;
183  doda->return_used_block(coords);
184 }
185 
187 {
188  RAYENT_TYPE * w = coords;
189  RAYENT_TYPE gcd = 0;
190  for (NVAR_TYPE i = 0; i < get_dimension(); ++i)
191  {
192  if (gcd == 0)
193  gcd = w[i];
194  else if (w[i] != 0)
195  {
196  RAYENT_TYPE r = (gcd < w[i] ? gcd : w[i]);
197  RAYENT_TYPE s = (gcd < w[i] ? w[i] : gcd);
198  while (r != 0)
199  {
200  RAYENT_TYPE t = s % r;
201  s = r;
202  r = t;
203  }
204  gcd = s;
205  }
206  }
207  if (gcd > 1)
208  for (NVAR_TYPE i = 0; i < get_dimension(); ++i)
209  w[i] /= gcd;
210 }
211 
212 DOTPROD_TYPE ray::obtain_dot_product(const constraint &hyperplane) const
213 {
214  DOTPROD_TYPE result = 0;
215  const CONSTR_TYPE * coeffs = hyperplane.coeffs();
216  for (NVAR_TYPE i = 0; i < dim; ++i)
217  //result += coords[i] * hyperplane[i];
218  result += coords[i] * coeffs[i];
219  return result;
220 }
221 
222 ray operator*(RAYENT_TYPE a, ray &r)
223 {
224  NVAR_TYPE d = r.get_dimension();
225  //RAYENT_TYPE *coords = new RAYENT_TYPE[d];
226  RAYENT_TYPE *coords = ray_data_allocation(d);
227  for (NVAR_TYPE i = 0; i < d; ++i)
228  coords[i] = a*r[i];
229  ray result(d, coords);
230  //delete [] coords;
231  doda->return_used_block(coords);
232  return result;
233 }
234 
235 RAYENT_TYPE operator*(const ray &r1, const ray &r2)
236 {
237  RAYENT_TYPE result = 0;
238  for (NVAR_TYPE i = 0; i < r1.get_dimension(); ++i)
239  result += r1[i]*r2[i];
240  return result;
241 }
242 
243 RAYENT_TYPE operator*(ray &r1, vector<long> &r2)
244 {
245  RAYENT_TYPE result = 0;
246  for (NVAR_TYPE i = 0; i < r1.get_dimension(); ++i)
247  result += r1[i]*r2[i];
248  return result;
249 }
250 
251 RAYENT_TYPE operator*( vector<long> &r1, ray &r2)
252 {
253  RAYENT_TYPE result = 0;
254  for (NVAR_TYPE i = 0; i < r1.size(); ++i)
255  result += r1[i]*r2[i];
256  return result;
257 }
258 
259 ray operator+(ray &r1, ray &r2)
260 {
261  NVAR_TYPE d = r1.get_dimension();
262  RAYENT_TYPE * coords = ray_data_allocation(d);
263  for (NVAR_TYPE i = 0; i < d; ++i)
264  coords[i] = r1[i] + r2[i];
265  ray result(d, coords);
266  doda->return_used_block(coords);
267  return result;
268 }
269 
270 ray operator-(const ray &r1, const ray &r2)
271 {
272  NVAR_TYPE d = r1.get_dimension();
273  RAYENT_TYPE *coords = ray_data_allocation(d);
274  for (NVAR_TYPE i = 0; i < d; ++i)
275  coords[i] = r1[i] - r2[i];
276  ray result(d, coords);
277  doda->return_used_block(coords);
278  return result;
279 }
280 
281 ray ray_sum(const set<ray> &rs)
282 {
283  NVAR_TYPE d = 0;
284  RAYENT_TYPE *coords = nullptr;
285  for (auto riter = rs.begin(); riter != rs.end(); ++riter)
286  {
287  ray r = *riter;
288  if (coords == nullptr)
289  {
290  d = r.get_dimension();
291  coords = ray_data_allocation(d);
292  for (NVAR_TYPE i = 0; i < d; ++i) coords[i] = 0;
293  }
294  for (NVAR_TYPE i = 0; i < d; ++i)
295  {
296  coords[i] += r[i];
297  }
298  }
299  ray result(d, coords);
300  doda->return_used_block(coords);
301  return result;
302 }
303 
304 bool operator==(const ray &r1, const ray &r2)
305 {
306  bool result = true;
307  for (NVAR_TYPE i = 0; result and i < r1.get_dimension(); ++i)
308  result = r1[i] == r2[i];
309  return result;
310 }
311 
312 bool operator!=(const ray &r1, const ray &r2)
313 {
314  bool result = true;
315  for (NVAR_TYPE i = 0; result and i < r1.get_dimension(); ++i)
316  result = r1[i] == r2[i];
317  return !result;
318 }
319 
320 ostream & operator<<(ostream & ostr, const ray &r)
321 {
322  ostr << "( ";
323  NVAR_TYPE i;
324  for (i = 0; i < r.dim - 1; ++i)
325  ostr << r[i] << ", ";
326  ostr << r[i] << " )";
327  return ostr;
328 }
329 
330 ray & ray::operator=(const ray &other)
331 {
332  if (!(*this == other))
333  {
334  // resize coords if need be
335  if (dim != other.dim)
336  {
337  dim = other.dim;
338  //delete [] coords;
339  //coords = new RAYENT_TYPE[dim];
340  doda->return_used_block(coords);
341  coords = ray_data_allocation(dim);
342  }
343  // copy coords
344  for (NVAR_TYPE i = 0; i < dim; ++i)
345  coords[i] = other.coords[i];
346  }
347  return *this;
348 }
349 
350 void ray::swap(ray &other)
351 {
352  RAYENT_TYPE tmpval;
353  for (NVAR_TYPE i = 0; i < dim; ++i)
354  {
355  tmpval = coords[i];
356  coords[i] = other.coords[i];
357  other.coords[i] = tmpval;
358  }
359 }
360 
361 bool operator<(const ray &first_ray, const ray &second_ray)
362 {
363  bool result = true;
364  NVAR_TYPE i = 0;
365  bool equal = true;
366  while (equal and i < first_ray.dim)
367  {
368  if (first_ray[i] != second_ray[i])
369  {
370  equal = false;
371  result = first_ray[i] < second_ray[i];
372  }
373  ++i;
374  }
375  return result and (not equal);
376 }
377 
378 const set<ray> & LP_Solver::get_rays() { return rays; }
379 
380 #endif
ray ray_sum(const set< ray > &rs)
Add all the rays in a set.
Definition: lp_solver.cpp:281
special memory pool allocator for Grevlex_Order_Data and WGrevlex_Order_Data
Definition: goda.hpp:67
ray operator-(const ray &r1, const ray &r2)
Subtract the two rays.
Definition: lp_solver.cpp:270
friend bool operator<(const ray &, const ray &)
Lexicographic comparison of rays.
Definition: lp_solver.cpp:361
ray operator+(ray &r1, ray &r2)
Add the two rays.
Definition: lp_solver.cpp:259
TYPE * get_new_block()
allocates and returns a block of memory
Definition: goda.hpp:108
friend bool operator!=(const constraint &a, const constraint &b)
check for constraint inequality
Grading_Order_Data_Allocator< DEG_TYPE > * doda
memory manager for ray entries
Definition: lp_solver.cpp:122
virtual const set< ray > & get_rays()
Returns the rays that define the skeleton.
Definition: lp_solver.cpp:378
friend bool operator<(const constraint &a, const constraint &b)
Lexicographic comparison of constraints.
Definition: lp_solver.cpp:48
~constraint()
Deletes memory allocated by the constructor.
Definition: lp_solver.cpp:111
friend ostream & operator<<(ostream &, const constraint &)
print a representation of the constraint to the stream
Definition: lp_solver.cpp:81
ray operator*(RAYENT_TYPE a, ray &r)
Multiply every coordinate in the given ray by the given scalar.
Definition: lp_solver.cpp:222
constraint(NVAR_TYPE, CONSTR_TYPE [])
Initialize constraint to the given coefficients.
Definition: lp_solver.cpp:23
DOTPROD_TYPE obtain_dot_product(const constraint &) const
Convenience function to compute dot product between ray and the given constraint. ...
Definition: lp_solver.cpp:212
NVAR_TYPE get_number_of_variables() const
Returns the number of variables in the constraint.
Definition: lp_solver.hpp:108
friend bool operator==(const ray &, const ray &)
Indicates whether the two rays are equal.
Definition: lp_solver.cpp:304
void swap(ray &)
Swap two rays of equal dimension by swapping their data, avoiding memory reallocation.
Definition: lp_solver.cpp:350
a constraint
Definition: lp_solver.hpp:53
~ray()
Deletes memory allocated by the constructor.
Definition: lp_solver.cpp:180
friend bool operator==(const constraint &a, const constraint &b)
check for constraint equality
Definition: lp_solver.cpp:61
ray(NVAR_TYPE, long=-1)
Creates a ray with the given number of variables, all set to 0.
Definition: lp_solver.cpp:132
const CONSTR_TYPE * coeffs() const
Returns the coefficients that determine this constraints.
Definition: lp_solver.hpp:116
NVAR_TYPE get_dimension() const
Returns the dimension of this ray.
Definition: lp_solver.hpp:259
ray & operator=(const ray &)
Assignment operator; assigns the value of other to this.
Definition: lp_solver.cpp:330
friend ostream & operator<<(ostream &, const ray &)
Output is of the form .
Definition: lp_solver.cpp:320
void return_used_block(TYPE *freed_block)
returns a block of memory that is no longer needed to the pool
Definition: goda.hpp:121
friend bool operator!=(const ray &, const ray &)
Indicates whether the two rays are unequal.
Definition: lp_solver.cpp:312
void simplify_ray()
Simplifies the ray by dividing its components by the least common denominator.
Definition: lp_solver.cpp:186
a ray defined by nonnegative coordinates
Definition: lp_solver.hpp:190