PandA-2024.02
glpk_solver.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
46 #include "custom_map.hpp"
47 #include <cfloat>
48 #include <climits>
49 #include <iostream>
50 #include <utility>
51 
52 #include "dbgPrintHelper.hpp"
53 #include "exceptions.hpp"
54 #include "glpk_solver.hpp"
55 #include "meilp_solver.hpp"
56 #include "utility.hpp"
57 
58 extern "C"
59 {
60 #define _GLP_PROB
61 #define GLP_PROB
62 #define GLP_PROB_DEFINED
63 #if HAVE_GLPK_NESTED
64 #include <glpk/glpk.h>
65 #else
66 #include <glpk.h>
67 #endif
68 }
69 
71  : meilp_solver(), lp(nullptr), scp(nullptr), iocp(nullptr), bfcp(nullptr), mip_solution(false)
72 {
73 }
74 
76 {
77  if(lp)
78  {
79  glp_delete_prob(lp);
80  }
81  delete scp;
82  delete iocp;
83  delete bfcp;
84 }
85 
86 /*
87  * Will be passed as a callback pointer to the GLPK library. The info pointer is used to point to the verbosity field of
88  * the current glpk_solver instance.
89  */
90 int glpk_print_hook(void* DEBUG_PARAMETER(info), const char* DEBUG_PARAMETER(msg))
91 {
92  INDENT_DBG_MEX(DEBUG_LEVEL_VERBOSE, *(static_cast<int*>(info)), msg);
93  // return non-zero so that GLPK does not print stuff on its own.
94  return 1;
95 }
96 
97 void glpk_solver::make(int nvars)
98 {
99  if(lp)
100  {
101  glp_delete_prob(lp);
102  }
103  lp = glp_create_prob();
104 
105  delete bfcp;
106  bfcp = new glp_bfcp();
107 
108  glp_get_bfcp(lp, bfcp);
109 
110  delete scp;
111  scp = new glp_smcp();
112  glp_init_smcp(scp);
113  scp->presolve = GLP_ON;
114 
115  delete iocp;
116  iocp = new glp_iocp();
117  glp_init_iocp(iocp);
118  iocp->presolve = GLP_ON;
119 
121  {
122  bfcp->msg_lev = iocp->msg_lev = scp->msg_lev = GLP_MSG_OFF;
123  }
125  {
126  bfcp->msg_lev = iocp->msg_lev = scp->msg_lev = GLP_MSG_ERR;
127  }
129  {
130  bfcp->msg_lev = iocp->msg_lev = scp->msg_lev = GLP_MSG_ALL;
131  }
132 
133  glp_set_bfcp(lp, bfcp);
134 
135  // set up the print hook so that output from GLPK goes through our own handler.
136  // lib_term_hook ( &glpk_print_hook, (void *) &debug_level);
137 
138  if(lp == nullptr)
139  {
140  THROW_ERROR(std::string("ErrorLpSolve"));
141  }
142  if(nvars)
143  {
144  glp_add_cols(lp, nvars);
145  }
146  if(MAX_time > 0)
147  {
148  scp->tm_lim = MAX_time;
149  scp->it_lim = MAX_time;
150  }
151 }
152 
154 {
156  set_all_bounds();
157  mip_solution = false;
160  {
161  print(std::cerr);
162  }
163 
164  scp->meth = GLP_DUALP; // use two-phase dual simplex, and if it fails, switch to the primal simplex
165  scp->pricing = GLP_PT_STD; // Pricing technique, standard (textbook)
166  scp->r_test = GLP_RT_HAR; // Ratio test technique: Harris’ two-pass ratio test
167  scp->presolve = GLP_ON; // use built in presolver
168  scp->tol_bnd = double(1e-7); // Tolerance used to check if the basic solution is primal feasible
169  scp->tol_dj = double(1e-7); // Tolerance used to check if the basic solution is dual feasible
170  scp->tol_piv = double(1e-10); // Tolerance used to choose eligble pivotal elements of the simplex table
171  scp->obj_ll = DBL_MIN; // Lower limit of the objective function
172  scp->obj_ul = DBL_MAX; // Upper limit of the objective function
173  scp->it_lim = INT_MAX; // Simplex iteration limit
174  scp->tm_lim = INT_MAX; // Searching time limit, in milliseconds
175  scp->out_frq = 200; // Output frequency, in iterations. This parameter specifies how frequently the solver sends
176  // information about the solution process to the terminal
177  scp->out_dly = 0; // Output delay, in milliseconds
178  scp->presolve = GLP_OFF; // Enable the built-in presolver
179 
180  int simplex_res = glp_simplex(lp, scp);
181 
182  /* POSSIBLE RESULTS
183  0 The LP problem instance has been successfully solved.
184  (This code does not necessarily mean that the solver has
185  found optimal solution. It only means that the solution
186  process was successful.)
187  GLP_EBADB Unable to start the search, because the initial basis speci-
188  fied in the problem object is invalid—the number of basic
189  (auxiliary and structural) variables is not the same as the
190  number of rows in the problem object.
191  GLP_ESING Unable to start the search, because the basis matrix corre-
192  sponding to the initial basis is singular within the working
193  precision.
194  GLP_ECOND Unable to start the search, because the basis matrix cor-
195  responding to the initial basis is ill-conditioned, i.e. its
196  condition number is too large.
197  GLP_EBOUND Unable to start the search, because some double-bounded
198  (auxiliary or structural) variables have incorrect bounds.
199  GLP_EFAIL The search was prematurely terminated due to the solver
200  failure.
201  GLP_EOBJLL The search was prematurely terminated, because the ob-
202  jective function being maximized has reached its lower
203  limit and continues decreasing (the dual simplex only).
204  GLP_EOBJUL The search was prematurely terminated, because the ob-
205  jective function being minimized has reached its upper
206  limit and continues increasing (the dual simplex only).
207  GLP_EITLIM The search was prematurely terminated, because the sim-
208  plex iteration limit has been exceeded.
209  GLP_ETMLIM The search was prematurely terminated, because the time
210  limit has been exceeded.
211  GLP_ENOPFS The LP problem instance has no primal feasible solution
212  (only if the LP presolver is used).
213  GLP_ENODFS The LP problem instance has no dual feasible solution
214  (only if the LP presolver is used).
215  */
216 
217  switch(simplex_res)
218  {
219  case 0:
220  {
221  PRINT_MSG("*** SUCCESS! The LP problem instance has been successfully solved! ***");
222  break;
223  }
224  case GLP_EBADB:
225  {
226  PRINT_MSG("ERROR: Unable to start the search, because the initial basis specified in the problem"
227  " object is invalid the number of basic (auxiliary and structural) variables is not the"
228  " same as the number of rows in the problem object");
229  break;
230  }
231  case GLP_ESING:
232  {
233  PRINT_MSG("ERROR: Unable to start the search, because the basis matrix corresponding to the initial basis"
234  " is singular within the working precision");
235  break;
236  }
237  case GLP_ECOND:
238  {
239  PRINT_MSG("ERROR: Unable to start the search, because the basis matrix corresponding to the initial"
240  " basis is ill-conditioned, i.e. its condition number is too large");
241  break;
242  }
243  case GLP_EBOUND:
244  {
245  PRINT_MSG("ERROR: Unable to start the search, because some double-bounded (auxiliary or structural)"
246  " variables have incorrect bounds");
247  break;
248  }
249  case GLP_EFAIL:
250  {
251  PRINT_MSG("ERROR: The search was prematurely terminated due to the solver failure");
252  break;
253  }
254  case GLP_EOBJLL:
255  {
256  PRINT_MSG("ERROR: The search was prematurely terminated, because the objective function being"
257  " maximized has reached its lower limit and continues decreasing (the dual simplex only)");
258  break;
259  }
260  case GLP_EOBJUL:
261  {
262  PRINT_MSG("ERROR: The search was prematurely terminated, because the objective function being"
263  " minimized has reached its upper limit and continues increasing (the dual simplex only)");
264  break;
265  }
266  case GLP_EITLIM:
267  {
268  PRINT_MSG("ERROR: The search was prematurely terminated, because the simplex iteration limit"
269  " has been exceeded");
270  break;
271  }
272  case GLP_ETMLIM:
273  {
274  PRINT_MSG("ERROR: The search was prematurely terminated, because the time limit has been exceeded");
275  break;
276  }
277  case GLP_ENOPFS:
278  {
279  PRINT_MSG("The LP problem instance has no primal feasible solution (only if the LP presolver is used)");
280  break;
281  }
282  case GLP_ENODFS:
283  {
284  PRINT_MSG("The LP problem instance has no dual feasible solution (only if the LP presolver is used)");
285  break;
286  }
287  default:
288  PRINT_MSG("ERROR: unknown glp_solve return code");
289  }
290 
291  int status = glp_get_status(lp);
292 
293  /* POSSIBLE PROBLEM STATUS
294  GLP_OPT solution is optimal;
295  GLP_FEAS solution is feasible;
296  GLP_INFEAS solution is infeasible;
297  GLP_NOFEAS problem has no feasible solution;
298  GLP_UNBND problem has unbounded solution;
299  GLP_UNDEF solution is undefined.
300  */
301 
302  switch(status)
303  {
304  case GLP_OPT:
305  {
306  PRINT_MSG("SUCCESS: PROBLEM SOLUTION IS OPTIMAL");
307  break;
308  }
309  case GLP_FEAS:
310  {
311  PRINT_MSG("SUCCESS: PROBLEM SOLUTION IS FEASIBLE");
312  break;
313  }
314  case GLP_INFEAS:
315  {
316  PRINT_MSG("FAILURE: PROBLEM SOLUTION IS INFEASIBLE");
317  break;
318  }
319  case GLP_NOFEAS:
320  {
321  PRINT_MSG("FAILURE: PROBLEM HAS NO FEASIBLE SOLUTION");
322  break;
323  }
324  case GLP_UNBND:
325  {
326  PRINT_MSG("FAILURE: PROBLEM HAS UNBOUNDED SOLUTION");
327  break;
328  }
329  case GLP_UNDEF:
330  {
331  PRINT_MSG("FAILURE: PROBLEM SOLUTION IS UNDEFINED");
332  break;
333  }
334  default:
335  PRINT_MSG("ERROR: unknown glp_get_status return code");
336  }
337 
338  int prim_stat = glp_get_prim_stat(lp);
339 
340  /* POSSIBLE PRIMAL STATUS
341  GLP_UNDEF primal solution is undefined;
342  GLP_FEAS primal solution is feasible;
343  GLP_INFEAS primal solution is infeasible;
344  GLP_NOFEAS no primal feasible solution exists.
345  */
346 
347  switch(prim_stat)
348  {
349  case GLP_UNDEF:
350  {
351  PRINT_MSG("FAILURE: Primal solution is undefined");
352  break;
353  }
354  case GLP_FEAS:
355  {
356  PRINT_MSG("SUCCESS: Primal solution is feasible");
357  break;
358  }
359  case GLP_INFEAS:
360  {
361  PRINT_MSG("FAILURE: Primal solution is infeasible");
362  break;
363  }
364  case GLP_NOFEAS:
365  {
366  PRINT_MSG("FAILURE: No Primal feasible solution exists");
367  break;
368  }
369  default:
370  PRINT_MSG("ERROR: unknown glp_get_prim_stat return code");
371  }
372 
373  return (simplex_res == 0 && status == GLP_OPT && prim_stat == GLP_FEAS) ? 0 : 1;
374 }
375 
377 {
379  set_all_bounds();
380  mip_solution = true;
381 
384  {
385  print(std::cerr);
386  }
387 
388  /* scale the problem data*/
389  if(!iocp->presolve)
390  {
391  glp_scale_prob(lp, GLP_SF_AUTO);
392  }
393  /* construct starting LP basis */
394  if(!iocp->presolve)
395  {
396  glp_adv_basis(lp, 0);
397  }
398  if(!iocp->presolve)
399  {
400  glp_set_bfcp(lp, bfcp);
401  int simplex_res = glp_simplex(lp, scp);
402  switch(simplex_res)
403  {
404  case 0:
405  {
406  // PRINT_MSG("*** SUCCESS! The LP problem instance has been successfully solved! ***");
407  break;
408  }
409  case GLP_EBADB:
410  {
411  PRINT_MSG("ERROR: Unable to start the search, because the initial basis specified in the problem"
412  " object is invalid the number of basic (auxiliary and structural) variables is not the"
413  " same as the number of rows in the problem object");
414  break;
415  }
416  case GLP_ESING:
417  {
418  PRINT_MSG("ERROR: Unable to start the search, because the basis matrix corresponding to the initial basis"
419  " is singular within the working precision");
420  break;
421  }
422  case GLP_ECOND:
423  {
424  PRINT_MSG("ERROR: Unable to start the search, because the basis matrix corresponding to the initial"
425  " basis is ill-conditioned, i.e. its condition number is too large");
426  break;
427  }
428  case GLP_EBOUND:
429  {
430  PRINT_MSG("ERROR: Unable to start the search, because some double-bounded (auxiliary or structural)"
431  " variables have incorrect bounds");
432  break;
433  }
434  case GLP_EFAIL:
435  {
436  PRINT_MSG("ERROR: The search was prematurely terminated due to the solver failure");
437  break;
438  }
439  case GLP_EOBJLL:
440  {
441  PRINT_MSG("ERROR: The search was prematurely terminated, because the objective function being"
442  " maximized has reached its lower limit and continues decreasing (the dual simplex only)");
443  break;
444  }
445  case GLP_EOBJUL:
446  {
447  PRINT_MSG("ERROR: The search was prematurely terminated, because the objective function being"
448  " minimized has reached its upper limit and continues increasing (the dual simplex only)");
449  break;
450  }
451  case GLP_EITLIM:
452  {
453  PRINT_MSG("ERROR: The search was prematurely terminated, because the simplex iteration limit"
454  " has been exceeded");
455  break;
456  }
457  case GLP_ETMLIM:
458  {
459  PRINT_MSG("ERROR: The search was prematurely terminated, because the time limit has been exceeded");
460  break;
461  }
462  case GLP_ENOPFS:
463  {
464  // PRINT_MSG("The LP problem instance has no primal feasible solution (only if the LP presolver is used)");
465  return 1;
466  }
467  case GLP_ENODFS:
468  {
469  // PRINT_MSG("The LP problem instance has no dual feasible solution (only if the LP presolver is used)");
470  return 1;
471  }
472  default:
473  PRINT_MSG("ERROR: unknown glp_solve return code");
474  }
475  }
476  int intopt_res = glp_intopt(lp, iocp);
477 
478  /* POSSIBLE RESULTS
479  0 The LP problem instance has been successfully solved.
480  (This code does not necessarily mean that the solver has
481  found optimal solution. It only means that the solution
482  process was successful.)
483  GLP_EBOUND Unable to start the search, because some double-bounded
484  (auxiliary or structural) variables have incorrect bounds.
485  GLP_EROOT Unable to start the search, because optimal basis for initial
486  LP relaxation is not provided. (This code may appear only
487  if the presolver is disabled.)
488  GLP_ENOPFS Unable to start the search, because LP relaxation of the
489  MIP problem instance has no primal feasible solution.
490  (This code may appear only if the presolver is enabled.)
491  GLP_ENODFS Unable to start the search, because LP relaxation of the
492  MIP problem instance has no dual feasible solution. In
493  other word, this code means that if the LP relaxation has
494  at least one primal feasible solution, its optimal solution is
495  unbounded, so if the MIP problem has at least one integer
496  feasible solution, its (integer) optimal solution is also un-
497  bounded. (This code may appear only if the presolver is
498  enabled.)
499  GLP_EFAIL The search was prematurely terminated due to the solver
500  failure.
501  GLP_EMIPGAP The search was prematurely terminated, because the rela-
502  tive mip gap tolerance has been reached.
503  GLP_ETMLIM The search was prematurely terminated, because the time
504  limit has been exceeded.
505  GLP_ESTOP The search was prematurely terminated by application.
506  (This code may appear only if the advanced solver inter-
507  face is used.)
508  */
509 
510  switch(intopt_res)
511  {
512  case 0:
513  {
514  // PRINT_MSG("*** SUCCESS! The MILP problem instance has been successfully solved! ***");
515  break;
516  }
517  case GLP_EBOUND:
518  {
519  PRINT_MSG("ERROR: Unable to start the search, because some double-bounded"
520  " (auxiliary or structural) variables have incorrect bounds");
521  break;
522  }
523  case GLP_EROOT:
524  {
525  PRINT_MSG("ERROR: Unable to start the search, because optimal basis for initial"
526  " LP relaxation is not provided");
527  break;
528  }
529  case GLP_ENOPFS:
530  {
531  /*PRINT_MSG("ERROR: Unable to start the search, because LP relaxation of the"
532  " MIP problem instance has no primal feasible solution");*/
533  return 1;
534  }
535  case GLP_ENODFS:
536  {
537  PRINT_MSG("Unable to start the search, because LP relaxation of the"
538  " MIP problem instance has no dual feasible solution. In"
539  " other word, this code means that if the LP relaxation has"
540  " at least one primal feasible solution, its optimal solution is"
541  " unbounded, so if the MIP problem has at least one integer"
542  " feasible solution, its (integer) optimal solution is also un"
543  " bounded.");
544  break;
545  }
546  case GLP_EFAIL:
547  {
548  PRINT_MSG("ERROR: The search was prematurely terminated due to the solver failure");
549  break;
550  }
551  case GLP_EMIPGAP:
552  {
553  PRINT_MSG("ERROR: The search was prematurely terminated, because the rela"
554  " tive mip gap tolerance has been reached");
555  break;
556  }
557  case GLP_ETMLIM:
558  {
559  PRINT_MSG("ERROR: The search was prematurely terminated, because the time limit has been exceeded");
560  break;
561  }
562  case GLP_ESTOP:
563  {
564  PRINT_MSG("ERROR: The search was prematurely terminated by application");
565  break;
566  }
567  default:
568  PRINT_MSG("ERROR: unknown glp_intopt return code");
569  }
570 
571  int status = glp_mip_status(lp);
572 
573  /* POSSIBLE PROBLEM STATUS
574  GLP_OPT solution is optimal;
575  GLP_FEAS solution is feasible;
576  GLP_NOFEAS problem has no feasible solution;
577  GLP_UNDEF solution is undefined.
578  */
579 
580  switch(status)
581  {
582  case GLP_OPT:
583  {
584  // PRINT_MSG("SUCCESS: PROBLEM SOLUTION IS OPTIMAL");
585  break;
586  }
587  case GLP_FEAS:
588  {
589  PRINT_MSG("SUCCESS: PROBLEM SOLUTION IS FEASIBLE");
590  break;
591  }
592  case GLP_NOFEAS:
593  {
594  PRINT_MSG("FAILURE: PROBLEM HAS NO FEASIBLE SOLUTION");
595  break;
596  }
597  case GLP_UNDEF:
598  {
599  PRINT_MSG("FAILURE: PROBLEM SOLUTION IS UNDEFINED");
600  break;
601  }
602  default:
603  PRINT_MSG("ERROR: unknown glp_get_status return code");
604  }
605  return (intopt_res == 0 && status == GLP_OPT) ? 0 : 1;
606 }
607 
608 void glpk_solver::add_row(std::map<int, double>& i_coeffs, double i_rhs, ilp_sign i_sign, const std::string& name)
609 {
610  if(i_coeffs.empty())
611  {
612  return;
613  }
614  copy(i_coeffs);
615  THROW_ASSERT(lp, "the matrix must exist");
616  int row_index = glp_add_rows(lp, 1);
617  if(name.length() < 255)
618  {
619  glp_set_row_name(lp, row_index, const_cast<char*>(name.c_str()));
620  }
621  else
622  {
623  glp_set_row_name(lp, row_index, const_cast<char*>((name.substr(0, 252) + "...").c_str()));
624  }
625  glp_set_mat_row(lp, row_index, static_cast<int>(i_coeffs.size()), int_buffer - 1, real_buffer - 1);
626  switch(i_sign)
627  {
628  case E:
629  glp_set_row_bnds(lp, row_index, GLP_FX, i_rhs, i_rhs);
630  break;
631  case L:
632  glp_set_row_bnds(lp, row_index, GLP_UP, 0, i_rhs);
633  break;
634  case G:
635  glp_set_row_bnds(lp, row_index, GLP_LO, i_rhs, 0); // we assume that the upper bound is ignored
636  break;
637  default:
638  THROW_UNREACHABLE("");
639  }
640 }
641 
643 {
644  return glp_get_num_rows(lp);
645 }
646 
648 {
649  return glp_get_num_cols(lp);
650 }
651 
652 void glpk_solver::objective_add(std::map<int, double>& i_coeffs, ilp_dir dir)
653 {
654  THROW_ASSERT(lp, "the matrix must exist");
655  switch(dir)
656  {
657  case min:
658  glp_set_obj_dir(lp, GLP_MIN);
659  break;
660  case max:
661  glp_set_obj_dir(lp, GLP_MAX);
662  break;
663  default:
664  THROW_ERROR(std::string("ErrorLpSolve"));
665  }
666 
667  auto i_end = i_coeffs.end();
668  for(auto i = i_coeffs.begin(); i != i_end; ++i)
669  {
670  glp_set_obj_coef(lp, i->first + 1, i->second);
671  }
672 }
673 
674 void glpk_solver::print(std::ostream& os __attribute__((unused)))
675 {
677  set_all_bounds();
678  // for the time being the os is not supported
679  // set_outputstream(lp, os);
680  glp_write_sol(lp, "glp_sol.txt");
681  glp_write_mps(lp, GLP_MPS_FILE, nullptr, "glpk.mps");
682  glp_write_lp(lp, nullptr, "glpk.lp");
683 }
684 
685 void glpk_solver::print_to_file(const std::string& file_name)
686 {
688  set_all_bounds();
689  // for the time being the os is not supported
690  // set_outputstream(lp, os);
691  glp_write_sol(lp, (file_name + ".txt").c_str());
692  glp_write_mps(lp, GLP_MPS_FILE, nullptr, (file_name + ".mps").c_str());
693  glp_write_lp(lp, nullptr, (file_name + ".lp").c_str());
694 }
695 
697 {
698  glp_set_col_kind(lp, i + 1, GLP_IV);
699 }
700 
701 void glpk_solver::get_vars_solution(std::map<int, double>& vars) const
702 {
703  vars.clear();
704  int nc = glp_get_num_cols(lp);
705  for(int i = 0; i < nc; i++)
706  {
707  if(mip_solution)
708  {
709  vars[i] = glp_mip_col_val(lp, i + 1);
710  }
711  else
712  {
713  vars[i] = glp_get_col_prim(lp, i + 1);
714  }
715  }
716 }
717 
718 void glpk_solver::set_col_name(int var, const std::string& name)
719 {
720  std::string ost = name + "_" + std::to_string(var);
721  glp_set_col_name(lp, var + 1, const_cast<char*>(ost.c_str()));
722 }
723 
724 std::string glpk_solver::get_col_name(int var)
725 {
726  return std::string(glp_get_col_name(lp, var + 1));
727 }
728 
730 {
731  return glp_add_cols(lp, 1) - 1;
732 }
733 
735 {
736  /* Type Bounds Comment
737  GLP_FR −∞ < x < +∞ Free (unbounded) variable
738  GLP_LO lb ≤ x < +∞ Variable with lower bound
739  GLP_UP −∞ < x ≤ ub Variable with upper bound
740  GLP_DB lb ≤ x ≤ ub Double-bounded variable
741  GLP_FX lb = x = ub Fixed variable
742  */
743 
744  // NOTE: when a variable is created, it's col_type is GLP_FX
745  int nc = glp_get_num_cols(lp);
746  for(int i = 0; i < nc; i++)
747  {
748  int var = i + 1;
749  switch(glp_get_col_type(lp, var))
750  {
751  case GLP_FR:
752  glp_set_col_bnds(lp, var, GLP_FR, 0, 0);
753 #if(__GNUC__ >= 7)
754  [[gnu::fallthrough]];
755 #endif
756  case GLP_LO:
757  {
758  if(lower_bounds.find(i) != lower_bounds.end())
759  {
760  glp_set_col_bnds(lp, var, GLP_LO, lower_bounds[i], 0);
761  }
762  else
763  {
764  THROW_ERROR("Lower bounded variable, but lower bound can't be found in lower_bounds");
765  }
766  break;
767  }
768  case GLP_FX:
769  {
770  // IF THE VARIABLE HAS A LOWER AND UPPER BOUND, IT MAY BECOME FX IF LB == UP or DB is UP > LB
771  if((lower_bounds.find(i) != lower_bounds.end()) && (upper_bounds.find(i) != upper_bounds.end()))
772  {
773  if(upper_bounds[i] == lower_bounds[i])
774  {
775  // PRINT_MSG("GLP_FX becomes GLP_FX");
776  glp_set_col_bnds(lp, var, GLP_FX, lower_bounds[i], upper_bounds[i]);
777  }
778  else
779  {
780  // PRINT_MSG("GLP_FX becomes GLP_DB");
781  glp_set_col_bnds(lp, var, GLP_DB, lower_bounds[i], upper_bounds[i]);
782  }
783  }
784  // IF THE VARIABLE HAS A LOWER BOUND, BUT DOES NOT HAVE AN UPPER BOUND IT BECOMES LOWER BOUNDED
785  else if((lower_bounds.find(i) != lower_bounds.end()) && (upper_bounds.find(i) == upper_bounds.end()))
786  {
787  // PRINT_MSG("GLP_FX becomes GLP_LO");
788  glp_set_col_bnds(lp, var, GLP_LO, lower_bounds[i], 0);
789  }
790  // IF THE VARIABLE HAS AN UPPER BOUND, BUT DOES NOT HAVE A LOWER BOUND IT BECOMES UPPER BOUNDED
791  else if((lower_bounds.find(i) == lower_bounds.end()) && (upper_bounds.find(i) != upper_bounds.end()))
792  {
793  // PRINT_MSG("GLP_FX becomes GLP_UP");
794  glp_set_col_bnds(lp, var, GLP_UP, 0, upper_bounds[i]);
795  }
796  else
797  {
798  THROW_ERROR("Fixed bounded variable, but either upper or lower bound can't be found in vectors or "
799  "bounds are different");
800  }
801  break;
802  }
803  case GLP_UP:
804  {
805  if(upper_bounds.find(i) != upper_bounds.end())
806  {
807  glp_set_col_bnds(lp, var, GLP_UP, 0, upper_bounds[i]);
808  }
809  else
810  {
811  THROW_ERROR("Upper bounded variable, but upper bound can't be found in upper_bounds");
812  }
813  break;
814  }
815  case GLP_DB:
816  {
817  if((lower_bounds.find(i) != lower_bounds.end()) && (upper_bounds.find(i) != upper_bounds.end()))
818  {
819  THROW_ASSERT(lower_bounds[i] <= upper_bounds[i], "Error in bound of variable " + std::to_string(i) +
820  " : " + std::to_string(lower_bounds[i]) + " " +
821  std::to_string(glp_get_col_ub(lp, var)));
822  glp_set_col_bnds(lp, var, GLP_DB, lower_bounds[i], upper_bounds[i]);
823  }
824  else
825  {
826  THROW_ERROR("Double bounded variable, but either lower or upper bound can't be found in bounds");
827  }
828  break;
829  }
830  default:
831  THROW_ERROR(std::string("ErrorLpSolve"));
832  }
833  }
834 }
#define INT_MAX
Definition: bellmanford.c:24
Less then.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
virtual void copy(const std::map< int, double > &i_coeffs)
File containing functions and utilities to support the printing of debug messagges.
int solve() override
Solve the linear problem.
void set_all_bounds() override
Set the lower and upper of the variables using lower_bounds and upper_bounds.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
glp_iocp * iocp
integer solver control parameter
Definition: glpk_solver.hpp:76
CustomUnorderedMap< int, double > upper_bounds
The upper bound of the variables. They will be really set by solve method.
Minimization.
void objective_add(std::map< int, double > &i_coeffs, ilp_dir dir) override
Set the objective function.
CustomUnorderedMap< int, double > lower_bounds
The lower bound of the variables. They will be really set by solve method.
int solve_ilp() override
Solve the integer linear problem.
~glpk_solver() override
Definition: glpk_solver.cpp:75
int add_empty_column() override
Add an empty column ???
void set_col_name(int var, const std::string &name) override
Set name of a variable (column)
Maximization.
exceptions managed by PandA
redefinition of map to manage ordered/unordered structures
glp_prob * lp
Definition: glpk_solver.hpp:66
bool mip_solution
it is true when solve_ilp() has been executed, false otherwise
Definition: glpk_solver.hpp:86
void print(std::ostream &os) override
Print the problem.
void print_to_file(const std::string &file_name) override
Print the problem.
ilp_dir
Type of objective function.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void set_int(int i) override
Set a variable to have only integer values.
int debug_level
debug_level
glp_bfcp * bfcp
basis factorization control parameters
Definition: glpk_solver.hpp:81
int get_number_constraints() const override
Return the number of constraints.
int glpk_print_hook(void *DEBUG_PARAMETER(info), const char *DEBUG_PARAMETER(msg))
Definition: glpk_solver.cpp:90
int * int_buffer
indexes in the constraint buffer
void make(int nvars) override
???
Definition: glpk_solver.cpp:97
glp_smcp * scp
simplex_control_params
Definition: glpk_solver.hpp:71
Base class providing several methods to encapsulate the interface to several ilp solver.
std::string get_col_name(int var) override
Get name of a variable (column)
This file collects some utility functions and macros.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
float float3 __attribute__((vector_size(16)))
Greater then.
#define DEBUG_PARAMETER(parameter)
macro used to solve problem of parameters used only in not-release
Definition: utility.hpp:91
int MAX_time
Time-out value.
void get_vars_solution(std::map< int, double > &vars) const override
Return the solution of the problem.
ilp_sign
Possible operator in constraints.
int get_number_variables() const override
Return the number of variables.
double * real_buffer
values in the constraint buffer
#define PRINT_MSG(mex)
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
void add_row(std::map< int, double > &i_coeffs, double i_rhs, ilp_sign i_sign, const std::string &name) override
Add a constraint to the ilp formulation.
Linear Programming solver according to the newer syntax (from version 4.35) of the GLPK solver...
#define DEBUG_LEVEL_MINIMUM
minimum debugging print is performed.
This class provide an interface to different solvers.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:54 for PandA-2024.02 by doxygen 1.8.13