Scippy

SCIP

Solving Constraint Integer Programs

lpi_glop.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file lpi_glop.cpp
17  * @ingroup LPIS
18  * @brief LP interface for Glop
19  * @author Frederic Didier
20  * @author Marc Pfetsch
21  */
22 
23 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 /* turn off some warnings from includes */
26 #pragma GCC diagnostic ignored "-Wsign-compare"
27 #pragma GCC diagnostic ignored "-Wpedantic"
28 #pragma GCC diagnostic ignored "-Wignored-qualifiers"
29 #pragma GCC diagnostic ignored "-Wshadow"
30 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
31 #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
32 #pragma GCC diagnostic ignored "-Woverflow"
33 
34 #include "ortools/base/version.h"
35 #include "ortools/glop/lp_solver.h"
36 #include "ortools/glop/revised_simplex.h"
37 #include "ortools/lp_data/lp_print_utils.h"
38 #include "ortools/lp_data/lp_data_utils.h"
39 #include "ortools/lp_data/proto_utils.h"
40 #include "ortools/util/file_util.h"
41 #include "ortools/util/stats.h"
42 #include "ortools/util/time_limit.h"
43 
44 #include "ortools/base/logging.h"
45 #include "ortools/base/vlog_is_on.h"
46 
47 #include "lpi/lpi.h"
48 #include "scip/pub_message.h"
49 
50 #include <assert.h>
51 
52 /* turn warnings on again */
53 #pragma GCC diagnostic warning "-Wsign-compare"
54 #pragma GCC diagnostic warning "-Wpedantic"
55 #pragma GCC diagnostic warning "-Wignored-qualifiers"
56 #pragma GCC diagnostic warning "-Wshadow"
57 #pragma GCC diagnostic warning "-Wnon-virtual-dtor"
58 #pragma GCC diagnostic warning "-Wctor-dtor-privacy"
59 #pragma GCC diagnostic warning "-Woverflow"
60 
61 
62 using operations_research::TimeLimit;
63 using operations_research::glop::BasisState;
64 using operations_research::glop::ColIndex;
65 using operations_research::glop::ColIndexVector;
66 using operations_research::glop::ConstraintStatus;
67 using operations_research::glop::ConstraintStatusColumn;
68 using operations_research::glop::DenseBooleanColumn;
69 using operations_research::glop::DenseBooleanRow;
70 using operations_research::glop::DenseColumn;
71 using operations_research::glop::DenseRow;
72 using operations_research::glop::SparseColumn;
73 using operations_research::glop::ScatteredColumn;
74 using operations_research::glop::ScatteredColumnIterator;
75 using operations_research::glop::SparseMatrix;
76 using operations_research::glop::Fractional;
77 using operations_research::glop::GetProblemStatusString;
78 using operations_research::glop::ProblemStatus;
79 using operations_research::glop::RowIndex;
80 using operations_research::glop::ScatteredRow;
81 using operations_research::glop::ScatteredRowIterator;
82 using operations_research::glop::VariableStatus;
83 using operations_research::glop::VariableStatusRow;
84 using operations_research::MPModelProto;
85 
86 /** LP interface */
87 struct SCIP_LPi
88 {
89  operations_research::glop::LinearProgram* linear_program; /**< the linear program */
90  operations_research::glop::LinearProgram* scaled_lp; /**< scaled linear program */
91  operations_research::glop::RevisedSimplex* solver; /**< direct reference to the revised simplex, not passing through lp_solver */
92  operations_research::glop::GlopParameters* parameters; /**< parameters */
93  operations_research::glop::LpScalingHelper* scaler; /**< scaler auxiliary class */
94 
95  /* the following is used by SCIPlpiWasSolved() */
98 
99  /* store the values of some parameters in order to be able to return them */
100  bool lp_info; /**< whether additional output is turned on */
101  SCIP_PRICING pricing; /**< SCIP pricing setting */
102  bool from_scratch; /**< store whether basis is ignored for next solving call */
103  int numthreads; /**< number of threads used to solve the LP (0 = automatic) */
104  SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
105  bool checkcondition; /**< Should condition number of LP basis be checked for stability? */
106  int timing; /**< type of timer (1 - cpu, 2 - wallclock, 0 - off) */
107 
108  /* other data */
109  SCIP_Longint niterations; /**< number of iterations used */
110 
111  /* Temporary vectors allocated here for speed. This gain is non-negligible
112  * because in many situations, only a few entries of these vectors are
113  * inspected (hypersparsity) and allocating them is in O(num_rows) or
114  * O(num_cols) instead of O(num_non_zeros) to read/clear them. */
115  ScatteredRow* tmp_row; /**< temporary vector */
116  ScatteredColumn* tmp_column; /**< temporary vector */
117 };
118 
119 /** uncomment to turn off scaling */
120 /* #define NOSCALING */
121 
122 /** define feasibility check to possibly reoptimize: 0: no check, 1: completely new check, 2: check unscaled variable and activity values */
123 #ifdef NOSCALING
124 #define UNSCALEDFEAS_CHECK 0
125 #else
126 #define UNSCALEDFEAS_CHECK 2
127 #endif
128 
129 
130 /*
131  * LP Interface Methods
132  */
133 
134 char* initGlopName( );
135 
136 static char* glopname = initGlopName( );
137 
138 char* initGlopName( )
139 {
140  glopname = new char[100];
141  (void) snprintf(glopname, 100, "Glop %d.%d", operations_research::OrToolsMajorVersion(), operations_research::OrToolsMinorVersion());
142  return glopname;
143 }
144 
145 /** gets name and version of LP solver */
147  void
148  )
149 {
150  return glopname;
151 }
152 
153 /** gets description of LP solver (developer, webpage, ...) */
155  void
156  )
157 {
158  return "Glop Linear Solver, developed by Google, part of OR-Tools (developers.google.com/optimization)";
159 }
160 
161 /** gets pointer for LP solver - use only with great care */
163  SCIP_LPI* lpi /**< pointer to an LP interface structure */
164  )
165 {
166  assert( lpi != NULL );
167 
168  SCIPerrorMessage("SCIPlpiGetSolverPointer() has not been implemented yet.\n");
169 
170  return NULL;
171 }
172 
173 /** pass integrality information to LP solver */
175  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
176  int ncols, /**< length of integrality array */
177  int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
178  )
179 {
180  assert( lpi != NULL );
181  assert( lpi->linear_program != NULL );
182  assert( ncols == 0 || ncols == lpi->linear_program->num_variables().value() );
183 
184  /* Pass on integrality information (currently not used by Glop). */
185  for (ColIndex col(0); col < ColIndex(ncols); ++col)
186  {
187  assert( intInfo != NULL );
188  int info = intInfo[col.value()];
189  assert( info == 0 || info == 1 );
190  if ( info == 0 )
191  lpi->linear_program->SetVariableType(col, operations_research::glop::LinearProgram::VariableType::CONTINUOUS);
192  else
193  lpi->linear_program->SetVariableType(col, operations_research::glop::LinearProgram::VariableType::INTEGER);
194  }
195 
196  return SCIP_OKAY;
197 }
198 
199 /** informs about availability of a primal simplex solving method */
201  void
202  )
203 {
204  return TRUE;
205 }
206 
207 /** informs about availability of a dual simplex solving method */
209  void
210  )
211 {
212  return TRUE;
213 }
214 
215 /** informs about availability of a barrier solving method */
217  void
218  )
219 {
220  return FALSE;
221 }
222 
223 
224 /*
225  * LPI Creation and Destruction Methods
226  */
227 
228 /**@name LPI Creation and Destruction Methods */
229 /**@{ */
230 
231 /** creates an LP problem object */
233  SCIP_LPI** lpi, /**< pointer to an LP interface structure */
234  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
235  const char* name, /**< problem name */
236  SCIP_OBJSEN objsen /**< objective sense */
237  )
238 {
239  assert( lpi != NULL );
240  assert( name != NULL );
241 
242  /* Initilialize memory. */
244  (*lpi)->linear_program = new operations_research::glop::LinearProgram();
245  (*lpi)->scaled_lp = new operations_research::glop::LinearProgram();
246  (*lpi)->solver = new operations_research::glop::RevisedSimplex();
247  (*lpi)->parameters = new operations_research::glop::GlopParameters();
248  (*lpi)->scaler = new operations_research::glop::LpScalingHelper();
249 
250  /* Set problem name and objective direction. */
251  (*lpi)->linear_program->SetName(std::string(name));
252  SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
253 
254  (*lpi)->from_scratch = false;
255  (*lpi)->lp_info = false;
256  (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
257  (*lpi)->lp_modified_since_last_solve = true;
258  (*lpi)->lp_time_limit_was_reached = false;
259  (*lpi)->conditionlimit = -1.0;
260  (*lpi)->checkcondition = false;
261  (*lpi)->niterations = 0LL;
262 
263  (*lpi)->tmp_row = new ScatteredRow();
264  (*lpi)->tmp_column = new ScatteredColumn();
265 
266 #ifdef NOSCALING
267  (*lpi)->parameters->set_use_scaling(false);
268 #endif
269 
270  return SCIP_OKAY;
271 }
272 
273 /** deletes an LP problem object */
275  SCIP_LPI** lpi /**< pointer to an LP interface structure */
276  )
277 {
278  SCIPdebugMessage("SCIPlpiFree\n");
279 
280  delete (*lpi)->scaler;
281  delete (*lpi)->parameters;
282  delete (*lpi)->solver;
283  delete (*lpi)->scaled_lp;
284  delete (*lpi)->linear_program;
285 
286  delete (*lpi)->tmp_row;
287  delete (*lpi)->tmp_column;
288 
289  BMSfreeMemory(lpi);
290 
291  return SCIP_OKAY;
292 }
293 
294 /**@} */
295 
296 
297 
298 
299 /*
300  * Modification Methods
301  */
302 
303 /**@name Modification Methods */
304 /**@{ */
305 
306 /** copies LP data with column matrix into LP solver */
308  SCIP_LPI* lpi, /**< LP interface structure */
309  SCIP_OBJSEN objsen, /**< objective sense */
310  int ncols, /**< number of columns */
311  const SCIP_Real* obj, /**< objective function values of columns */
312  const SCIP_Real* lb, /**< lower bounds of columns */
313  const SCIP_Real* ub, /**< upper bounds of columns */
314  char** colnames, /**< column names, or NULL */
315  int nrows, /**< number of rows */
316  const SCIP_Real* lhs, /**< left hand sides of rows */
317  const SCIP_Real* rhs, /**< right hand sides of rows */
318  char** rownames, /**< row names, or NULL */
319  int nnonz, /**< number of nonzero elements in the constraint matrix */
320  const int* beg, /**< start index of each column in ind- and val-array */
321  const int* ind, /**< row indices of constraint matrix entries */
322  const SCIP_Real* val /**< values of constraint matrix entries */
323  )
324 {
325  assert( lpi != NULL );
326  assert( lpi->linear_program != NULL );
327  assert( obj != NULL );
328  assert( lb != NULL );
329  assert( ub != NULL );
330  assert( beg != NULL );
331  assert( ind != NULL );
332  assert( val != NULL );
333 
334  lpi->linear_program->Clear();
335  SCIP_CALL( SCIPlpiAddRows(lpi, nrows, lhs, rhs, rownames, 0, NULL, NULL, NULL) );
336  SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
337  SCIP_CALL( SCIPlpiChgObjsen(lpi, objsen) );
338 
339  return SCIP_OKAY;
340 }
341 
342 /** adds columns to the LP */
344  SCIP_LPI* lpi, /**< LP interface structure */
345  int ncols, /**< number of columns to be added */
346  const SCIP_Real* obj, /**< objective function values of new columns */
347  const SCIP_Real* lb, /**< lower bounds of new columns */
348  const SCIP_Real* ub, /**< upper bounds of new columns */
349  char** colnames, /**< column names, or NULL */
350  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
351  const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
352  const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
353  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
354  )
355 {
356  assert( lpi != NULL );
357  assert( lpi->linear_program != NULL );
358  assert( obj != NULL );
359  assert( lb != NULL );
360  assert( ub != NULL );
361  assert( nnonz >= 0) ;
362  assert( ncols >= 0) ;
363 
364  SCIPdebugMessage("adding %d columns with %d nonzeros.\n", ncols, nnonz);
365 
366  /* @todo add names */
367  if ( nnonz > 0 )
368  {
369  assert( beg != NULL );
370  assert( ind != NULL );
371  assert( val != NULL );
372  assert( ncols > 0 );
373 
374 #ifndef NDEBUG
375  /* perform check that no new rows are added */
376  RowIndex num_rows = lpi->linear_program->num_constraints();
377  for (int j = 0; j < nnonz; ++j)
378  {
379  assert( 0 <= ind[j] && ind[j] < num_rows.value() );
380  assert( val[j] != 0.0 );
381  }
382 #endif
383 
384  int nz = 0;
385  for (int i = 0; i < ncols; ++i)
386  {
387  const ColIndex col = lpi->linear_program->CreateNewVariable();
388  lpi->linear_program->SetVariableBounds(col, lb[i], ub[i]);
389  lpi->linear_program->SetObjectiveCoefficient(col, obj[i]);
390  const int end = (nnonz == 0 || i == ncols - 1) ? nnonz : beg[i + 1];
391  while ( nz < end )
392  {
393  lpi->linear_program->SetCoefficient(RowIndex(ind[nz]), col, val[nz]);
394  ++nz;
395  }
396  }
397  assert( nz == nnonz );
398  }
399  else
400  {
401  for (int i = 0; i < ncols; ++i)
402  {
403  const ColIndex col = lpi->linear_program->CreateNewVariable();
404  lpi->linear_program->SetVariableBounds(col, lb[i], ub[i]);
405  lpi->linear_program->SetObjectiveCoefficient(col, obj[i]);
406  }
407  }
408 
409  lpi->lp_modified_since_last_solve = true;
410 
411  return SCIP_OKAY;
412 }
413 
414 /** deletes all columns in the given range from LP */
416  SCIP_LPI* lpi, /**< LP interface structure */
417  int firstcol, /**< first column to be deleted */
418  int lastcol /**< last column to be deleted */
419  )
420 {
421  assert( lpi != NULL );
422  assert( lpi->linear_program != NULL );
423  assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->linear_program->num_variables() );
424 
425  SCIPdebugMessage("deleting columns %d to %d.\n", firstcol, lastcol);
426 
427  const ColIndex num_cols = lpi->linear_program->num_variables();
428  DenseBooleanRow columns_to_delete(num_cols, false);
429  for (int i = firstcol; i <= lastcol; ++i)
430  columns_to_delete[ColIndex(i)] = true;
431 
432  lpi->linear_program->DeleteColumns(columns_to_delete);
433  lpi->lp_modified_since_last_solve = true;
434 
435  return SCIP_OKAY;
436 }
437 
438 /** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
440  SCIP_LPI* lpi, /**< LP interface structure */
441  int* dstat /**< deletion status of columns
442  * input: 1 if column should be deleted, 0 if not
443  * output: new position of column, -1 if column was deleted */
444  )
445 {
446  assert( lpi != NULL );
447  assert( lpi->linear_program != NULL );
448  assert( dstat != NULL );
449 
450  const ColIndex num_cols = lpi->linear_program->num_variables();
451  DenseBooleanRow columns_to_delete(num_cols, false);
452  int new_index = 0;
453  int num_deleted_columns = 0;
454  for (ColIndex col(0); col < num_cols; ++col)
455  {
456  int i = col.value();
457  if ( dstat[i] == 1 )
458  {
459  columns_to_delete[col] = true;
460  dstat[i] = -1;
461  ++num_deleted_columns;
462  }
463  else
464  dstat[i] = new_index++;
465  }
466  SCIPdebugMessage("SCIPlpiDelColset: deleting %d columns.\n", num_deleted_columns);
467  lpi->linear_program->DeleteColumns(columns_to_delete);
468  lpi->lp_modified_since_last_solve = true;
469 
470  return SCIP_OKAY;
471 }
472 
473 /** adds rows to the LP */
475  SCIP_LPI* lpi, /**< LP interface structure */
476  int nrows, /**< number of rows to be added */
477  const SCIP_Real* lhs, /**< left hand sides of new rows */
478  const SCIP_Real* rhs, /**< right hand sides of new rows */
479  char** rownames, /**< row names, or NULL */
480  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
481  const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
482  const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
483  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
484  )
485 {
486  assert( lpi != NULL );
487  assert( lpi->linear_program != NULL );
488  assert( lhs != NULL );
489  assert( rhs != NULL );
490  assert( nnonz >= 0) ;
491  assert( nrows >= 0) ;
492 
493  SCIPdebugMessage("adding %d rows with %d nonzeros.\n", nrows, nnonz);
494 
495  /* @todo add names */
496  if ( nnonz > 0 )
497  {
498  assert( beg != NULL );
499  assert( ind != NULL );
500  assert( val != NULL );
501  assert( nrows > 0 );
502 
503 #ifndef NDEBUG
504  /* perform check that no new columns are added - this is likely to be a mistake */
505  const ColIndex num_cols = lpi->linear_program->num_variables();
506  for (int j = 0; j < nnonz; ++j)
507  {
508  assert( val[j] != 0.0 );
509  assert( 0 <= ind[j] && ind[j] < num_cols.value() );
510  }
511 #endif
512 
513  int nz = 0;
514  for (int i = 0; i < nrows; ++i)
515  {
516  const RowIndex row = lpi->linear_program->CreateNewConstraint();
517  lpi->linear_program->SetConstraintBounds(row, lhs[i], rhs[i]);
518  const int end = (nnonz == 0 || i == nrows - 1) ? nnonz : beg[i + 1];
519  while ( nz < end )
520  {
521  lpi->linear_program->SetCoefficient(row, ColIndex(ind[nz]), val[nz]);
522  ++nz;
523  }
524  }
525  assert( nz == nnonz );
526  }
527  else
528  {
529  for (int i = 0; i < nrows; ++i)
530  {
531  const RowIndex row = lpi->linear_program->CreateNewConstraint();
532  lpi->linear_program->SetConstraintBounds(row, lhs[i], rhs[i]);
533  }
534  }
535 
536  lpi->lp_modified_since_last_solve = true;
537 
538  return SCIP_OKAY;
539 }
540 
541 /** delete rows from LP and update the current basis */
542 static
544  SCIP_LPI* lpi, /**< LP interface structure */
545  const DenseBooleanColumn& rows_to_delete /**< array to mark rows that should be deleted */
546  )
547 {
548  const RowIndex num_rows = lpi->linear_program->num_constraints();
549  const ColIndex num_cols = lpi->linear_program->num_variables();
550 
551  /* try to repair basis status if problem size has not changed before */
552  BasisState state = lpi->solver->GetState();
553  if ( state.statuses.size() == num_cols.value() + num_rows.value() )
554  {
555  /* Shift the status of the non-deleted rows. Note that if the deleted rows where part of the basis (i.e., constraint
556  * not tight), then we should be left with a correct basis afterward. This should be the most common use case in SCIP. */
557  ColIndex new_size = num_cols;
558  for (RowIndex row(0); row < num_rows; ++row)
559  {
560  if ( rows_to_delete[row] )
561  continue;
562  state.statuses[new_size++] = state.statuses[num_cols + RowToColIndex(row)];
563  }
564  state.statuses.resize(new_size);
565  lpi->solver->LoadStateForNextSolve(state);
566  }
567 
568  lpi->linear_program->DeleteRows(rows_to_delete);
569  lpi->lp_modified_since_last_solve = true;
570 }
571 
572 /** deletes all rows in the given range from LP */
574  SCIP_LPI* lpi, /**< LP interface structure */
575  int firstrow, /**< first row to be deleted */
576  int lastrow /**< last row to be deleted */
577  )
578 {
579  assert( lpi != NULL );
580  assert( lpi->linear_program != NULL );
581  assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->linear_program->num_constraints() );
582 
583  const RowIndex num_rows = lpi->linear_program->num_constraints();
584  DenseBooleanColumn rows_to_delete(num_rows, false);
585  for (int i = firstrow; i <= lastrow; ++i)
586  rows_to_delete[RowIndex(i)] = true;
587 
588  SCIPdebugMessage("deleting rows %d to %d.\n", firstrow, lastrow);
589  deleteRowsAndUpdateCurrentBasis(lpi, rows_to_delete);
590 
591  return SCIP_OKAY;
592 }
593 
594 /** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
596  SCIP_LPI* lpi, /**< LP interface structure */
597  int* dstat /**< deletion status of rows
598  * input: 1 if row should be deleted, 0 if not
599  * output: new position of row, -1 if row was deleted */
600  )
601 {
602  assert( lpi != NULL );
603  assert( lpi->linear_program != NULL );
604 
605  const RowIndex num_rows = lpi->linear_program->num_constraints();
606  DenseBooleanColumn rows_to_delete(num_rows, false);
607  int new_index = 0;
608  int num_deleted_rows = 0;
609  for (RowIndex row(0); row < num_rows; ++row)
610  {
611  int i = row.value();
612  if (dstat[i] == 1)
613  {
614  rows_to_delete[row] = true;
615  dstat[i] = -1;
616  ++num_deleted_rows;
617  }
618  else
619  dstat[i] = new_index++;
620  }
621 
622  SCIPdebugMessage("SCIPlpiDelRowset: deleting %d rows.\n", num_deleted_rows);
623  deleteRowsAndUpdateCurrentBasis(lpi, rows_to_delete);
624 
625  return SCIP_OKAY;
626 }
627 
628 /** clears the whole LP */
630  SCIP_LPI* lpi /**< LP interface structure */
631  )
632 {
633  assert( lpi != NULL );
634  assert( lpi->linear_program != NULL );
635 
636  SCIPdebugMessage("SCIPlpiClear\n");
637 
638  lpi->linear_program->Clear();
639  lpi->lp_modified_since_last_solve = true;
640 
641  return SCIP_OKAY;
642 }
643 
644 /** changes lower and upper bounds of columns */
646  SCIP_LPI* lpi, /**< LP interface structure */
647  int ncols, /**< number of columns to change bounds for */
648  const int* ind, /**< column indices or NULL if ncols is zero */
649  const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
650  const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
651  )
652 {
653  assert( lpi != NULL );
654  assert( lpi->linear_program != NULL );
655  assert( ncols == 0 || (ind != NULL && lb != NULL && ub != NULL) );
656 
657  SCIPdebugMessage("changing %d bounds.\n", ncols);
658  if ( ncols <= 0 )
659  return SCIP_OKAY;
660 
661  for (int i = 0; i < ncols; ++i)
662  {
663  SCIPdebugMessage(" col %d: [%g,%g]\n", ind[i], lb[i], ub[i]);
664 
665  if ( SCIPlpiIsInfinity(lpi, lb[i]) )
666  {
667  SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
668  return SCIP_LPERROR;
669  }
670  if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
671  {
672  SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
673  return SCIP_LPERROR;
674  }
675 
676  lpi->linear_program->SetVariableBounds(ColIndex(ind[i]), lb[i], ub[i]);
677  }
678  lpi->lp_modified_since_last_solve = true;
679 
680  return SCIP_OKAY;
681 }
682 
683 /** changes left and right hand sides of rows */
685  SCIP_LPI* lpi, /**< LP interface structure */
686  int nrows, /**< number of rows to change sides for */
687  const int* ind, /**< row indices */
688  const SCIP_Real* lhs, /**< new values for left hand sides */
689  const SCIP_Real* rhs /**< new values for right hand sides */
690  )
691 {
692  assert( lpi != NULL );
693  assert( lpi->linear_program != NULL );
694 
695  if ( nrows <= 0 )
696  return SCIP_OKAY;
697 
698  SCIPdebugMessage("changing %d sides\n", nrows);
699 
700  for (int i = 0; i < nrows; ++i)
701  lpi->linear_program->SetConstraintBounds(RowIndex(ind[i]), lhs[i], rhs[i]);
702 
703  lpi->lp_modified_since_last_solve = true;
704 
705  return SCIP_OKAY;
706 }
707 
708 /** changes a single coefficient */
710  SCIP_LPI* lpi, /**< LP interface structure */
711  int row, /**< row number of coefficient to change */
712  int col, /**< column number of coefficient to change */
713  SCIP_Real newval /**< new value of coefficient */
714  )
715 {
716  assert( lpi != NULL );
717  assert( lpi->linear_program != NULL );
718  assert( 0 <= row && row < lpi->linear_program->num_constraints().value() );
719  assert( 0 <= col && col < lpi->linear_program->num_variables().value() );
720 
721  SCIPdebugMessage("Set coefficient (%d,%d) to %f.\n", row, col, newval);
722  lpi->linear_program->CleanUp();
723  assert( lpi->linear_program->IsCleanedUp() );
724  lpi->linear_program->SetCoefficient(RowIndex(row), ColIndex(col), newval);
725 
726  lpi->lp_modified_since_last_solve = true;
727 
728  return SCIP_OKAY;
729 }
730 
731 /** changes the objective sense */
733  SCIP_LPI* lpi, /**< LP interface structure */
734  SCIP_OBJSEN objsen /**< new objective sense */
735  )
736 {
737  assert( lpi != NULL);
738  assert( lpi->linear_program != NULL);
739 
740  SCIPdebugMessage("changing objective sense to %d\n", objsen);
741 
742  switch (objsen)
743  {
745  lpi->linear_program->SetMaximizationProblem(true);
746  break;
748  lpi->linear_program->SetMaximizationProblem(false);
749  break;
750  }
751  lpi->lp_modified_since_last_solve = true;
752 
753  return SCIP_OKAY;
754 }
755 
756 /** changes objective values of columns in the LP */
758  SCIP_LPI* lpi, /**< LP interface structure */
759  int ncols, /**< number of columns to change objective value for */
760  const int* ind, /**< column indices to change objective value for */
761  const SCIP_Real* obj /**< new objective values for columns */
762  )
763 {
764  assert( lpi != NULL );
765  assert( lpi->linear_program != NULL );
766  assert( ind != NULL );
767  assert( obj != NULL );
768 
769  SCIPdebugMessage("changing %d objective values\n", ncols);
770 
771  for (int i = 0; i < ncols; ++i)
772  lpi->linear_program->SetObjectiveCoefficient(ColIndex(ind[i]), obj[i]);
773 
774  lpi->lp_modified_since_last_solve = true;
775 
776  return SCIP_OKAY;
777 }
778 
779 /** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
781  SCIP_LPI* lpi, /**< LP interface structure */
782  int row, /**< row number to scale */
783  SCIP_Real scaleval /**< scaling multiplier */
784  )
785 {
786  SCIP_Real* vals;
787  SCIP_Real lhs;
788  SCIP_Real rhs;
789  int nnonz;
790  int* inds;
791  int beg;
792 
793  assert( lpi != NULL );
794  assert( lpi->linear_program != NULL );
795 
796  SCIPdebugMessage("Scale row %d by %f.\n", row, scaleval);
797 
798  /* alloc memory */
799  ColIndex num_cols = lpi->linear_program->num_variables();
800 
801  SCIP_ALLOC( BMSallocMemoryArray(&inds, num_cols.value()) );
802  SCIP_ALLOC( BMSallocMemoryArray(&vals, num_cols.value()) );
803 
804  /* get the row */
805  SCIP_CALL( SCIPlpiGetRows(lpi, row, row, &lhs, &rhs, &nnonz, &beg, inds, vals) );
806 
807  /* scale row coefficients */
808  for (int j = 0; j < nnonz; ++j)
809  {
810  SCIP_CALL( SCIPlpiChgCoef(lpi, row, inds[j], vals[j] * scaleval) );
811  }
812  BMSfreeMemoryArray(&vals);
813  BMSfreeMemoryArray(&inds);
814 
815  /* scale row sides */
816  if ( ! SCIPlpiIsInfinity(lpi, -lhs) )
817  lhs *= scaleval;
818  else if ( scaleval < 0.0 )
819  lhs = SCIPlpiInfinity(lpi);
820 
821  if ( ! SCIPlpiIsInfinity(lpi, rhs) )
822  rhs *= scaleval;
823  else if ( scaleval < 0.0 )
824  rhs = -SCIPlpiInfinity(lpi);
825 
826  if ( scaleval > 0.0 )
827  {
828  SCIP_CALL( SCIPlpiChgSides(lpi, 1, &row, &lhs, &rhs) );
829  }
830  else
831  {
832  SCIP_CALL( SCIPlpiChgSides(lpi, 1, &row, &rhs, &lhs) );
833  }
834 
835  lpi->lp_modified_since_last_solve = true;
836 
837  return SCIP_OKAY;
838 }
839 
840 /** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
841  * are divided by the scalar; for negative scalars, the column's bounds are switched
842  */
844  SCIP_LPI* lpi, /**< LP interface structure */
845  int col, /**< column number to scale */
846  SCIP_Real scaleval /**< scaling multiplier */
847  )
848 {
849  SCIP_Real* vals;
850  SCIP_Real lb;
851  SCIP_Real ub;
852  SCIP_Real obj;
853  int nnonz;
854  int* inds;
855  int beg;
856 
857  assert( lpi != NULL );
858  assert( lpi->linear_program != NULL );
859 
860  SCIPdebugMessage("Scale column %d by %f.\n", col, scaleval);
861 
862  /* alloc memory */
863  RowIndex num_rows = lpi->linear_program->num_constraints();
864 
865  SCIP_ALLOC( BMSallocMemoryArray(&inds, num_rows.value()) );
866  SCIP_ALLOC( BMSallocMemoryArray(&vals, num_rows.value()) );
867 
868  /* get the column */
869  SCIP_CALL( SCIPlpiGetCols(lpi, col, col, &lb, &ub, &nnonz, &beg, inds, vals) );
870 
871  /* scale column coefficients */
872  for (int j = 0; j < nnonz; ++j)
873  {
874  SCIP_CALL( SCIPlpiChgCoef(lpi, col, inds[j], vals[j] * scaleval) );
875  }
876  BMSfreeMemoryArray(&vals);
877  BMSfreeMemoryArray(&inds);
878 
879  /* scale objective value */
880  SCIP_CALL( SCIPlpiGetObj(lpi, col, col, &obj) );
881  obj *= scaleval;
882  SCIP_CALL( SCIPlpiChgObj(lpi, 1, &col, &obj) );
883 
884  /* scale bound */
885  if ( ! SCIPlpiIsInfinity(lpi, -lb) )
886  lb *= scaleval;
887  else if ( scaleval < 0.0 )
888  lb = SCIPlpiInfinity(lpi);
889 
890  if ( ! SCIPlpiIsInfinity(lpi, ub) )
891  ub *= scaleval;
892  else if ( scaleval < 0.0 )
893  ub = -SCIPlpiInfinity(lpi);
894 
895  if ( scaleval > 0.0 )
896  {
897  SCIP_CALL( SCIPlpiChgBounds(lpi, 1, &col, &lb, &ub) );
898  }
899  else
900  {
901  SCIP_CALL( SCIPlpiChgBounds(lpi, 1, &col, &ub, &lb) );
902  }
903 
904  return SCIP_OKAY;
905 }
906 
907 
908 /**@} */
909 
910 
911 
912 
913 /*
914  * Data Accessing Methods
915  */
916 
917 /**@name Data Accessing Methods */
918 /**@{ */
919 
920 /** gets the number of rows in the LP */
922  SCIP_LPI* lpi, /**< LP interface structure */
923  int* nrows /**< pointer to store the number of rows */
924  )
925 {
926  assert( lpi != NULL );
927  assert( lpi->linear_program != NULL );
928  assert( nrows != NULL );
929 
930  SCIPdebugMessage("getting number of rows.\n");
931 
932  *nrows = lpi->linear_program->num_constraints().value();
933 
934  return SCIP_OKAY;
935 }
936 
937 /** gets the number of columns in the LP */
939  SCIP_LPI* lpi, /**< LP interface structure */
940  int* ncols /**< pointer to store the number of cols */
941  )
942 {
943  assert( lpi != NULL );
944  assert( lpi->linear_program != NULL );
945  assert( ncols != NULL );
946 
947  SCIPdebugMessage("getting number of columns.\n");
948 
949  *ncols = lpi->linear_program->num_variables().value();
950 
951  return SCIP_OKAY;
952 }
953 
954 /** gets objective sense of the LP */
956  SCIP_LPI* lpi, /**< LP interface structure */
957  SCIP_OBJSEN* objsen /**< pointer to store objective sense */
958  )
959 {
960  assert( lpi != NULL );
961  assert( lpi->linear_program != NULL );
962  assert( objsen != NULL );
963 
964  SCIPdebugMessage("getting objective sense.\n");
965 
966  *objsen = lpi->linear_program->IsMaximizationProblem() ? SCIP_OBJSEN_MAXIMIZE : SCIP_OBJSEN_MINIMIZE;
967 
968  return SCIP_OKAY;
969 }
970 
971 /** gets the number of nonzero elements in the LP constraint matrix */
973  SCIP_LPI* lpi, /**< LP interface structure */
974  int* nnonz /**< pointer to store the number of nonzeros */
975  )
976 {
977  assert( lpi != NULL );
978  assert( lpi->linear_program != NULL );
979  assert( nnonz != NULL );
980 
981  SCIPdebugMessage("getting number of non-zeros.\n");
982 
983  *nnonz = (int) lpi->linear_program->num_entries().value();
984 
985  return SCIP_OKAY;
986 }
987 
988 /** gets columns from LP problem object; the arrays have to be large enough to store all values
989  * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
990  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
991  */
993  SCIP_LPI* lpi, /**< LP interface structure */
994  int firstcol, /**< first column to get from LP */
995  int lastcol, /**< last column to get from LP */
996  SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
997  SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
998  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
999  int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1000  int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1001  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1002  )
1003 {
1004  assert( lpi != NULL );
1005  assert( lpi->linear_program != NULL );
1006  assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->linear_program->num_variables() );
1007  assert( (lb != NULL && ub != NULL) || (lb == NULL && ub == NULL) );
1008  assert( (nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL) );
1009 
1010  const DenseRow& tmplb = lpi->linear_program->variable_lower_bounds();
1011  const DenseRow& tmpub = lpi->linear_program->variable_upper_bounds();
1012 
1013  if ( nnonz != NULL )
1014  {
1015  assert( beg != NULL );
1016  assert( ind != NULL );
1017  assert( val != NULL );
1018 
1019  *nnonz = 0;
1020  int index = 0;
1021  for (ColIndex col(firstcol); col <= ColIndex(lastcol); ++col, ++index)
1022  {
1023  if ( lb != NULL )
1024  lb[index] = tmplb[col];
1025  if ( ub != NULL )
1026  ub[index] = tmpub[col];
1027 
1028  beg[index] = *nnonz;
1029  const SparseColumn& column = lpi->linear_program->GetSparseColumn(col);
1030  for (const SparseColumn::Entry& entry : column)
1031  {
1032  const RowIndex row = entry.row();
1033  ind[*nnonz] = row.value();
1034  val[*nnonz] = entry.coefficient();
1035  ++(*nnonz);
1036  }
1037  }
1038  }
1039  else
1040  {
1041  int index = 0;
1042  for (ColIndex col(firstcol); col <= ColIndex(lastcol); ++col, ++index)
1043  {
1044  if ( lb != NULL )
1045  lb[index] = tmplb[col];
1046  if ( ub != NULL )
1047  ub[index] = tmpub[col];
1048  }
1049  }
1050 
1051  return SCIP_OKAY;
1052 }
1053 
1054 /** gets rows from LP problem object; the arrays have to be large enough to store all values.
1055  * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
1056  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1057  */
1059  SCIP_LPI* lpi, /**< LP interface structure */
1060  int firstrow, /**< first row to get from LP */
1061  int lastrow, /**< last row to get from LP */
1062  SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
1063  SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
1064  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1065  int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
1066  int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
1067  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1068  )
1069 {
1070  assert( lpi != NULL );
1071  assert( lpi->linear_program != NULL );
1072  assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->linear_program->num_constraints() );
1073  assert( (lhs == NULL && rhs == NULL) || (rhs != NULL && lhs != NULL) );
1074  assert( (nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL) );
1075 
1076  const DenseColumn& tmplhs = lpi->linear_program->constraint_lower_bounds();
1077  const DenseColumn& tmprhs = lpi->linear_program->constraint_upper_bounds();
1078 
1079  if ( nnonz != NULL )
1080  {
1081  assert( beg != NULL );
1082  assert( ind != NULL );
1083  assert( val != NULL );
1084 
1085  const SparseMatrix& matrixtrans = lpi->linear_program->GetTransposeSparseMatrix();
1086 
1087  *nnonz = 0;
1088  int index = 0;
1089  for (RowIndex row(firstrow); row <= RowIndex(lastrow); ++row, ++index)
1090  {
1091  if ( lhs != NULL )
1092  lhs[index] = tmplhs[row];
1093  if ( rhs != NULL )
1094  rhs[index] = tmprhs[row];
1095 
1096  beg[index] = *nnonz;
1097  const SparseColumn& column = matrixtrans.column(ColIndex(row.value()));
1098  for (const SparseColumn::Entry& entry : column)
1099  {
1100  const RowIndex rowidx = entry.row();
1101  ind[*nnonz] = rowidx.value();
1102  val[*nnonz] = entry.coefficient();
1103  ++(*nnonz);
1104  }
1105  }
1106  }
1107  else
1108  {
1109  int index = 0;
1110  for (RowIndex row(firstrow); row <= RowIndex(lastrow); ++row, ++index)
1111  {
1112  if ( lhs != NULL )
1113  lhs[index] = tmplhs[row];
1114  if ( rhs != NULL )
1115  rhs[index] = tmprhs[row];
1116  }
1117  }
1118 
1119  return SCIP_OKAY;
1120 }
1121 
1122 /** gets column names */
1124  SCIP_LPI* lpi, /**< LP interface structure */
1125  int firstcol, /**< first column to get name from LP */
1126  int lastcol, /**< last column to get name from LP */
1127  char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
1128  char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
1129  int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
1130  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1131  )
1132 {
1133  assert( lpi != NULL );
1134  assert( lpi->linear_program != NULL );
1135  assert( colnames != NULL || namestoragesize == 0 );
1136  assert( namestorage != NULL || namestoragesize == 0 );
1137  assert( namestoragesize >= 0 );
1138  assert( storageleft != NULL );
1139  assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->linear_program->num_variables() );
1140 
1141  SCIPerrorMessage("SCIPlpiGetColNames() has not been implemented yet.\n");
1142 
1143  return SCIP_NOTIMPLEMENTED;
1144 }
1145 
1146 /** gets row names */
1148  SCIP_LPI* lpi, /**< LP interface structure */
1149  int firstrow, /**< first row to get name from LP */
1150  int lastrow, /**< last row to get name from LP */
1151  char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
1152  char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
1153  int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1154  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1155  )
1156 {
1157  assert( lpi != NULL );
1158  assert( lpi->linear_program != NULL );
1159  assert( rownames != NULL || namestoragesize == 0 );
1160  assert( namestorage != NULL || namestoragesize == 0 );
1161  assert( namestoragesize >= 0 );
1162  assert( storageleft != NULL );
1163  assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->linear_program->num_constraints() );
1164 
1165  SCIPerrorMessage("SCIPlpiGetRowNames() has not been implemented yet.\n");
1166 
1167  return SCIP_NOTIMPLEMENTED;
1168 }
1169 
1170 /** gets objective coefficients from LP problem object */
1172  SCIP_LPI* lpi, /**< LP interface structure */
1173  int firstcol, /**< first column to get objective coefficient for */
1174  int lastcol, /**< last column to get objective coefficient for */
1175  SCIP_Real* vals /**< array to store objective coefficients */
1176  )
1177 {
1178  assert( lpi != NULL );
1179  assert( lpi->linear_program != NULL );
1180  assert( firstcol <= lastcol );
1181  assert( vals != NULL );
1182 
1183  SCIPdebugMessage("getting objective values %d to %d\n", firstcol, lastcol);
1184 
1185  int index = 0;
1186  for (ColIndex col(firstcol); col <= ColIndex(lastcol); ++col)
1187  {
1188  vals[index] = lpi->linear_program->objective_coefficients()[col];
1189  ++index;
1190  }
1191 
1192  return SCIP_OKAY;
1193 }
1194 
1195 /** gets current bounds from LP problem object */
1197  SCIP_LPI* lpi, /**< LP interface structure */
1198  int firstcol, /**< first column to get bounds for */
1199  int lastcol, /**< last column to get bounds for */
1200  SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
1201  SCIP_Real* ubs /**< array to store upper bound values, or NULL */
1202  )
1203 {
1204  assert( lpi != NULL );
1205  assert( lpi->linear_program != NULL );
1206  assert( firstcol <= lastcol );
1207 
1208  SCIPdebugMessage("getting bounds %d to %d\n", firstcol, lastcol);
1209 
1210  int index = 0;
1211  for (ColIndex col(firstcol); col <= ColIndex(lastcol); ++col)
1212  {
1213  if ( lbs != NULL )
1214  lbs[index] = lpi->linear_program->variable_lower_bounds()[col];
1215 
1216  if ( ubs != NULL )
1217  ubs[index] = lpi->linear_program->variable_upper_bounds()[col];
1218 
1219  ++index;
1220  }
1221 
1222  return SCIP_OKAY;
1223 }
1224 
1225 /** gets current row sides from LP problem object */
1227  SCIP_LPI* lpi, /**< LP interface structure */
1228  int firstrow, /**< first row to get sides for */
1229  int lastrow, /**< last row to get sides for */
1230  SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
1231  SCIP_Real* rhss /**< array to store right hand side values, or NULL */
1232  )
1233 {
1234  assert( lpi != NULL );
1235  assert( lpi->linear_program != NULL );
1236  assert( firstrow <= lastrow );
1237 
1238  SCIPdebugMessage("getting row sides %d to %d\n", firstrow, lastrow);
1239 
1240  int index = 0;
1241  for (RowIndex row(firstrow); row <= RowIndex(lastrow); ++row)
1242  {
1243  if ( lhss != NULL )
1244  lhss[index] = lpi->linear_program->constraint_lower_bounds()[row];
1245 
1246  if ( rhss != NULL )
1247  rhss[index] = lpi->linear_program->constraint_upper_bounds()[row];
1248 
1249  ++index;
1250  }
1251 
1252  return SCIP_OKAY;
1253 }
1254 
1255 /** gets a single coefficient */
1257  SCIP_LPI* lpi, /**< LP interface structure */
1258  int row, /**< row number of coefficient */
1259  int col, /**< column number of coefficient */
1260  SCIP_Real* val /**< pointer to store the value of the coefficient */
1261  )
1262 {
1263  assert( lpi != NULL );
1264  assert( lpi->linear_program != NULL );
1265  assert( val != NULL );
1266 
1267  /* quite slow method: possibly needs linear time if matrix is not sorted */
1268  const SparseMatrix& matrix = lpi->linear_program->GetSparseMatrix();
1269  *val = matrix.LookUpValue(RowIndex(row), ColIndex(col));
1270 
1271  return SCIP_OKAY;
1272 }
1273 
1274 /**@} */
1275 
1276 
1277 
1278 
1279 /*
1280  * Solving Methods
1281  */
1282 
1283 /**@name Solving Methods */
1284 /**@{ */
1285 
1286 /** update scaled linear program */
1287 static
1289  SCIP_LPI* lpi /**< LP interface structure */
1290  )
1291 {
1292  if ( ! lpi->lp_modified_since_last_solve )
1293  return;
1294 
1295  lpi->scaled_lp->PopulateFromLinearProgram(*lpi->linear_program);
1296  lpi->scaled_lp->AddSlackVariablesWhereNecessary(false);
1297 
1298  /* @todo: Avoid doing a copy if there is no scaling. */
1299  /* @todo: Avoid rescaling if not much changed. */
1300  if ( lpi->parameters->use_scaling() )
1301  lpi->scaler->Scale(lpi->scaled_lp);
1302  else
1303  lpi->scaler->Clear();
1304 }
1305 
1306 /** check primal feasibility */
1307 static
1309  SCIP_LPI* lpi /**< LP interface structure */
1310  )
1311 {
1312  assert( lpi != NULL );
1313  assert( lpi->solver != NULL );
1314  assert( lpi->linear_program != NULL );
1315 
1316 #if UNSCALEDFEAS_CHECK == 1
1317  /* get unscaled solution */
1318  const ColIndex num_cols = lpi->linear_program->num_variables();
1319  DenseRow unscaledsol(num_cols);
1320  for (ColIndex col = ColIndex(0); col < num_cols; ++col)
1321  unscaledsol[col] = lpi->scaler->UnscaleVariableValue(col, lpi->solver->GetVariableValue(col));
1322 
1323  /* if the solution is not feasible w.r.t. absolute tolerances, try to fix it in the unscaled problem */
1324  const double feastol = lpi->parameters->primal_feasibility_tolerance();
1325  return lpi->linear_program->SolutionIsLPFeasible(unscaledsol, feastol);
1326 
1327 #elif UNSCALEDFEAS_CHECK == 2
1328  const double feastol = lpi->parameters->primal_feasibility_tolerance();
1329 
1330  /* check bounds of unscaled solution */
1331  const ColIndex num_cols = lpi->linear_program->num_variables();
1332  for (ColIndex col = ColIndex(0); col < num_cols; ++col)
1333  {
1334  const Fractional val = lpi->scaler->UnscaleVariableValue(col, lpi->solver->GetVariableValue(col));
1335  const Fractional lb = lpi->linear_program->variable_lower_bounds()[col];
1336  if ( val < lb - feastol )
1337  return false;
1338  const Fractional ub = lpi->linear_program->variable_upper_bounds()[col];
1339  if ( val > ub + feastol )
1340  return false;
1341  }
1342 
1343  /* check activities of unscaled solution */
1344  const RowIndex num_rows = lpi->linear_program->num_constraints();
1345  for (RowIndex row(0); row < num_rows; ++row)
1346  {
1347  const Fractional val = lpi->scaler->UnscaleConstraintActivity(row, lpi->solver->GetConstraintActivity(row));
1348  const Fractional lhs = lpi->linear_program->constraint_lower_bounds()[row];
1349  if ( val < lhs - feastol )
1350  return false;
1351  const Fractional rhs = lpi->linear_program->constraint_upper_bounds()[row];
1352  if ( val > rhs + feastol )
1353  return false;
1354  }
1355 #endif
1356 
1357  return true;
1358 }
1359 
1360 /** common function between the two LPI Solve() functions */
1361 static
1363  SCIP_LPI* lpi, /**< LP interface structure */
1364  bool recursive, /**< Is this a recursive call? */
1365  std::unique_ptr<TimeLimit>& time_limit /**< time limit */
1366  )
1367 {
1368  assert( lpi != NULL );
1369  assert( lpi->solver != NULL );
1370  assert( lpi->parameters != NULL );
1371 
1372  updateScaledLP(lpi);
1373 
1374  lpi->solver->SetParameters(*(lpi->parameters));
1375  lpi->lp_time_limit_was_reached = false;
1376 
1377  /* possibly ignore warm start information for next solve */
1378  if ( lpi->from_scratch )
1379  lpi->solver->ClearStateForNextSolve();
1380 
1381  if ( ! lpi->solver->Solve(*(lpi->scaled_lp), time_limit.get()).ok() )
1382  {
1383  return SCIP_LPERROR;
1384  }
1385  lpi->lp_time_limit_was_reached = time_limit->LimitReached();
1386  if ( recursive )
1387  lpi->niterations += (SCIP_Longint) lpi->solver->GetNumberOfIterations();
1388  else
1389  lpi->niterations = (SCIP_Longint) lpi->solver->GetNumberOfIterations();
1390 
1391  SCIPdebugMessage("status=%s obj=%f iter=%ld.\n", GetProblemStatusString(lpi->solver->GetProblemStatus()).c_str(),
1392  lpi->solver->GetObjectiveValue(), lpi->solver->GetNumberOfIterations());
1393 
1394  const ProblemStatus status = lpi->solver->GetProblemStatus();
1395  if ( (status == ProblemStatus::PRIMAL_FEASIBLE || status == ProblemStatus::OPTIMAL) && lpi->parameters->use_scaling() )
1396  {
1397  if ( ! checkUnscaledPrimalFeasibility(lpi) )
1398  {
1399  SCIPdebugMessage("Solution not feasible w.r.t. absolute tolerance %g -> reoptimize.\n", lpi->parameters->primal_feasibility_tolerance());
1400 
1401  /* Re-solve without scaling to try to fix the infeasibility. */
1402  lpi->parameters->set_use_scaling(false);
1403  lpi->lp_modified_since_last_solve = true;
1404  SolveInternal(lpi, true, time_limit); /* inherit time limit, so used time is not reset; do not change iteration limit for resolve */
1405  lpi->parameters->set_use_scaling(true);
1406 
1407 #ifdef SCIP_DEBUG
1408  if ( ! checkUnscaledPrimalFeasibility(lpi) )
1409  SCIPdebugMessage("Solution still not feasible after turning off scaling.\n");
1410 #endif
1411  }
1412  }
1413 
1414  lpi->lp_modified_since_last_solve = false;
1415 
1416  return SCIP_OKAY;
1417 }
1418 
1419 /** calls primal simplex to solve the LP */
1421  SCIP_LPI* lpi /**< LP interface structure */
1422  )
1423 {
1424  assert( lpi != NULL );
1425  assert( lpi->solver != NULL );
1426  assert( lpi->linear_program != NULL );
1427  assert( lpi->parameters != NULL );
1428 
1429  SCIPdebugMessage("SCIPlpiSolvePrimal: %d rows, %d cols.\n", lpi->linear_program->num_constraints().value(), lpi->linear_program->num_variables().value());
1430  std::unique_ptr<TimeLimit> time_limit = TimeLimit::FromParameters(*lpi->parameters);
1431  lpi->niterations = 0;
1432 
1433  lpi->parameters->set_use_dual_simplex(false);
1434  return SolveInternal(lpi, false, time_limit);
1435 }
1436 
1437 /** calls dual simplex to solve the LP */
1439  SCIP_LPI* lpi /**< LP interface structure */
1440  )
1441 {
1442  assert( lpi != NULL );
1443  assert( lpi->solver != NULL );
1444  assert( lpi->linear_program != NULL );
1445  assert( lpi->parameters != NULL );
1446 
1447  SCIPdebugMessage("SCIPlpiSolveDual: %d rows, %d cols.\n", lpi->linear_program->num_constraints().value(), lpi->linear_program->num_variables().value());
1448  std::unique_ptr<TimeLimit> time_limit = TimeLimit::FromParameters(*lpi->parameters);
1449  lpi->niterations = 0;
1450 
1451  lpi->parameters->set_use_dual_simplex(true);
1452  return SolveInternal(lpi, false, time_limit);
1453 }
1454 
1455 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
1457  SCIP_LPI* lpi, /**< LP interface structure */
1458  SCIP_Bool crossover /**< perform crossover */
1459  )
1460 {
1461  assert( lpi != NULL );
1462  assert( lpi->solver != NULL );
1463  assert( lpi->linear_program != NULL );
1464  assert( lpi->parameters != NULL );
1465 
1466  SCIPerrorMessage("SCIPlpiSolveBarrier - Not supported.\n");
1467 
1468  return SCIP_NOTIMPLEMENTED;
1469 }
1470 
1471 /** start strong branching */
1473  SCIP_LPI* lpi /**< LP interface structure */
1474  )
1475 { /*lint --e{715}*/
1476  assert( lpi != NULL );
1477  assert( lpi->linear_program != NULL );
1478  assert( lpi->solver != NULL );
1479 
1480  updateScaledLP(lpi);
1481 
1482  /* @todo Save state and do all the branching from there. */
1483  return SCIP_OKAY;
1484 }
1485 
1486 /** end strong branching */
1488  SCIP_LPI* lpi /**< LP interface structure */
1489  )
1490 { /*lint --e{715}*/
1491  assert( lpi != NULL );
1492  assert( lpi->linear_program != NULL );
1493  assert( lpi->solver != NULL );
1494 
1495  /* @todo Restore the saved state. */
1496  return SCIP_OKAY;
1497 }
1498 
1499 /** determine whether the dual bound is valid */
1500 static
1502  ProblemStatus status /**< status to be checked */
1503  )
1504 {
1505  return status == ProblemStatus::OPTIMAL || status == ProblemStatus::DUAL_FEASIBLE || status == ProblemStatus::DUAL_UNBOUNDED;
1506 }
1507 
1508 /** performs strong branching iterations */
1509 static
1511  SCIP_LPI* lpi, /**< LP interface structure */
1512  int col_index, /**< column to apply strong branching on */
1513  SCIP_Real psol, /**< fractional current primal solution value of column */
1514  int itlim, /**< iteration limit for strong branchings */
1515  SCIP_Real* down, /**< stores dual bound after branching column down */
1516  SCIP_Real* up, /**< stores dual bound after branching column up */
1517  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
1518  * otherwise, it can only be used as an estimate value */
1519  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
1520  * otherwise, it can only be used as an estimate value */
1521  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1522  )
1523 {
1524  assert( lpi != NULL );
1525  assert( lpi->scaled_lp != NULL );
1526  assert( down != NULL );
1527  assert( up != NULL );
1528  assert( downvalid != NULL );
1529  assert( upvalid != NULL );
1530 
1531  SCIPdebugMessage("calling strongbranching on variable %d (%d iterations)\n", col_index, itlim);
1532 
1533  /* We work on the scaled problem. */
1534  const ColIndex col(col_index);
1535  const Fractional lb = lpi->scaled_lp->variable_lower_bounds()[col];
1536  const Fractional ub = lpi->scaled_lp->variable_upper_bounds()[col];
1537  const double value = psol * lpi->scaler->VariableScalingFactor(col);
1538 
1539  /* Configure solver. */
1540 
1541  /* @todo Use the iteration limit once glop supports incrementality. */
1542  int num_iterations = 0;
1543  lpi->parameters->set_use_dual_simplex(true);
1544  lpi->solver->SetParameters(*(lpi->parameters));
1545  const Fractional eps = lpi->parameters->primal_feasibility_tolerance();
1546 
1547  std::unique_ptr<TimeLimit> time_limit = TimeLimit::FromParameters(*lpi->parameters);
1548 
1549  /* Down branch. */
1550  const Fractional newub = EPSCEIL(value - 1.0, eps);
1551  if ( newub >= lb - 0.5 )
1552  {
1553  lpi->scaled_lp->SetVariableBounds(col, lb, newub);
1554 
1555  if ( lpi->solver->Solve(*(lpi->scaled_lp), time_limit.get()).ok() )
1556  {
1557  num_iterations += (int) lpi->solver->GetNumberOfIterations();
1558  *down = lpi->solver->GetObjectiveValue();
1559  *downvalid = IsDualBoundValid(lpi->solver->GetProblemStatus()) ? TRUE : FALSE;
1560 
1561  SCIPdebugMessage("down: itlim=%d col=%d [%f,%f] obj=%f status=%d iter=%ld.\n", itlim, col_index, lb, EPSCEIL(value - 1.0, eps),
1562  lpi->solver->GetObjectiveValue(), (int) lpi->solver->GetProblemStatus(), lpi->solver->GetNumberOfIterations());
1563  }
1564  else
1565  {
1566  SCIPerrorMessage("error during solve");
1567  *down = 0.0;
1568  *downvalid = FALSE;
1569  }
1570  }
1571  else
1572  {
1573  if ( lpi->linear_program->IsMaximizationProblem() )
1574  *down = lpi->parameters->objective_lower_limit();
1575  else
1576  *down = lpi->parameters->objective_upper_limit();
1577  *downvalid = TRUE;
1578  }
1579 
1580  /* Up branch. */
1581  const Fractional newlb = EPSFLOOR(value + 1.0, eps);
1582  if ( newlb <= ub + 0.5 )
1583  {
1584  lpi->scaled_lp->SetVariableBounds(col, newlb, ub);
1585 
1586  if ( lpi->solver->Solve(*(lpi->scaled_lp), time_limit.get()).ok() )
1587  {
1588  num_iterations += (int) lpi->solver->GetNumberOfIterations();
1589  *up = lpi->solver->GetObjectiveValue();
1590  *upvalid = IsDualBoundValid(lpi->solver->GetProblemStatus()) ? TRUE : FALSE;
1591 
1592  SCIPdebugMessage("up: itlim=%d col=%d [%f,%f] obj=%f status=%d iter=%ld.\n", itlim, col_index, EPSFLOOR(value + 1.0, eps), ub,
1593  lpi->solver->GetObjectiveValue(), (int) lpi->solver->GetProblemStatus(), lpi->solver->GetNumberOfIterations());
1594  }
1595  else
1596  {
1597  SCIPerrorMessage("error during solve");
1598  *up = 0.0;
1599  *upvalid = FALSE;
1600  }
1601  }
1602  else
1603  {
1604  if (lpi->linear_program->IsMaximizationProblem())
1605  *up = lpi->parameters->objective_lower_limit();
1606  else
1607  *up = lpi->parameters->objective_upper_limit();
1608  *upvalid = TRUE;
1609  }
1610 
1611  /* Restore bound. */
1612  lpi->scaled_lp->SetVariableBounds(col, lb, ub);
1613  if ( iter != NULL )
1614  *iter = num_iterations;
1615 
1616  return SCIP_OKAY;
1617 }
1618 
1619 /** performs strong branching iterations on one @b fractional candidate */
1621  SCIP_LPI* lpi, /**< LP interface structure */
1622  int col_index, /**< column to apply strong branching on */
1623  SCIP_Real psol, /**< fractional current primal solution value of column */
1624  int itlim, /**< iteration limit for strong branchings */
1625  SCIP_Real* down, /**< stores dual bound after branching column down */
1626  SCIP_Real* up, /**< stores dual bound after branching column up */
1627  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
1628  * otherwise, it can only be used as an estimate value */
1629  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
1630  * otherwise, it can only be used as an estimate value */
1631  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1632  )
1633 {
1634  assert( lpi != NULL );
1635  assert( lpi->scaled_lp != NULL );
1636  assert( down != NULL );
1637  assert( up != NULL );
1638  assert( downvalid != NULL );
1639  assert( upvalid != NULL );
1640 
1641  SCIPdebugMessage("calling strongbranching on fractional variable %d (%d iterations)\n", col_index, itlim);
1642 
1643  SCIP_CALL( strongbranch(lpi, col_index, psol, itlim, down, up, downvalid, upvalid, iter) );
1644 
1645  return SCIP_OKAY;
1646 }
1647 
1648 /** performs strong branching iterations on given @b fractional candidates */
1650  SCIP_LPI* lpi, /**< LP interface structure */
1651  int* cols, /**< columns to apply strong branching on */
1652  int ncols, /**< number of columns */
1653  SCIP_Real* psols, /**< fractional current primal solution values of columns */
1654  int itlim, /**< iteration limit for strong branchings */
1655  SCIP_Real* down, /**< stores dual bounds after branching columns down */
1656  SCIP_Real* up, /**< stores dual bounds after branching columns up */
1657  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
1658  * otherwise, they can only be used as an estimate values */
1659  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
1660  * otherwise, they can only be used as an estimate values */
1661  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1662  )
1663 {
1664  assert( lpi != NULL );
1665  assert( lpi->linear_program != NULL );
1666  assert( cols != NULL );
1667  assert( psols != NULL );
1668  assert( down != NULL) ;
1669  assert( up != NULL );
1670  assert( downvalid != NULL );
1671  assert( upvalid != NULL );
1672 
1673  SCIPerrorMessage("SCIPlpiStrongbranchesFrac - not implemented.\n");
1674 
1675  return SCIP_NOTIMPLEMENTED;
1676 }
1677 
1678 /** performs strong branching iterations on one candidate with @b integral value */
1680  SCIP_LPI* lpi, /**< LP interface structure */
1681  int col, /**< column to apply strong branching on */
1682  SCIP_Real psol, /**< current integral primal solution value of column */
1683  int itlim, /**< iteration limit for strong branchings */
1684  SCIP_Real* down, /**< stores dual bound after branching column down */
1685  SCIP_Real* up, /**< stores dual bound after branching column up */
1686  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
1687  * otherwise, it can only be used as an estimate value */
1688  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
1689  * otherwise, it can only be used as an estimate value */
1690  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1691  )
1692 {
1693  assert( lpi != NULL );
1694  assert( lpi->linear_program != NULL );
1695  assert( down != NULL );
1696  assert( up != NULL );
1697  assert( downvalid != NULL );
1698  assert( upvalid != NULL );
1699 
1700  SCIP_CALL( strongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter) );
1701 
1702  return SCIP_OKAY;
1703 }
1704 
1705 /** performs strong branching iterations on given candidates with @b integral values */
1707  SCIP_LPI* lpi, /**< LP interface structure */
1708  int* cols, /**< columns to apply strong branching on */
1709  int ncols, /**< number of columns */
1710  SCIP_Real* psols, /**< current integral primal solution values of columns */
1711  int itlim, /**< iteration limit for strong branchings */
1712  SCIP_Real* down, /**< stores dual bounds after branching columns down */
1713  SCIP_Real* up, /**< stores dual bounds after branching columns up */
1714  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
1715  * otherwise, they can only be used as an estimate values */
1716  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
1717  * otherwise, they can only be used as an estimate values */
1718  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1719  )
1720 {
1721  assert( lpi != NULL );
1722  assert( lpi->linear_program != NULL );
1723  assert( cols != NULL );
1724  assert( psols != NULL );
1725  assert( down != NULL) ;
1726  assert( up != NULL );
1727  assert( downvalid != NULL );
1728  assert( upvalid != NULL );
1729 
1730  SCIPerrorMessage("SCIPlpiStrongbranchesInt - not implemented.\n");
1731 
1732  return SCIP_NOTIMPLEMENTED;
1733 }
1734 /**@} */
1735 
1736 
1737 
1738 
1739 /*
1740  * Solution Information Methods
1741  */
1742 
1743 /**@name Solution Information Methods */
1744 /**@{ */
1745 
1746 /** returns whether a solve method was called after the last modification of the LP */
1748  SCIP_LPI* lpi /**< LP interface structure */
1749  )
1750 {
1751  assert( lpi != NULL );
1752 
1753  /* @todo Track this to avoid uneeded resolving. */
1754  return ( ! lpi->lp_modified_since_last_solve );
1755 }
1756 
1757 /** gets information about primal and dual feasibility of the current LP solution
1758  *
1759  * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
1760  * returns true. If the LP is changed, this information might be invalidated.
1761  *
1762  * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
1763  * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
1764  * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
1765  * the problem might actually be feasible).
1766  */
1768  SCIP_LPI* lpi, /**< LP interface structure */
1769  SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
1770  SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
1771  )
1772 {
1773  assert( lpi != NULL );
1774  assert( lpi->solver != NULL );
1775  assert( primalfeasible != NULL );
1776  assert( dualfeasible != NULL );
1777 
1778  const ProblemStatus status = lpi->solver->GetProblemStatus();
1779  *primalfeasible = (status == ProblemStatus::OPTIMAL || status == ProblemStatus::PRIMAL_FEASIBLE);
1780  *dualfeasible = (status == ProblemStatus::OPTIMAL || status == ProblemStatus::DUAL_FEASIBLE);
1781 
1782  SCIPdebugMessage("SCIPlpiGetSolFeasibility primal:%d dual:%d\n", *primalfeasible, *dualfeasible);
1783 
1784  return SCIP_OKAY;
1785 }
1786 
1787 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
1788  * this does not necessarily mean, that the solver knows and can return the primal ray
1789  */
1791  SCIP_LPI* lpi /**< LP interface structure */
1792  )
1793 {
1794  assert( lpi != NULL );
1795  assert( lpi->solver != NULL );
1796 
1797  return lpi->solver->GetProblemStatus() == ProblemStatus::PRIMAL_UNBOUNDED;
1798 }
1799 
1800 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
1801  * and the solver knows and can return the primal ray
1802  */
1804  SCIP_LPI* lpi /**< LP interface structure */
1805  )
1806 {
1807  assert( lpi != NULL );
1808  assert( lpi->solver != NULL );
1809 
1810  return lpi->solver->GetProblemStatus() == ProblemStatus::PRIMAL_UNBOUNDED;
1811 }
1812 
1813 /** returns TRUE iff LP is proven to be primal unbounded */
1815  SCIP_LPI* lpi /**< LP interface structure */
1816  )
1817 {
1818  assert( lpi != NULL );
1819  assert( lpi->solver != NULL );
1820 
1821  return lpi->solver->GetProblemStatus() == ProblemStatus::PRIMAL_UNBOUNDED;
1822 }
1823 
1824 /** returns TRUE iff LP is proven to be primal infeasible */
1826  SCIP_LPI* lpi /**< LP interface structure */
1827  )
1828 {
1829  assert( lpi != NULL );
1830  assert( lpi->solver != NULL );
1831 
1832  const ProblemStatus status = lpi->solver->GetProblemStatus();
1833 
1834  return status == ProblemStatus::DUAL_UNBOUNDED || status == ProblemStatus::PRIMAL_INFEASIBLE;
1835 }
1836 
1837 /** returns TRUE iff LP is proven to be primal feasible */
1839  SCIP_LPI* lpi /**< LP interface structure */
1840  )
1841 {
1842  assert( lpi != NULL );
1843  assert( lpi->solver != NULL );
1844 
1845  const ProblemStatus status = lpi->solver->GetProblemStatus();
1846 
1847  return status == ProblemStatus::PRIMAL_FEASIBLE || status == ProblemStatus::OPTIMAL;
1848 }
1849 
1850 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
1851  * this does not necessarily mean, that the solver knows and can return the dual ray
1852  */
1854  SCIP_LPI* lpi /**< LP interface structure */
1855  )
1856 {
1857  assert( lpi != NULL );
1858  assert( lpi->solver != NULL );
1859 
1860  const ProblemStatus status = lpi->solver->GetProblemStatus();
1861 
1862  return status == ProblemStatus::DUAL_UNBOUNDED;
1863 }
1864 
1865 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
1866  * and the solver knows and can return the dual ray
1867  */
1869  SCIP_LPI* lpi /**< LP interface structure */
1870  )
1871 {
1872  assert( lpi != NULL );
1873  assert( lpi->solver != NULL );
1874 
1875  const ProblemStatus status = lpi->solver->GetProblemStatus();
1876 
1877  return status == ProblemStatus::DUAL_UNBOUNDED;
1878 }
1879 
1880 /** returns TRUE iff LP is proven to be dual unbounded */
1882  SCIP_LPI* lpi /**< LP interface structure */
1883  )
1884 {
1885  assert( lpi != NULL );
1886  assert( lpi->solver != NULL );
1887 
1888  const ProblemStatus status = lpi->solver->GetProblemStatus();
1889  return status == ProblemStatus::DUAL_UNBOUNDED;
1890 }
1891 
1892 /** returns TRUE iff LP is proven to be dual infeasible */
1894  SCIP_LPI* lpi /**< LP interface structure */
1895  )
1896 {
1897  assert( lpi != NULL );
1898  assert( lpi->solver != NULL );
1899 
1900  const ProblemStatus status = lpi->solver->GetProblemStatus();
1901  return status == ProblemStatus::PRIMAL_UNBOUNDED || status == ProblemStatus::DUAL_INFEASIBLE;
1902 }
1903 
1904 /** returns TRUE iff LP is proven to be dual feasible */
1906  SCIP_LPI* lpi /**< LP interface structure */
1907  )
1908 {
1909  assert( lpi != NULL );
1910  assert( lpi->solver != NULL );
1911 
1912  const ProblemStatus status = lpi->solver->GetProblemStatus();
1913 
1914  return status == ProblemStatus::DUAL_FEASIBLE || status == ProblemStatus::OPTIMAL;
1915 }
1916 
1917 /** returns TRUE iff LP was solved to optimality */
1919  SCIP_LPI* lpi /**< LP interface structure */
1920  )
1921 {
1922  assert( lpi != NULL );
1923  assert( lpi->solver != NULL );
1924 
1925  return lpi->solver->GetProblemStatus() == ProblemStatus::OPTIMAL;
1926 }
1927 
1928 /** returns TRUE iff current LP solution is stable
1929  *
1930  * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
1931  * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
1932  * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
1933  * SCIPlpiIsStable() should return false.
1934  */
1936  SCIP_LPI* lpi /**< LP interface structure */
1937  )
1938 {
1939  assert( lpi != NULL );
1940  assert( lpi->solver != NULL );
1941 
1942  /* For correctness, we need to report "unstable" if Glop was not able to prove optimality because of numerical
1943  * issues. Currently Glop still reports primal/dual feasible if at the end, one status is within the tolerance but not
1944  * the other. */
1945  const ProblemStatus status = lpi->solver->GetProblemStatus();
1946  if ( (status == ProblemStatus::PRIMAL_FEASIBLE || status == ProblemStatus::DUAL_FEASIBLE) &&
1947  ! SCIPlpiIsObjlimExc(lpi) && ! SCIPlpiIsIterlimExc(lpi) && ! SCIPlpiIsTimelimExc(lpi))
1948  {
1949  SCIPdebugMessage("OPTIMAL not reached and no limit: unstable.\n");
1950  return FALSE;
1951  }
1952 
1953  if ( status == ProblemStatus::ABNORMAL || status == ProblemStatus::INVALID_PROBLEM || status == ProblemStatus::IMPRECISE )
1954  return FALSE;
1955 
1956  /* If we have a regular basis and the condition limit is set, we compute (an upper bound on) the condition number of
1957  * the basis; everything above the specified threshold is then counted as instable. */
1958  if ( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
1959  {
1960  SCIP_RETCODE retcode;
1961  SCIP_Real kappa;
1962 
1964  if ( retcode != SCIP_OKAY )
1965  SCIPABORT();
1966  assert( kappa != SCIP_INVALID ); /*lint !e777*/
1967 
1968  if ( kappa > lpi->conditionlimit )
1969  return FALSE;
1970  }
1971 
1972  return TRUE;
1973 }
1974 
1975 /** returns TRUE iff the objective limit was reached */
1977  SCIP_LPI* lpi /**< LP interface structure */
1978  )
1979 {
1980  assert( lpi != NULL );
1981  assert( lpi->solver != NULL );
1982 
1983  return lpi->solver->objective_limit_reached();
1984 }
1985 
1986 /** returns TRUE iff the iteration limit was reached */
1988  SCIP_LPI* lpi /**< LP interface structure */
1989  )
1990 {
1991  assert( lpi != NULL );
1992  assert( lpi->solver != NULL );
1993  assert( lpi->niterations >= (int) lpi->solver->GetNumberOfIterations() );
1994 
1995  int maxiter = (int) lpi->parameters->max_number_of_iterations();
1996  return maxiter >= 0 && lpi->niterations >= maxiter;
1997 }
1998 
1999 /** returns TRUE iff the time limit was reached */
2001  SCIP_LPI* lpi /**< LP interface structure */
2002  )
2003 {
2004  assert( lpi != NULL );
2005  assert( lpi->solver != NULL );
2006 
2007  return lpi->lp_time_limit_was_reached;
2008 }
2009 
2010 /** returns the internal solution status of the solver */
2012  SCIP_LPI* lpi /**< LP interface structure */
2013  )
2014 {
2015  assert( lpi != NULL );
2016  assert( lpi->solver != NULL );
2017 
2018  return static_cast<int>(lpi->solver->GetProblemStatus());
2019 }
2020 
2021 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
2023  SCIP_LPI* lpi, /**< LP interface structure */
2024  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
2025  )
2026 {
2027  assert( lpi != NULL );
2028  assert( lpi->solver != NULL );
2029  assert( success != NULL );
2030 
2031  *success = FALSE;
2032 
2033  return SCIP_OKAY;
2034 }
2035 
2036 /** gets objective value of solution */
2038  SCIP_LPI* lpi, /**< LP interface structure */
2039  SCIP_Real* objval /**< stores the objective value */
2040  )
2041 {
2042  assert( lpi != NULL );
2043  assert( lpi->solver != NULL );
2044  assert( objval != NULL );
2045 
2046  *objval = lpi->solver->GetObjectiveValue();
2047 
2048  return SCIP_OKAY;
2049 }
2050 
2051 /** gets primal and dual solution vectors for feasible LPs
2052  *
2053  * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
2054  * SCIPlpiIsOptimal() returns true.
2055  */
2057  SCIP_LPI* lpi, /**< LP interface structure */
2058  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
2059  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
2060  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
2061  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
2062  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
2063  )
2064 {
2065  assert( lpi != NULL );
2066  assert( lpi->solver != NULL );
2067 
2068  SCIPdebugMessage("SCIPlpiGetSol\n");
2069  if ( objval != NULL )
2070  *objval = lpi->solver->GetObjectiveValue();
2071 
2072  const ColIndex num_cols = lpi->linear_program->num_variables();
2073  for (ColIndex col(0); col < num_cols; ++col)
2074  {
2075  int i = col.value();
2076 
2077  if ( primsol != NULL )
2078  primsol[i] = lpi->scaler->UnscaleVariableValue(col, lpi->solver->GetVariableValue(col));
2079 
2080  if ( redcost != NULL )
2081  redcost[i] = lpi->scaler->UnscaleReducedCost(col, lpi->solver->GetReducedCost(col));
2082  }
2083 
2084  const RowIndex num_rows = lpi->linear_program->num_constraints();
2085  for (RowIndex row(0); row < num_rows; ++row)
2086  {
2087  int j = row.value();
2088 
2089  if ( dualsol != NULL )
2090  dualsol[j] = lpi->scaler->UnscaleDualValue(row, lpi->solver->GetDualValue(row));
2091 
2092  if ( activity != NULL )
2093  activity[j] = lpi->scaler->UnscaleConstraintActivity(row, lpi->solver->GetConstraintActivity(row));
2094  }
2095 
2096  return SCIP_OKAY;
2097 }
2098 
2099 /** gets primal ray for unbounded LPs */
2101  SCIP_LPI* lpi, /**< LP interface structure */
2102  SCIP_Real* ray /**< primal ray */
2103  )
2104 {
2105  assert( lpi != NULL );
2106  assert( lpi->solver != NULL );
2107  assert( ray != NULL );
2108 
2109  SCIPdebugMessage("SCIPlpiGetPrimalRay\n");
2110 
2111  const ColIndex num_cols = lpi->linear_program->num_variables();
2112  const DenseRow& primal_ray = lpi->solver->GetPrimalRay();
2113  for (ColIndex col(0); col < num_cols; ++col)
2114  ray[col.value()] = lpi->scaler->UnscaleVariableValue(col, primal_ray[col]);
2115 
2116  return SCIP_OKAY;
2117 }
2118 
2119 /** gets dual Farkas proof for infeasibility */
2121  SCIP_LPI* lpi, /**< LP interface structure */
2122  SCIP_Real* dualfarkas /**< dual Farkas row multipliers */
2123  )
2124 {
2125  assert( lpi != NULL );
2126  assert( lpi->solver != NULL );
2127  assert( dualfarkas != NULL );
2128 
2129  SCIPdebugMessage("SCIPlpiGetDualfarkas\n");
2130 
2131  const RowIndex num_rows = lpi->linear_program->num_constraints();
2132  const DenseColumn& dual_ray = lpi->solver->GetDualRay();
2133  for (RowIndex row(0); row < num_rows; ++row)
2134  dualfarkas[row.value()] = -lpi->scaler->UnscaleDualValue(row, dual_ray[row]); /* reverse sign */
2135 
2136  return SCIP_OKAY;
2137 }
2138 
2139 /** gets the number of LP iterations of the last solve call */
2141  SCIP_LPI* lpi, /**< LP interface structure */
2142  int* iterations /**< pointer to store the number of iterations of the last solve call */
2143  )
2144 {
2145  assert( lpi != NULL );
2146  assert( lpi->solver != NULL );
2147  assert( iterations != NULL );
2148 
2149  *iterations = (int) lpi->niterations;
2150 
2151  return SCIP_OKAY;
2152 }
2153 
2154 /** gets information about the quality of an LP solution
2155  *
2156  * Such information is usually only available, if also a (maybe not optimal) solution is available.
2157  * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
2158  */
2160  SCIP_LPI* lpi, /**< LP interface structure */
2161  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
2162  SCIP_Real* quality /**< pointer to store quality number */
2163  )
2164 {
2165  assert( lpi != NULL );
2166  assert( lpi->solver != NULL );
2167  assert( quality != NULL );
2168 
2169  SCIPdebugMessage("Requesting solution quality: quality %d\n", qualityindicator);
2170 
2171  switch ( qualityindicator )
2172  {
2174  *quality = lpi->solver->GetBasisFactorization().ComputeInfinityNormConditionNumber();
2175  break;
2176 
2178  *quality = lpi->solver->GetBasisFactorization().ComputeInfinityNormConditionNumberUpperBound();
2179  break;
2180 
2181  default:
2182  SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
2183  return SCIP_INVALIDDATA;
2184  }
2185 
2186  return SCIP_OKAY;
2187 }
2188 
2189 /**@} */
2190 
2191 
2192 
2193 
2194 /*
2195  * LP Basis Methods
2196  */
2197 
2198 /**@name LP Basis Methods */
2199 /**@{ */
2200 
2201 /** convert Glop variable basis status to SCIP status */
2202 static
2204  VariableStatus status, /**< variable status */
2205  Fractional rc /**< reduced cost of variable */
2206  )
2207 {
2208  switch ( status )
2209  {
2210  case VariableStatus::BASIC:
2211  return SCIP_BASESTAT_BASIC;
2212  case VariableStatus::AT_UPPER_BOUND:
2213  return SCIP_BASESTAT_UPPER;
2214  case VariableStatus::AT_LOWER_BOUND:
2215  return SCIP_BASESTAT_LOWER;
2216  case VariableStatus::FREE:
2217  return SCIP_BASESTAT_ZERO;
2218  case VariableStatus::FIXED_VALUE:
2219  return rc > 0.0 ? SCIP_BASESTAT_LOWER : SCIP_BASESTAT_UPPER;
2220  default:
2221  SCIPerrorMessage("invalid Glop basis status.\n");
2222  abort();
2223  }
2224 }
2225 
2226 /** convert Glop constraint basis status to SCIP status */
2227 static
2229  ConstraintStatus status, /**< constraint status */
2230  Fractional dual /**< dual variable value */
2231  )
2232 {
2233  switch ( status )
2234  {
2235  case ConstraintStatus::BASIC:
2236  return SCIP_BASESTAT_BASIC;
2237  case ConstraintStatus::AT_UPPER_BOUND:
2238  return SCIP_BASESTAT_UPPER;
2239  case ConstraintStatus::AT_LOWER_BOUND:
2240  return SCIP_BASESTAT_LOWER;
2241  case ConstraintStatus::FREE:
2242  return SCIP_BASESTAT_ZERO;
2243  case ConstraintStatus::FIXED_VALUE:
2244  return dual > 0.0 ? SCIP_BASESTAT_LOWER : SCIP_BASESTAT_UPPER;
2245  default:
2246  SCIPerrorMessage("invalid Glop basis status.\n");
2247  abort();
2248  }
2249 }
2250 
2251 /** Convert SCIP variable status to Glop status */
2252 static
2254  int status /**< SCIP variable status */
2255  )
2256 {
2257  switch ( status )
2258  {
2259  case SCIP_BASESTAT_BASIC:
2260  return VariableStatus::BASIC;
2261  case SCIP_BASESTAT_UPPER:
2262  return VariableStatus::AT_UPPER_BOUND;
2263  case SCIP_BASESTAT_LOWER:
2264  return VariableStatus::AT_LOWER_BOUND;
2265  case SCIP_BASESTAT_ZERO:
2266  return VariableStatus::FREE;
2267  default:
2268  SCIPerrorMessage("invalid SCIP basis status.\n");
2269  abort();
2270  }
2271 }
2272 
2273 /** Convert a SCIP constraint status to its corresponding Glop slack VariableStatus.
2274  *
2275  * Note that we swap the upper/lower bounds.
2276  */
2277 static
2279  int status /**< SCIP constraint status */
2280  )
2281 {
2282  switch ( status )
2283  {
2284  case SCIP_BASESTAT_BASIC:
2285  return VariableStatus::BASIC;
2286  case SCIP_BASESTAT_UPPER:
2287  return VariableStatus::AT_LOWER_BOUND;
2288  case SCIP_BASESTAT_LOWER:
2289  return VariableStatus::AT_UPPER_BOUND;
2290  case SCIP_BASESTAT_ZERO:
2291  return VariableStatus::FREE;
2292  default:
2293  SCIPerrorMessage("invalid SCIP basis status.\n");
2294  abort();
2295  }
2296 }
2297 
2298 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
2300  SCIP_LPI* lpi, /**< LP interface structure */
2301  int* cstat, /**< array to store column basis status, or NULL */
2302  int* rstat /**< array to store row basis status, or NULL */
2303  )
2304 {
2305  SCIPdebugMessage("SCIPlpiGetBase\n");
2306 
2307  assert( lpi->solver->GetProblemStatus() == ProblemStatus::OPTIMAL );
2308 
2309  if ( cstat != NULL )
2310  {
2311  const ColIndex num_cols = lpi->linear_program->num_variables();
2312  for (ColIndex col(0); col < num_cols; ++col)
2313  {
2314  int i = col.value();
2315  cstat[i] = (int) ConvertGlopVariableStatus(lpi->solver->GetVariableStatus(col), lpi->solver->GetReducedCost(col));
2316  }
2317  }
2318 
2319  if ( rstat != NULL )
2320  {
2321  const RowIndex num_rows = lpi->linear_program->num_constraints();
2322  for (RowIndex row(0); row < num_rows; ++row)
2323  {
2324  int i = row.value();
2325  rstat[i] = (int) ConvertGlopConstraintStatus(lpi->solver->GetConstraintStatus(row), lpi->solver->GetDualValue(row));
2326  }
2327  }
2328 
2329  return SCIP_OKAY;
2330 }
2331 
2332 /** sets current basis status for columns and rows */
2334  SCIP_LPI* lpi, /**< LP interface structure */
2335  const int* cstat, /**< array with column basis status */
2336  const int* rstat /**< array with row basis status */
2337  )
2338 {
2339  assert( lpi != NULL );
2340  assert( lpi->linear_program != NULL );
2341  assert( lpi->solver != NULL );
2342 
2343  const ColIndex num_cols = lpi->linear_program->num_variables();
2344  const RowIndex num_rows = lpi->linear_program->num_constraints();
2345 
2346  assert( cstat != NULL || num_cols == 0 );
2347  assert( rstat != NULL || num_rows == 0 );
2348 
2349  SCIPdebugMessage("SCIPlpiSetBase\n");
2350 
2351  BasisState state;
2352  state.statuses.reserve(ColIndex(num_cols.value() + num_rows.value()));
2353 
2354  for (ColIndex col(0); col < num_cols; ++col)
2355  state.statuses[col] = ConvertSCIPVariableStatus(cstat[col.value()]);
2356 
2357  for (RowIndex row(0); row < num_rows; ++row)
2358  state.statuses[num_cols + RowToColIndex(row)] = ConvertSCIPConstraintStatusToSlackStatus(cstat[row.value()]);
2359 
2360  lpi->solver->LoadStateForNextSolve(state);
2361 
2362  return SCIP_OKAY;
2363 }
2364 
2365 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
2367  SCIP_LPI* lpi, /**< LP interface structure */
2368  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
2369  )
2370 {
2371  assert( lpi != NULL );
2372  assert( lpi->linear_program != NULL );
2373  assert( lpi->solver != NULL );
2374  assert( bind != NULL );
2375 
2376  SCIPdebugMessage("SCIPlpiGetBasisInd\n");
2377 
2378  /* the order is important! */
2379  const ColIndex num_cols = lpi->linear_program->num_variables();
2380  const RowIndex num_rows = lpi->linear_program->num_constraints();
2381  for (RowIndex row(0); row < num_rows; ++row)
2382  {
2383  const ColIndex col = lpi->solver->GetBasis(row);
2384  if (col < num_cols)
2385  bind[row.value()] = col.value();
2386  else
2387  {
2388  assert( col < num_cols.value() + num_rows.value() );
2389  bind[row.value()] = -1 - (col - num_cols).value();
2390  }
2391  }
2392 
2393  return SCIP_OKAY;
2394 }
2395 
2396 /** get row of inverse basis matrix B^-1
2397  *
2398  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2399  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2400  * see also the explanation in lpi.h.
2401  */
2403  SCIP_LPI* lpi, /**< LP interface structure */
2404  int r, /**< row number */
2405  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
2406  int* inds, /**< array to store the non-zero indices, or NULL */
2407  int* ninds /**< pointer to store the number of non-zero indices, or NULL
2408  * (-1: if we do not store sparsity information) */
2409  )
2410 {
2411  assert( lpi != NULL );
2412  assert( lpi->linear_program != NULL );
2413  assert( lpi->solver != NULL );
2414  assert( lpi->scaler != NULL );
2415  assert( coef != NULL );
2416 
2417  lpi->solver->GetBasisFactorization().LeftSolveForUnitRow(ColIndex(r), lpi->tmp_row);
2418  lpi->scaler->UnscaleUnitRowLeftSolve(lpi->solver->GetBasis(RowIndex(r)), lpi->tmp_row);
2419 
2420  const ColIndex size = lpi->tmp_row->values.size();
2421  assert( size.value() == lpi->linear_program->num_constraints() );
2422 
2423  /* if we want a sparse vector */
2424  if ( ninds != NULL && inds != NULL )
2425  {
2426  *ninds = 0;
2427  /* Vectors in Glop might be stored in dense or sparse format depending on the values. If non_zeros are given, we
2428  * can directly loop over the non_zeros, otherwise we have to collect the nonzeros. */
2429  if ( ! lpi->tmp_row->non_zeros.empty() )
2430  {
2431  ScatteredRowIterator end = lpi->tmp_row->end();
2432  for (ScatteredRowIterator iter = lpi->tmp_row->begin(); iter != end; ++iter)
2433  {
2434  int idx = (*iter).column().value();
2435  assert( 0 <= idx && idx < lpi->linear_program->num_constraints() );
2436  coef[idx] = (*iter).coefficient();
2437  inds[(*ninds)++] = idx;
2438  }
2439  }
2440  else
2441  {
2442  /* use dense access to tmp_row */
2443  const Fractional eps = lpi->parameters->primal_feasibility_tolerance();
2444  for (ColIndex col(0); col < size; ++col)
2445  {
2446  SCIP_Real val = (*lpi->tmp_row)[col];
2447  if ( fabs(val) >= eps )
2448  {
2449  coef[col.value()] = val;
2450  inds[(*ninds)++] = col.value();
2451  }
2452  }
2453  }
2454  return SCIP_OKAY;
2455  }
2456 
2457  /* dense version */
2458  for (ColIndex col(0); col < size; ++col)
2459  coef[col.value()] = (*lpi->tmp_row)[col];
2460 
2461  if ( ninds != NULL )
2462  *ninds = -1;
2463 
2464  return SCIP_OKAY;
2465 }
2466 
2467 /** get column of inverse basis matrix B^-1
2468  *
2469  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2470  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2471  * see also the explanation in lpi.h.
2472  */
2474  SCIP_LPI* lpi, /**< LP interface structure */
2475  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
2476  * you have to call SCIPlpiGetBasisInd() to get the array which links the
2477  * B^-1 column numbers to the row and column numbers of the LP!
2478  * c must be between 0 and nrows-1, since the basis has the size
2479  * nrows * nrows */
2480  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
2481  int* inds, /**< array to store the non-zero indices, or NULL */
2482  int* ninds /**< pointer to store the number of non-zero indices, or NULL
2483  * (-1: if we do not store sparsity information) */
2484  )
2485 {
2486  assert( lpi != NULL );
2487  assert( lpi->linear_program != NULL );
2488  assert( lpi->solver != NULL );
2489  assert( lpi->scaler != NULL );
2490  assert( coef != NULL );
2491 
2492  /* we need to loop through the rows to extract the values for column c */
2493  const ColIndex col(c);
2494  const RowIndex num_rows = lpi->linear_program->num_constraints();
2495 
2496  /* if we want a sparse vector */
2497  if ( ninds != NULL && inds != NULL )
2498  {
2499  const Fractional eps = lpi->parameters->primal_feasibility_tolerance();
2500 
2501  *ninds = 0;
2502  for (int row = 0; row < num_rows; ++row)
2503  {
2504  lpi->solver->GetBasisFactorization().LeftSolveForUnitRow(ColIndex(row), lpi->tmp_row);
2505  lpi->scaler->UnscaleUnitRowLeftSolve(lpi->solver->GetBasis(RowIndex(row)), lpi->tmp_row);
2506 
2507  SCIP_Real val = (*lpi->tmp_row)[col];
2508  if ( fabs(val) >= eps )
2509  {
2510  coef[row] = val;
2511  inds[(*ninds)++] = row;
2512  }
2513  }
2514  return SCIP_OKAY;
2515  }
2516 
2517  /* dense version */
2518  for (int row = 0; row < num_rows; ++row)
2519  {
2520  lpi->solver->GetBasisFactorization().LeftSolveForUnitRow(ColIndex(row), lpi->tmp_row);
2521  lpi->scaler->UnscaleUnitRowLeftSolve(lpi->solver->GetBasis(RowIndex(row)), lpi->tmp_row);
2522  coef[row] = (*lpi->tmp_row)[col];
2523  }
2524 
2525  if ( ninds != NULL )
2526  *ninds = -1;
2527 
2528  return SCIP_OKAY;
2529 }
2530 
2531 /** get row of inverse basis matrix times constraint matrix B^-1 * A
2532  *
2533  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2534  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2535  * see also the explanation in lpi.h.
2536  */
2538  SCIP_LPI* lpi, /**< LP interface structure */
2539  int r, /**< row number */
2540  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
2541  SCIP_Real* coef, /**< vector to return coefficients of the row */
2542  int* inds, /**< array to store the non-zero indices, or NULL */
2543  int* ninds /**< pointer to store the number of non-zero indices, or NULL
2544  * (-1: if we do not store sparsity information) */
2545  )
2546 {
2547  assert( lpi != NULL );
2548  assert( lpi->linear_program != NULL );
2549  assert( lpi->solver != NULL );
2550  assert( lpi->scaler != NULL );
2551  assert( coef != NULL );
2552 
2553  /* get row of basis inverse, loop through columns and muliply with matrix */
2554  lpi->solver->GetBasisFactorization().LeftSolveForUnitRow(ColIndex(r), lpi->tmp_row);
2555  lpi->scaler->UnscaleUnitRowLeftSolve(lpi->solver->GetBasis(RowIndex(r)), lpi->tmp_row);
2556 
2557  const ColIndex num_cols = lpi->linear_program->num_variables();
2558 
2559  /* if we want a sparse vector */
2560  if ( ninds != NULL && inds != NULL )
2561  {
2562  const Fractional eps = lpi->parameters->primal_feasibility_tolerance();
2563 
2564  *ninds = 0;
2565  for (ColIndex col(0); col < num_cols; ++col)
2566  {
2567  SCIP_Real val = operations_research::glop::ScalarProduct(lpi->tmp_row->values, lpi->linear_program->GetSparseColumn(col));
2568  if ( fabs(val) >= eps )
2569  {
2570  coef[col.value()] = val;
2571  inds[(*ninds)++] = col.value();
2572  }
2573  }
2574  return SCIP_OKAY;
2575  }
2576 
2577  /* dense version */
2578  for (ColIndex col(0); col < num_cols; ++col)
2579  coef[col.value()] = operations_research::glop::ScalarProduct(lpi->tmp_row->values, lpi->linear_program->GetSparseColumn(col));
2580 
2581  if ( ninds != NULL )
2582  *ninds = -1;
2583 
2584  return SCIP_OKAY;
2585 }
2586 
2587 /** get column of inverse basis matrix times constraint matrix B^-1 * A
2588  *
2589  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2590  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2591  * see also the explanation in lpi.h.
2592  */
2594  SCIP_LPI* lpi, /**< LP interface structure */
2595  int c, /**< column number */
2596  SCIP_Real* coef, /**< vector to return coefficients of the column */
2597  int* inds, /**< array to store the non-zero indices, or NULL */
2598  int* ninds /**< pointer to store the number of non-zero indices, or NULL
2599  * (-1: if we do not store sparsity information) */
2600  )
2601 {
2602  assert( lpi != NULL );
2603  assert( lpi->linear_program != NULL );
2604  assert( lpi->solver != NULL );
2605  assert( lpi->scaler != NULL );
2606  assert( coef != NULL );
2607 
2608  lpi->solver->GetBasisFactorization().RightSolveForProblemColumn(ColIndex(c), lpi->tmp_column);
2609  lpi->scaler->UnscaleColumnRightSolve(lpi->solver->GetBasisVector(), ColIndex(c), lpi->tmp_column);
2610 
2611  const RowIndex num_rows = lpi->tmp_column->values.size();
2612 
2613  /* if we want a sparse vector */
2614  if ( ninds != NULL && inds != NULL )
2615  {
2616  *ninds = 0;
2617  /* Vectors in Glop might be stored in dense or sparse format depending on the values. If non_zeros are given, we
2618  * can directly loop over the non_zeros, otherwise we have to collect the nonzeros. */
2619  if ( ! lpi->tmp_column->non_zeros.empty() )
2620  {
2621  ScatteredColumnIterator end = lpi->tmp_column->end();
2622  for (ScatteredColumnIterator iter = lpi->tmp_column->begin(); iter != end; ++iter)
2623  {
2624  int idx = (*iter).row().value();
2625  assert( 0 <= idx && idx < num_rows );
2626  coef[idx] = (*iter).coefficient();
2627  inds[(*ninds)++] = idx;
2628  }
2629  }
2630  else
2631  {
2632  /* use dense access to tmp_column */
2633  const Fractional eps = lpi->parameters->primal_feasibility_tolerance();
2634  for (RowIndex row(0); row < num_rows; ++row)
2635  {
2636  SCIP_Real val = (*lpi->tmp_column)[row];
2637  if ( fabs(val) > eps )
2638  {
2639  coef[row.value()] = val;
2640  inds[(*ninds)++] = row.value();
2641  }
2642  }
2643  }
2644  return SCIP_OKAY;
2645  }
2646 
2647  /* dense version */
2648  for (RowIndex row(0); row < num_rows; ++row)
2649  coef[row.value()] = (*lpi->tmp_column)[row];
2650 
2651  if ( ninds != NULL )
2652  *ninds = -1;
2653 
2654  return SCIP_OKAY;
2655 }
2656 
2657 /**@} */
2658 
2659 
2660 
2661 
2662 /*
2663  * LP State Methods
2664  */
2665 
2666 /**@name LP State Methods */
2667 /**@{ */
2668 
2669 /* SCIP_LPiState stores basis information and is implemented by the glop BasisState class.
2670  * However, because in type_lpi.h there is
2671  * typedef struct SCIP_LPiState SCIP_LPISTATE;
2672  * We cannot just use a typedef here and SCIP_LPiState needs to be a struct.
2673  */
2674 struct SCIP_LPiState : BasisState {};
2675 
2676 /** stores LPi state (like basis information) into lpistate object */
2678  SCIP_LPI* lpi, /**< LP interface structure */
2679  BMS_BLKMEM* blkmem, /**< block memory */
2680  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
2681  )
2682 {
2683  assert( lpi != NULL );
2684  assert( lpi->solver != NULL );
2685  assert( lpistate != NULL );
2686 
2687  *lpistate = static_cast<SCIP_LPISTATE*>(new BasisState(lpi->solver->GetState()));
2688 
2689  return SCIP_OKAY;
2690 }
2691 
2692 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
2693  * columns and rows since the state was stored with SCIPlpiGetState()
2694  */
2696  SCIP_LPI* lpi, /**< LP interface structure */
2697  BMS_BLKMEM* blkmem, /**< block memory */
2698  const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
2699  )
2700 {
2701  assert( lpi != NULL );
2702  assert( lpi->solver != NULL );
2703  assert( lpistate != NULL );
2704 
2705  lpi->solver->LoadStateForNextSolve(*lpistate);
2706 
2707  return SCIP_OKAY;
2708 }
2709 
2710 /** clears current LPi state (like basis information) of the solver */
2712  SCIP_LPI* lpi /**< LP interface structure */
2713  )
2714 {
2715  assert( lpi != NULL );
2716  assert( lpi->solver != NULL );
2717 
2718  lpi->solver->ClearStateForNextSolve();
2719 
2720  return SCIP_OKAY;
2721 }
2722 
2723 /** frees LPi state information */
2725  SCIP_LPI* lpi, /**< LP interface structure */
2726  BMS_BLKMEM* blkmem, /**< block memory */
2727  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
2728  )
2729 {
2730  assert( lpi != NULL );
2731  assert( lpi->solver != NULL );
2732  assert( lpistate != NULL );
2733 
2734  delete *lpistate;
2735  *lpistate = NULL;
2736 
2737  return SCIP_OKAY;
2738 }
2739 
2740 /** checks, whether the given LP state contains simplex basis information */
2742  SCIP_LPI* lpi, /**< LP interface structure */
2743  SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
2744  )
2745 {
2746  assert( lpi != NULL );
2747  assert( lpi->solver != NULL );
2748 
2749  return lpistate != NULL;
2750 }
2751 
2752 /** reads LP state (like basis information from a file */
2754  SCIP_LPI* lpi, /**< LP interface structure */
2755  const char* fname /**< file name */
2756  )
2757 {
2758  assert( lpi != NULL );
2759  assert( lpi->solver != NULL );
2760 
2761  SCIPerrorMessage("SCIPlpiReadState - not implemented.\n");
2762 
2763  return SCIP_NOTIMPLEMENTED;
2764 }
2765 
2766 /** writes LPi state (i.e. basis information) to a file */
2768  SCIP_LPI* lpi, /**< LP interface structure */
2769  const char* fname /**< file name */
2770  )
2771 {
2772  assert( lpi != NULL );
2773  assert( lpi->solver != NULL );
2774 
2775  SCIPerrorMessage("SCIPlpiWriteState - not implemented.\n");
2776 
2777  return SCIP_NOTIMPLEMENTED;
2778 }
2779 
2780 /**@} */
2781 
2782 
2783 
2784 
2785 /*
2786  * LP Pricing Norms Methods
2787  */
2788 
2789 /**@name LP Pricing Norms Methods */
2790 /**@{ */
2791 
2792 /* SCIP_LPiNorms stores norm information so they are not recomputed from one state to the next. */
2793 /* @todo Implement this. */
2794 struct SCIP_LPiNorms {};
2795 
2796 /** stores LPi pricing norms information
2797  *
2798  * @todo store primal norms as well?
2799  */
2801  SCIP_LPI* lpi, /**< LP interface structure */
2802  BMS_BLKMEM* blkmem, /**< block memory */
2803  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
2804  )
2805 {
2806  assert( lpi != NULL );
2807  assert( blkmem != NULL );
2808  assert( lpi->solver != NULL );
2809  assert( lpinorms != NULL );
2810 
2811  return SCIP_OKAY;
2812 }
2813 
2814 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
2815  * columns and rows since the state was stored with SCIPlpiGetNorms()
2816  */
2818  SCIP_LPI* lpi, /**< LP interface structure */
2819  BMS_BLKMEM* blkmem, /**< block memory */
2820  const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
2821  )
2822 {
2823  assert( lpi != NULL );
2824  assert( blkmem != NULL );
2825  assert( lpi->solver != NULL );
2826  assert( lpinorms != NULL );
2827 
2828  return SCIP_OKAY;
2829 }
2830 
2831 /** frees pricing norms information */
2833  SCIP_LPI* lpi, /**< LP interface structure */
2834  BMS_BLKMEM* blkmem, /**< block memory */
2835  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
2836  )
2837 {
2838  assert( lpi != NULL );
2839  assert( blkmem != NULL );
2840  assert( lpi->solver != NULL );
2841  assert( lpinorms != NULL );
2842 
2843  return SCIP_OKAY;
2844 }
2845 
2846 /**@} */
2847 
2848 
2849 
2850 
2851 /*
2852  * Parameter Methods
2853  */
2854 
2855 /**@name Parameter Methods */
2856 /**@{ */
2857 
2858 /** gets integer parameter of LP */
2860  SCIP_LPI* lpi, /**< LP interface structure */
2861  SCIP_LPPARAM type, /**< parameter number */
2862  int* ival /**< buffer to store the parameter value */
2863  )
2864 {
2865  assert( lpi != NULL );
2866  assert( lpi->parameters != NULL );
2867 
2868  /* Not (yet) supported by Glop: SCIP_LPPAR_FASTMIP, SCIP_LPPAR_POLISHING, SCIP_LPPAR_REFACTOR */
2869  switch ( type )
2870  {
2872  *ival = (int) lpi->from_scratch;
2873  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_FROMSCRATCH = %d.\n", *ival);
2874  break;
2875  case SCIP_LPPAR_LPINFO:
2876  *ival = (int) lpi->lp_info;
2877  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_LPINFO = %d.\n", *ival);
2878  break;
2879  case SCIP_LPPAR_LPITLIM:
2880  *ival = (int) lpi->parameters->max_number_of_iterations();
2881  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_LPITLIM = %d.\n", *ival);
2882  break;
2883  case SCIP_LPPAR_PRESOLVING:
2884  *ival = lpi->parameters->use_preprocessing();
2885  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_PRESOLVING = %d.\n", *ival);
2886  break;
2887  case SCIP_LPPAR_PRICING:
2888  *ival = lpi->pricing;
2889  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_PRICING = %d.\n", *ival);
2890  break;
2891 #ifndef NOSCALING
2892  case SCIP_LPPAR_SCALING:
2893  *ival = lpi->parameters->use_scaling();
2894  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_SCALING = %d.\n", *ival);
2895  break;
2896 #endif
2897  case SCIP_LPPAR_THREADS:
2898  *ival = lpi->numthreads;
2899  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_THREADS = %d.\n", *ival);
2900  break;
2901  case SCIP_LPPAR_TIMING:
2902  *ival = lpi->timing;
2903  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_TIMING = %d.\n", *ival);
2904  break;
2905  case SCIP_LPPAR_RANDOMSEED:
2906  *ival = (int) lpi->parameters->random_seed();
2907  SCIPdebugMessage("SCIPlpiGetIntpar: SCIP_LPPAR_RANDOMSEED = %d.\n", *ival);
2908  break;
2909  default:
2910  return SCIP_PARAMETERUNKNOWN;
2911  }
2912 
2913  return SCIP_OKAY;
2914 }
2915 
2916 /** sets integer parameter of LP */
2918  SCIP_LPI* lpi, /**< LP interface structure */
2919  SCIP_LPPARAM type, /**< parameter number */
2920  int ival /**< parameter value */
2921  )
2922 {
2923  assert( lpi != NULL );
2924  assert( lpi->parameters != NULL );
2925 
2926  switch ( type )
2927  {
2929  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_FROMSCRATCH -> %d.\n", ival);
2930  lpi->from_scratch = (bool) ival;
2931  break;
2932  case SCIP_LPPAR_LPINFO:
2933  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_LPINFO -> %d.\n", ival);
2934  if ( ival == 0 )
2935  {
2936  (void) google::SetVLOGLevel("*", google::GLOG_INFO);
2937  lpi->lp_info = false;
2938  }
2939  else
2940  {
2941  (void) google::SetVLOGLevel("*", google::GLOG_ERROR);
2942  lpi->lp_info = true;
2943  }
2944  break;
2945  case SCIP_LPPAR_LPITLIM:
2946  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_LPITLIM -> %d.\n", ival);
2947  lpi->parameters->set_max_number_of_iterations(ival);
2948  break;
2949  case SCIP_LPPAR_PRESOLVING:
2950  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_PRESOLVING -> %d.\n", ival);
2951  lpi->parameters->set_use_preprocessing(ival);
2952  break;
2953  case SCIP_LPPAR_PRICING:
2954  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_PRICING -> %d.\n", ival);
2955  lpi->pricing = (SCIP_Pricing)ival;
2956  switch ( lpi->pricing )
2957  {
2959  case SCIP_PRICING_AUTO:
2960  case SCIP_PRICING_PARTIAL:
2961  case SCIP_PRICING_STEEP:
2963  lpi->parameters->set_feasibility_rule(operations_research::glop::GlopParameters_PricingRule_STEEPEST_EDGE);
2964  break;
2965  case SCIP_PRICING_FULL:
2966  /* Dantzig does not really fit, but use it anyway */
2967  lpi->parameters->set_feasibility_rule(operations_research::glop::GlopParameters_PricingRule_DANTZIG);
2968  break;
2969  case SCIP_PRICING_DEVEX:
2970  lpi->parameters->set_feasibility_rule(operations_research::glop::GlopParameters_PricingRule_DEVEX);
2971  break;
2972  default:
2973  return SCIP_PARAMETERUNKNOWN;
2974  }
2975  break;
2976 #ifndef NOSCALING
2977  case SCIP_LPPAR_SCALING:
2978  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_SCALING -> %d.\n", ival);
2979  lpi->parameters->set_use_scaling(ival);
2980  break;
2981 #endif
2982  case SCIP_LPPAR_THREADS:
2983  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_THREADS -> %d.\n", ival);
2984  assert( ival >= 0 );
2985  lpi->numthreads = ival;
2986  if ( ival == 0 )
2987  lpi->parameters->set_num_omp_threads(1);
2988  else
2989  lpi->parameters->set_num_omp_threads(ival);
2990  break;
2991  case SCIP_LPPAR_TIMING:
2992  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_TIMING -> %d.\n", ival);
2993  assert( 0 <= ival && ival <= 2 );
2994  lpi->timing = ival;
2995  if ( ival == 1 )
2996  absl::SetFlag(&FLAGS_time_limit_use_usertime, true);
2997  else
2998  absl::SetFlag(&FLAGS_time_limit_use_usertime, false);
2999  break;
3000  case SCIP_LPPAR_RANDOMSEED:
3001  SCIPdebugMessage("SCIPlpiSetIntpar: SCIP_LPPAR_RANDOMSEED -> %d.\n", ival);
3002  assert( ival >= 0 );
3003  lpi->parameters->set_random_seed(ival);
3004  break;
3005  default:
3006  return SCIP_PARAMETERUNKNOWN;
3007  }
3008 
3009  return SCIP_OKAY;
3010 }
3011 
3012 /** gets floating point parameter of LP */
3014  SCIP_LPI* lpi, /**< LP interface structure */
3015  SCIP_LPPARAM type, /**< parameter number */
3016  SCIP_Real* dval /**< buffer to store the parameter value */
3017  )
3018 {
3019  assert( lpi != NULL );
3020  assert( lpi->parameters != NULL );
3021 
3022  /* Not (yet) supported by Glop: SCIP_LPPAR_ROWREPSWITCH, SCIP_LPPAR_BARRIERCONVTOL */
3023  switch ( type )
3024  {
3025  case SCIP_LPPAR_FEASTOL:
3026  *dval = lpi->parameters->primal_feasibility_tolerance();
3027  SCIPdebugMessage("SCIPlpiGetRealpar: SCIP_LPPAR_FEASTOL = %g.\n", *dval);
3028  break;
3030  *dval = lpi->parameters->dual_feasibility_tolerance();
3031  SCIPdebugMessage("SCIPlpiGetRealpar: SCIP_LPPAR_DUALFEASTOL = %g.\n", *dval);
3032  break;
3033  case SCIP_LPPAR_OBJLIM:
3034  if (lpi->linear_program->IsMaximizationProblem())
3035  *dval = lpi->parameters->objective_lower_limit();
3036  else
3037  *dval = lpi->parameters->objective_upper_limit();
3038  SCIPdebugMessage("SCIPlpiGetRealpar: SCIP_LPPAR_OBJLIM = %f.\n", *dval);
3039  break;
3040  case SCIP_LPPAR_LPTILIM:
3041  if ( absl::GetFlag(FLAGS_time_limit_use_usertime) )
3042  *dval = lpi->parameters->max_time_in_seconds();
3043  else
3044  *dval = lpi->parameters->max_deterministic_time();
3045  SCIPdebugMessage("SCIPlpiGetRealpar: SCIP_LPPAR_LPTILIM = %f.\n", *dval);
3046  break;
3048  *dval = lpi->conditionlimit;
3049  break;
3050 #ifdef SCIP_DISABLED_CODE
3051  /* currently do not apply Markowitz parameter, since the default value does not seem suitable for Glop */
3052  case SCIP_LPPAR_MARKOWITZ:
3053  *dval = lpi->parameters->markowitz_singularity_threshold();
3054  SCIPdebugMessage("SCIPlpiGetRealpar: SCIP_LPPAR_MARKOWITZ = %f.\n", *dval);
3055  break;
3056 #endif
3057  default:
3058  return SCIP_PARAMETERUNKNOWN;
3059  }
3060 
3061  return SCIP_OKAY;
3062 }
3063 
3064 /** sets floating point parameter of LP */
3066  SCIP_LPI* lpi, /**< LP interface structure */
3067  SCIP_LPPARAM type, /**< parameter number */
3068  SCIP_Real dval /**< parameter value */
3069  )
3070 {
3071  assert( lpi != NULL );
3072  assert( lpi->parameters != NULL );
3073 
3074  switch( type )
3075  {
3076  case SCIP_LPPAR_FEASTOL:
3077  SCIPdebugMessage("SCIPlpiSetRealpar: SCIP_LPPAR_FEASTOL -> %g.\n", dval);
3078  lpi->parameters->set_primal_feasibility_tolerance(dval);
3079  break;
3081  SCIPdebugMessage("SCIPlpiSetRealpar: SCIP_LPPAR_DUALFEASTOL -> %g.\n", dval);
3082  lpi->parameters->set_dual_feasibility_tolerance(dval);
3083  break;
3084  case SCIP_LPPAR_OBJLIM:
3085  SCIPdebugMessage("SCIPlpiSetRealpar: SCIP_LPPAR_OBJLIM -> %f.\n", dval);
3086  if (lpi->linear_program->IsMaximizationProblem())
3087  lpi->parameters->set_objective_lower_limit(dval);
3088  else
3089  lpi->parameters->set_objective_upper_limit(dval);
3090  break;
3091  case SCIP_LPPAR_LPTILIM:
3092  SCIPdebugMessage("SCIPlpiSetRealpar: SCIP_LPPAR_LPTILIM -> %f.\n", dval);
3093  if ( absl::GetFlag(FLAGS_time_limit_use_usertime) )
3094  lpi->parameters->set_max_time_in_seconds(dval);
3095  else
3096  lpi->parameters->set_max_deterministic_time(dval);
3097  break;
3099  lpi->conditionlimit = dval;
3100  lpi->checkcondition = (dval >= 0.0);
3101  break;
3102 #ifdef SCIP_DISABLED_CODE
3103  /* currently do not apply Markowitz parameter, since the default value does not seem suitable for Glop */
3104  case SCIP_LPPAR_MARKOWITZ:
3105  SCIPdebugMessage("SCIPlpiSetRealpar: SCIP_LPPAR_MARKOWITZ -> %f.\n", dval);
3106  lpi->parameters->set_markowitz_singularity_threshold(dval);
3107  break;
3108 #endif
3109  default:
3110  return SCIP_PARAMETERUNKNOWN;
3111  }
3112 
3113  return SCIP_OKAY;
3114 }
3115 
3116 /** interrupts the currently ongoing lp solve or disables the interrupt */
3118  SCIP_LPI* lpi, /**< LP interface structure */
3119  SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
3120  )
3121 {
3122  /*lint --e{715}*/
3123  assert(lpi != NULL);
3124 
3125  return SCIP_OKAY;
3126 }
3127 
3128 /**@} */
3129 
3130 
3131 
3132 
3133 /*
3134  * Numerical Methods
3135  */
3136 
3137 /**@name Numerical Methods */
3138 /**@{ */
3139 
3140 /** returns value treated as infinity in the LP solver */
3142  SCIP_LPI* lpi /**< LP interface structure */
3143  )
3144 {
3145  assert( lpi != NULL );
3147 }
3148 
3149 /** checks if given value is treated as infinity in the LP solver */
3151  SCIP_LPI* lpi, /**< LP interface structure */
3152  SCIP_Real val /**< value to be checked for infinity */
3153  )
3154 {
3155  assert( lpi != NULL );
3156 
3158 }
3159 
3160 /**@} */
3161 
3162 
3163 
3164 
3165 /*
3166  * File Interface Methods
3167  */
3168 
3169 /**@name File Interface Methods */
3170 /**@{ */
3171 
3172 /** reads LP from a file */
3174  SCIP_LPI* lpi, /**< LP interface structure */
3175  const char* fname /**< file name */
3176  )
3177 {
3178  assert( lpi != NULL );
3179  assert( lpi->linear_program != NULL );
3180  assert( fname != NULL );
3181 
3182  const std::string filespec(fname);
3183  MPModelProto proto;
3184  if ( ! ReadFileToProto(filespec, &proto) )
3185  {
3186  SCIPerrorMessage("Could not read <%s>\n", fname);
3187  return SCIP_READERROR;
3188  }
3189  lpi->linear_program->Clear();
3190  MPModelProtoToLinearProgram(proto, lpi->linear_program);
3191 
3192  return SCIP_OKAY;
3193 }
3194 
3195 /** writes LP to a file */
3197  SCIP_LPI* lpi, /**< LP interface structure */
3198  const char* fname /**< file name */
3199  )
3200 {
3201  assert( lpi != NULL );
3202  assert( lpi->linear_program != NULL );
3203  assert( fname != NULL );
3204 
3205  MPModelProto proto;
3206  LinearProgramToMPModelProto(*lpi->linear_program, &proto);
3207  const std::string filespec(fname);
3208  if ( ! WriteProtoToFile(filespec, proto, operations_research::ProtoWriteFormat::kProtoText, true) )
3209  {
3210  SCIPerrorMessage("Could not write <%s>\n", fname);
3211  return SCIP_READERROR;
3212  }
3213 
3214  return SCIP_OKAY;
3215 }
3216 
3217 /**@} */
bool lp_info
Definition: lpi_glop.cpp:100
static SCIP_RETCODE SolveInternal(SCIP_LPI *lpi, bool recursive, std::unique_ptr< TimeLimit > &time_limit)
Definition: lpi_glop.cpp:1362
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_glop.cpp:2473
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_glop.cpp:921
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:95
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_glop.cpp:274
SCIP_Real conditionlimit
Definition: lpi_cpx.c:164
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
Definition: lpi_glop.cpp:2695
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_glop.cpp:3150
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1881
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_glop.cpp:2817
int nrows
Definition: lpi_none.c:43
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_glop.cpp:2120
SCIP_PRICING pricing
Definition: lpi_clp.cpp:103
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1472
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_glop.cpp:2056
static VariableStatus ConvertSCIPConstraintStatusToSlackStatus(int status)
Definition: lpi_glop.cpp:2278
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:87
#define infinity
Definition: gastrans.c:71
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_glop.cpp:2917
enum SCIP_ObjSen SCIP_OBJSEN
Definition: type_lpi.h:36
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1420
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:162
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_glop.cpp:2299
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_glop.cpp:684
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_glop.cpp:2859
operations_research::glop::LpScalingHelper * scaler
Definition: lpi_glop.cpp:93
interface methods for specific LP solvers
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_glop.cpp:2140
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_glop.cpp:972
#define FALSE
Definition: def.h:87
operations_research::glop::LinearProgram * linear_program
Definition: lpi_glop.cpp:89
static SCIP_BASESTAT ConvertGlopConstraintStatus(ConstraintStatus status, Fractional dual)
Definition: lpi_glop.cpp:2228
operations_research::glop::LinearProgram * scaled_lp
Definition: lpi_glop.cpp:90
static SCIP_BASESTAT ConvertGlopVariableStatus(VariableStatus status, Fractional rc)
Definition: lpi_glop.cpp:2203
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_Bool checkcondition
Definition: lpi_cpx.c:165
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_glop.cpp:3065
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1803
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_glop.cpp:2800
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:64
static bool IsDualBoundValid(ProblemStatus status)
Definition: lpi_glop.cpp:1501
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_glop.cpp:938
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:116
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_glop.cpp:2753
static bool checkUnscaledPrimalFeasibility(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1308
int timing
Definition: lpi_glop.cpp:106
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_glop.cpp:208
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_glop.cpp:1196
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:629
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_glop.cpp:2159
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_glop.cpp:843
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_glop.cpp:955
bool lp_modified_since_last_solve
Definition: lpi_glop.cpp:96
#define BMSfreeMemory(ptr)
Definition: memory.h:138
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_glop.cpp:174
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:77
operations_research::glop::RevisedSimplex * solver
Definition: lpi_glop.cpp:91
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:2711
SCIP_RETCODE SCIPlpiGetCols(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lb, SCIP_Real *ub, int *nnonz, int *beg, int *ind, SCIP_Real *val)
Definition: lpi_glop.cpp:992
static void deleteRowsAndUpdateCurrentBasis(SCIP_LPI *lpi, const DenseBooleanColumn &rows_to_delete)
Definition: lpi_glop.cpp:543
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_glop.cpp:232
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_glop.cpp:2537
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_glop.cpp:343
real eps
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1814
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:2011
SCIP_Real feastol
Definition: lpi_cpx.c:163
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1438
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1935
operations_research::glop::GlopParameters * parameters
Definition: lpi_glop.cpp:92
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_glop.cpp:474
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_glop.cpp:3196
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:140
#define SCIPerrorMessage
Definition: pub_message.h:55
int ncols
Definition: lpi_none.c:44
static SCIP_RETCODE strongbranch(SCIP_LPI *lpi, int col_index, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_glop.cpp:1510
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_glop.cpp:2366
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_glop.cpp:1649
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_glop.cpp:2724
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1825
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_glop.cpp:1123
bool lp_time_limit_was_reached
Definition: lpi_glop.cpp:97
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col_index, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_glop.cpp:1620
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_glop.cpp:1706
int * rstat
Definition: lpi_clp.cpp:99
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_glop.cpp:154
#define SCIP_CALL(x)
Definition: def.h:384
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_glop.cpp:216
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_glop.cpp:1767
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_glop.cpp:2832
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_glop.cpp:573
static void updateScaledLP(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1288
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_glop.cpp:3173
#define EPSCEIL(x, eps)
Definition: def.h:211
static char * glopname
Definition: lpi_glop.cpp:136
SCIP_Longint niterations
Definition: lpi_glop.cpp:109
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1747
int numthreads
Definition: lpi_glop.cpp:103
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1790
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_glop.cpp:2037
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_glop.cpp:595
#define SCIP_Bool
Definition: def.h:84
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_glop.cpp:2741
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_glop.cpp:415
static VariableStatus ConvertSCIPVariableStatus(int status)
Definition: lpi_glop.cpp:2253
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_glop.cpp:2767
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:3141
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_glop.cpp:709
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1905
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_glop.cpp:2677
bool checkcondition
Definition: lpi_glop.cpp:105
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1893
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_glop.cpp:1147
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_glop.cpp:2333
int iterations
Definition: lpi_cpx.c:157
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1918
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_glop.cpp:200
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_glop.cpp:645
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:2000
SCIP_Real * r
Definition: circlepacking.c:50
SCIP_Pricing
Definition: type_lpi.h:67
SCIP_RETCODE SCIPlpiGetRows(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhs, SCIP_Real *rhs, int *nnonz, int *beg, int *ind, SCIP_Real *val)
Definition: lpi_glop.cpp:1058
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_glop.cpp:1679
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_glop.cpp:1456
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_glop.cpp:2100
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1487
SCIP_RETCODE SCIPlpiLoadColLP(SCIP_LPI *lpi, SCIP_OBJSEN objsen, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_glop.cpp:307
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_glop.cpp:780
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_glop.cpp:1226
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1868
public methods for message output
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_glop.cpp:2593
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_glop.cpp:1171
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1976
ScatteredRow * tmp_row
Definition: lpi_glop.cpp:115
#define SCIP_Real
Definition: def.h:177
ScatteredColumn * tmp_column
Definition: lpi_glop.cpp:116
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1838
bool from_scratch
Definition: lpi_glop.cpp:102
#define BMSallocMemory(ptr)
Definition: memory.h:111
#define SCIP_INVALID
Definition: def.h:197
#define SCIP_Longint
Definition: def.h:162
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_glop.cpp:757
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1853
SCIP_MESSAGEHDLR * messagehdlr
Definition: lpi_cpx.c:175
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_glop.cpp:3117
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_glop.cpp:1987
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_glop.cpp:1256
#define EPSFLOOR(x, eps)
Definition: def.h:210
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:430
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_glop.cpp:732
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_glop.cpp:2402
#define SCIP_ALLOC(x)
Definition: def.h:395
#define SCIPABORT()
Definition: def.h:356
const char * SCIPlpiGetSolverName(void)
Definition: lpi_glop.cpp:146
char * initGlopName()
Definition: lpi_glop.cpp:138
char name[200]
Definition: lpi_xprs.c:81
int * cstat
Definition: lpi_clp.cpp:98
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_glop.cpp:2022
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_glop.cpp:3013
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_glop.cpp:439