1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 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_qso.c
17 * @ingroup OTHER_CFILES
18 * @brief LP interface for QSopt version >= 070303
19 * @author Daniel Espinoza
20 * @author Marc Pfetsch
21 */
22
23 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24
25 #include "qsopt.h"
26 #include "scip/bitencode.h"
27 #include "lpi/lpi.h"
28 #include "scip/pub_message.h"
29 #include "scip/pub_misc.h"
30 #include <string.h>
31
32 typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
33 #define COLS_PER_PACKET SCIP_DUALPACKETSIZE
34 typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
35 #define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
36
37 enum LPI_QSOPT_Algo
38 {
39 LPI_QSOPT_ALGO_UNKNOWN = 0, /**< unknown */
40 LPI_QSOPT_ALGO_PRIMAL = 1, /**< primal simplex */
41 LPI_QSOPT_ALGO_DUAL = 2 /**< dual simplex */
42 };
43 typedef enum LPI_QSOPT_Algo LPI_QSOPT_ALGO;
44
45
46 /** LP interface */
47 struct SCIP_LPi
48 {
49 QSprob prob; /**< LP struct pointer */
50 int solstat; /**< solution status of last optimization call */
51 LPI_QSOPT_ALGO algo; /**< previously used algorithm */
52 int previt; /**< previous number of simplex iterations performed */
53 int rowspace; /**< current size of internal row-related arrays */
54 char* isen; /**< array of length rowspace */
55 double* irhs; /**< array of rhs rowspace */
56 double* irng; /**< array of range rowspace */
57 int* ircnt; /**< array of count rowspace */
58 int* irbeg; /**< array of beginning index rowspace */
59 int colspace; /**< current size of internal column-related arrays */
60 int* iccnt; /**< array of length colspace */
61 char* iccha; /**< array of type colspace */
62 int tbsz; /**< current size of tableau-related arrays */
63 double* itab; /**< array of length tbsz */
64 char* ibas; /**< array of length tbsz */
65 int pricing; /**< SCIP pricing option */
66 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
67 };
68
69 /** row norms */
70 struct SCIP_LPiNorms
71 {
72 int nrows; /**< number of rows */
73 int ncols; /**< number of columns */
74 char* cstat; /**< basis status of columns */
75 char* rstat; /**< basis status of rows */
76 SCIP_Real* norms; /**< row norms */
77 };
78
79
80 /** solver name */
81 static char __qsstr[SCIP_MAXSTRLEN];
82
83
84
85 /*
86 * local defines
87 */
88
89 /** (feasibility) tolerance for qsopt */
90 #define FEASTOL 1e-6
91
92 /** tolerance for testing equality */
93 #define EPSILON 1e-9
94
95 /** print location of the calling line */
96 #define __QS_PRINTLOC__ fprintf(stderr,", in (%s:%d)\n", __FILE__, __LINE__)
97
98 /** This macro is to print error messages and jump to the given point in the code, it also prints the
99 * file name and line where this happened. */
100 #define QS_TESTG(A,B,C) do{{ \
101 if (A){ \
102 fprintf(stderr, C); \
103 __QS_PRINTLOC__; \
104 goto B;}}}while(0)
105
106 /** This macro is to print error messages and to exit with SCIP_LPERROR. */
107 #define QS_ERROR(A,...) do{{ \
108 if (A){ \
109 fprintf(stderr,__VA_ARGS__); \
110 __QS_PRINTLOC__; \
111 return SCIP_LPERROR;}}}while(0)
112
113 /** Return value macro, if the value is non-zero, write to standard error the returning code and
114 * where this happened, and return SCIP_ERROR, otherwise return normal SCIP_OKAY termination code. */
115 #define QS_RETURN(A) do{ \
116 const int __RVAL__ = (A); \
117 if (__RVAL__){ \
118 fprintf(stderr,"LP Error: QSopt returned %d",__RVAL__); \
119 __QS_PRINTLOC__; \
120 return SCIP_ERROR;} \
121 return SCIP_OKAY;}while(0)
122
123 /** Return value macro, if the value is non-zero, write to standard error the returning code and
124 * where this happened, and return SCIP_ERROR, otherwise do nothing. */
125 #define QS_CONDRET(A) do{ \
126 const int __RVAL__ = (A); \
127 if (__RVAL__){ \
128 fprintf(stderr,"LP Error: QSopt returned %d",__RVAL__); \
129 __QS_PRINTLOC__; \
130 return SCIP_LPERROR;} \
131 }while(0)
132
133
134
135 /*
136 * LPi state methods
137 */
138
139
140 /** LPi state stores basis information */
141 struct SCIP_LPiState
142 {
143 int ncols; /**< number of LP columns */
144 int nrows; /**< number of LP rows */
145 COLPACKET* packcstat; /**< column basis status in compressed form */
146 ROWPACKET* packrstat; /**< row basis status in compressed form */
147 };
148
149 /** returns the number of packets needed to store column packet information */
150 static
colpacketNum(int ncols)151 int colpacketNum(
152 int ncols /**< number of columns to store */
153 )
154 {
155 return (ncols + (int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
156 }
157
158 /** returns the number of packets needed to store row packet information */
159 static
rowpacketNum(int nrows)160 int rowpacketNum(
161 int nrows /**< number of rows to store */
162 )
163 {
164 return (nrows + (int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
165 }
166
167 /** store row and column basis status in a packed LPi state object */
168 static
lpistatePack(SCIP_LPISTATE * lpistate,const int * cstat,const int * rstat)169 void lpistatePack(
170 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
171 const int* cstat, /**< basis status of columns in unpacked format */
172 const int* rstat /**< basis status of rows in unpacked format */
173 )
174 {
175 assert(lpistate != NULL);
176 assert(lpistate->packcstat != NULL);
177 assert(lpistate->packrstat != NULL);
178
179 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
180 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
181 }
182
183 /** unpacks row and column basis status from a packed LPi state object */
184 static
lpistateUnpack(const SCIP_LPISTATE * lpistate,int * cstat,int * rstat)185 void lpistateUnpack(
186 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
187 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
188 int* rstat /**< buffer for storing basis status of rows in unpacked format */
189 )
190 {
191 assert(lpistate != NULL);
192 assert(lpistate->packcstat != NULL);
193 assert(lpistate->packrstat != NULL);
194
195 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
196 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
197 }
198
199 /** creates LPi state information object */
200 static
lpistateCreate(SCIP_LPISTATE ** lpistate,BMS_BLKMEM * blkmem,int ncols,int nrows)201 SCIP_RETCODE lpistateCreate(
202 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
203 BMS_BLKMEM* blkmem, /**< block memory */
204 int ncols, /**< number of columns to store */
205 int nrows /**< number of rows to store */
206 )
207 {
208 assert(lpistate != NULL);
209 assert(blkmem != NULL);
210 assert(ncols >= 0);
211 assert(nrows >= 0);
212
213 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
214 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, colpacketNum(ncols)) );
215 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, rowpacketNum(nrows)) );
216
217 return SCIP_OKAY;
218 }
219
220 /** frees LPi state information */
221 static
lpistateFree(SCIP_LPISTATE ** lpistate,BMS_BLKMEM * blkmem)222 void lpistateFree(
223 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
224 BMS_BLKMEM* blkmem /**< block memory */
225 )
226 {
227 assert(blkmem != NULL);
228 assert(lpistate != NULL);
229 assert(*lpistate != NULL);
230
231 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, colpacketNum((*lpistate)->ncols));
232 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, rowpacketNum((*lpistate)->nrows));
233 BMSfreeBlockMemory(blkmem, lpistate);
234 }
235
236
237
238 /*
239 * local functions
240 */
241
242 /** ensure size of column-related arrays */
243 static
ensureTabMem(SCIP_LPI * const lpi,int sz)244 SCIP_RETCODE ensureTabMem(
245 SCIP_LPI* const lpi, /**< pointer to an LP interface structure */
246 int sz /**< size */
247 )
248 {
249 assert(lpi != NULL);
250 if( lpi->tbsz < sz )
251 {
252 lpi->tbsz = sz*2;
253 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->itab), lpi->tbsz) );
254 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->ibas), lpi->tbsz) );
255 }
256 return SCIP_OKAY;
257 }
258
259 /** ensure size of column-related arrays */
260 static
ensureColMem(SCIP_LPI * const lpi,int ncols)261 SCIP_RETCODE ensureColMem(
262 SCIP_LPI* const lpi, /**< pointer to an LP interface structure */
263 int ncols /**< number of columns */
264 )
265 {
266 assert(lpi != NULL);
267 if( lpi->colspace < ncols )
268 {
269 lpi->colspace = ncols*2;
270 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->iccnt), lpi->colspace) );
271 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->iccha), lpi->colspace) );
272 }
273 return SCIP_OKAY;
274 }
275
276 /** ensure size of row-related arrays */
277 static
ensureRowMem(SCIP_LPI * const lpi,int nrows)278 SCIP_RETCODE ensureRowMem(
279 SCIP_LPI* const lpi, /**< pointer to an LP interface structure */
280 int nrows /**< number of rows */
281 )
282 {
283 assert(lpi != NULL);
284 if( lpi->rowspace < nrows )
285 {
286 lpi->rowspace = nrows*2;
287 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->isen), lpi->rowspace) );
288 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->irhs), lpi->rowspace) );
289 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->irng), lpi->rowspace) );
290 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->ircnt), lpi->rowspace) );
291 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->irbeg), lpi->rowspace) );
292 }
293 return SCIP_OKAY;
294 }
295
296 /** transform lhs/rhs into qsopt format */
297 static
convertSides(SCIP_LPI * const lpi,int nrows,const double * const lhs,const double * const rhs)298 SCIP_RETCODE convertSides(
299 SCIP_LPI* const lpi, /**< pointer to an LP interface structure */
300 int nrows, /**< number of rows */
301 const double* const lhs, /**< left hand side */
302 const double* const rhs /**< right hand side */
303 )
304 {
305 int state;
306 register int i;
307
308 assert(lpi != NULL);
309 assert(lhs != NULL);
310 assert(rhs!= NULL);
311
312 for( i = 0 ; i < nrows ; ++i )
313 {
314 state = ((lhs[i] <= -QS_MAXDOUBLE ? 1 : 0) | (rhs[i] >= QS_MAXDOUBLE ? 2 : 0));
315 lpi->ircnt[i] = 0;
316 lpi->irbeg[i] = 0;
317 switch( state )
318 {
319 case 0:
320 /* check for equations */
321 if( EPSEQ(lhs[i], rhs[i], EPSILON) )
322 {
323 lpi->isen[i] = 'E';
324 lpi->irhs[i] = lhs[i];
325 lpi->irng[i] = 0.0;
326 }
327 else
328 {
329 lpi->isen[i] = 'R';
330 lpi->irhs[i] = lhs[i];
331 lpi->irng[i] = rhs[i] - lhs[i];
332 assert(lpi->irng[i] >= 0.0);
333 }
334 break;
335 case 1:
336 lpi->isen[i] = 'L';
337 lpi->irhs[i] = rhs[i];
338 lpi->irng[i] = 0;
339 break;
340 case 2:
341 lpi->isen[i] = 'G';
342 lpi->irhs[i] = lhs[i];
343 lpi->irng[i] = 0;
344 break;
345 default:
346 SCIPerrorMessage("Error, constraint %d has no bounds!", i);
347 SCIPABORT();
348 return SCIP_INVALIDDATA; /*lint !e527*/
349 }
350 }
351 return SCIP_OKAY;
352 }
353
354
355
356
357 /*
358 * Miscellaneous Methods
359 */
360
361
362 /**@name Miscellaneous Methods */
363 /**@{ */
364
365
366 /** gets name and version of LP solver */
SCIPlpiGetSolverName(void)367 const char* SCIPlpiGetSolverName(void)
368 {
369 char* vname;
370 size_t vnamelen;
371
372 /* need to copy string to __qsstr, since vname will be freed */
373 vname = QSversion();
374 vnamelen = strlen(vname);
375 if ( vnamelen >= SCIP_MAXSTRLEN-1 )
376 vnamelen = SCIP_MAXSTRLEN - 2;
377 memcpy(__qsstr, vname, vnamelen);
378 __qsstr[vnamelen+1] = '\0';
379 QSfree(vname);
380 return __qsstr;
381 }
382
383 /** gets description of LP solver (developer, webpage, ...) */
SCIPlpiGetSolverDesc(void)384 const char* SCIPlpiGetSolverDesc(
385 void
386 )
387 {
388 return "Linear Programming Solver developed by D. Applegate, W. Cook, S. Dash, and M. Mevenkamp (www.isye.gatech.edu/~wcook/qsopt)";
389 }
390
391 /** gets pointer for LP solver - use only with great care */
SCIPlpiGetSolverPointer(SCIP_LPI * lpi)392 void* SCIPlpiGetSolverPointer(
393 SCIP_LPI* lpi /**< pointer to an LP interface structure */
394 )
395 {
396 assert(lpi != NULL);
397 return (void*) lpi->prob;
398 }
399
400 /** pass integrality information to LP solver */
SCIPlpiSetIntegralityInformation(SCIP_LPI * lpi,int ncols,int * intInfo)401 SCIP_RETCODE SCIPlpiSetIntegralityInformation(
402 SCIP_LPI* lpi, /**< pointer to an LP interface structure */
403 int ncols, /**< length of integrality array */
404 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
405 )
406 { /*lint --e{715}*/
407 assert( lpi != NULL );
408 assert( ncols >= 0 );
409 assert( ncols == 0 || intInfo != NULL );
410
411 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
412 return SCIP_LPERROR;
413 }
414
415 /** informs about availability of a primal simplex solving method */
SCIPlpiHasPrimalSolve(void)416 SCIP_Bool SCIPlpiHasPrimalSolve(
417 void
418 )
419 {
420 return TRUE;
421 }
422
423 /** informs about availability of a dual simplex solving method */
SCIPlpiHasDualSolve(void)424 SCIP_Bool SCIPlpiHasDualSolve(
425 void
426 )
427 {
428 return TRUE;
429 }
430
431 /** informs about availability of a barrier solving method */
SCIPlpiHasBarrierSolve(void)432 SCIP_Bool SCIPlpiHasBarrierSolve(
433 void
434 )
435 {
436 return FALSE;
437 }
438
439 /**@} */
440
441
442
443
444 /*
445 * LPI Creation and Destruction Methods
446 */
447
448 /**@name LPI Creation and Destruction Methods */
449 /**@{ */
450
451 /** creates an LP problem object */
SCIPlpiCreate(SCIP_LPI ** lpi,SCIP_MESSAGEHDLR * messagehdlr,const char * name,SCIP_OBJSEN objsen)452 SCIP_RETCODE SCIPlpiCreate(
453 SCIP_LPI** lpi, /**< pointer to an LP interface structure */
454 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
455 const char* name, /**< problem name */
456 SCIP_OBJSEN objsen /**< objective sense */
457 )
458 {
459 /* QSopt only works with doubles as floating points and bool as integers */
460 assert(sizeof(SCIP_Real) == sizeof(double)); /*lint !e506*/
461 assert(sizeof(SCIP_Bool) == sizeof(int)); /*lint !e506*/
462 assert(name != NULL);
463 assert(lpi != NULL);
464
465 SCIPdebugMessage("SCIPlpiCreate()\n");
466
467 /* create LP */
468 SCIP_ALLOC( BMSallocMemory(lpi) );
469 memset(*lpi, 0, sizeof(struct SCIP_LPi));
470
471 (*lpi)->prob = QScreate_prob(name, (int) objsen);
472 if ( (*lpi)->prob == NULL )
473 {
474 SCIPerrorMessage("No memory\n");
475 return SCIP_LPERROR;
476 }
477
478 (*lpi)->rowspace = 1024;
479 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->isen),1024) );
480 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->irhs),1024) );
481 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->irng),1024) );
482 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->irbeg),1024) );
483 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->ircnt),1024) );
484
485 (*lpi)->colspace = 1024;
486 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->iccnt), 1024) );
487 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->iccha), 1024) );
488
489 (*lpi)->tbsz = 1024;
490 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->itab), 1024) );
491 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->ibas), 1024) );
492
493 (*lpi)->messagehdlr = messagehdlr;
494 (*lpi)->algo = LPI_QSOPT_ALGO_UNKNOWN;
495
496 return SCIP_OKAY;
497 }
498
499 /** deletes an LP problem object */
SCIPlpiFree(SCIP_LPI ** lpi)500 SCIP_RETCODE SCIPlpiFree(
501 SCIP_LPI** lpi /**< pointer to an LP interface structure */
502 )
503 {
504 assert(lpi != NULL);
505 assert(*lpi != NULL);
506
507 SCIPdebugMessage("SCIPlpiFree()\n");
508
509 /* free LP */
510 QSfree_prob((*lpi)->prob);
511 BMSfreeMemoryArray( &((*lpi)->isen) );
512 BMSfreeMemoryArray( &((*lpi)->irhs) );
513 BMSfreeMemoryArray( &((*lpi)->irng) );
514 BMSfreeMemoryArray( &((*lpi)->ircnt) );
515 BMSfreeMemoryArray( &((*lpi)->irbeg) );
516 BMSfreeMemoryArray( &((*lpi)->iccnt) );
517 BMSfreeMemoryArray( &((*lpi)->iccha) );
518 BMSfreeMemoryArray( &((*lpi)->itab) );
519 BMSfreeMemoryArray( &((*lpi)->ibas) );
520
521 /* free memory */
522 BMSfreeMemory(lpi);
523
524 return SCIP_OKAY;
525 }
526 /**@} */
527
528
529
530
531 /*
532 * Modification Methods
533 */
534
535 /**@name Modification Methods */
536 /**@{ */
537
538
539 /** copies LP data with column matrix into LP solver */
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)540 SCIP_RETCODE SCIPlpiLoadColLP(
541 SCIP_LPI* lpi, /**< LP interface structure */
542 SCIP_OBJSEN objsen, /**< objective sense */
543 int ncols, /**< number of columns */
544 const SCIP_Real* obj, /**< objective function values of columns */
545 const SCIP_Real* lb, /**< lower bounds of columns */
546 const SCIP_Real* ub, /**< upper bounds of columns */
547 char** colnames, /**< column names, or NULL */
548 int nrows, /**< number of rows */
549 const SCIP_Real* lhs, /**< left hand sides of rows */
550 const SCIP_Real* rhs, /**< right hand sides of rows */
551 char** rownames, /**< row names, or NULL */
552 int nnonz, /**< number of nonzero elements in the constraint matrix */
553 const int* beg, /**< start index of each column in ind- and val-array */
554 const int* ind, /**< row indices of constraint matrix entries */
555 const SCIP_Real* val /**< values of constraint matrix entries */
556 )
557 {
558 register int i;
559
560 #ifndef NDEBUG
561 {
562 int j;
563 for( j = 0; j < nnonz; j++ )
564 assert( val[j] != 0 );
565 }
566 #endif
567
568 assert(lpi != NULL);
569 assert(lpi->prob != NULL);
570 assert(lhs != NULL);
571 assert(rhs != NULL);
572 assert(obj != NULL);
573 assert(lb != NULL);
574 assert(ub != NULL);
575 assert(beg != NULL);
576 assert(ind != NULL);
577 assert(val != NULL);
578
579 lpi->solstat = 0;
580
581 SCIPdebugMessage("loading LP in column format into QSopt: %d cols, %d rows\n", ncols, nrows);
582
583 /* delete old LP */
584 SCIP_CALL( SCIPlpiClear(lpi) );
585
586 /* set sense */
587 if( objsen == SCIP_OBJSEN_MAXIMIZE )
588 {
589 QS_CONDRET( QSchange_objsense(lpi->prob, QS_MAX) );
590 }
591 else
592 {
593 QS_CONDRET( QSchange_objsense(lpi->prob, QS_MIN) );
594 }
595
596 /* add rows with no matrix, and then the columns, first ensure space */
597 SCIP_CALL( ensureRowMem(lpi, nrows) );
598
599 /* convert lhs/rhs into sen/rhs/range tuples */
600 SCIP_CALL( convertSides(lpi, nrows, lhs, rhs) );
601
602 /* now we add the rows */
603 QS_CONDRET( QSadd_ranged_rows(lpi->prob, nrows, lpi->ircnt, lpi->irbeg, 0, 0, lpi->irhs, lpi->isen, lpi->irng, (const char**)rownames) );
604
605 /* ensure column size */
606 SCIP_CALL( ensureColMem(lpi, ncols) );
607
608 /* compute column lengths */
609 for( i = 0; i < ncols-1; ++i )
610 {
611 lpi->iccnt[i] = beg[i+1] - beg[i];
612 assert(lpi->iccnt[i] >= 0);
613 }
614
615 if( ncols > 0 )
616 {
617 lpi->iccnt[ncols-1] = nnonz - beg[ncols-1];
618 assert(lpi->iccnt[ncols-1] >= 0);
619 }
620
621 /* and add the columns */
622 QS_CONDRET( QSadd_cols(lpi->prob, ncols, lpi->iccnt, (int*) beg, (int*) ind, (SCIP_Real*) val, (SCIP_Real*) obj,
623 (SCIP_Real*) lb, (SCIP_Real*) ub, (const char**)colnames) );
624
625 return SCIP_OKAY;
626 }
627
628
629 /** adds columns to the LP */
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)630 SCIP_RETCODE SCIPlpiAddCols(
631 SCIP_LPI* lpi, /**< LP interface structure */
632 int ncols, /**< number of columns to be added */
633 const SCIP_Real* obj, /**< objective function values of new columns */
634 const SCIP_Real* lb, /**< lower bounds of new columns */
635 const SCIP_Real* ub, /**< upper bounds of new columns */
636 char** colnames, /**< column names, or NULL */
637 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
638 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
639 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
640 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
641 )
642 {
643 register int i;
644 int* lbeg;
645
646 assert( lpi != NULL );
647 assert( lpi->prob != NULL );
648 assert(obj != NULL);
649 assert(nnonz == 0 || beg != NULL);
650 assert(nnonz == 0 || ind != NULL);
651 assert(nnonz == 0 || val != NULL);
652 assert(nnonz >= 0);
653 assert(ncols >= 0);
654
655 SCIPdebugMessage("adding %d columns with %d nonzeros to QSopt\n", ncols, nnonz);
656
657 if ( ncols <= 0 )
658 return SCIP_OKAY;
659 assert( lb != NULL && ub != NULL );
660
661 lpi->solstat = 0;
662
663 /* ensure column size */
664 SCIP_CALL( ensureColMem(lpi, ncols) );
665
666 /* if there are no nonzeros, we have to set up an artificial beg array */
667 if ( nnonz == 0 )
668 {
669 SCIP_ALLOC( BMSallocMemoryArray(&lbeg, ncols) );
670
671 /* compute column lengths */
672 for( i = 0; i < ncols; ++i )
673 {
674 lpi->iccnt[i] = 0;
675 lbeg[i] = 0;
676 }
677 }
678 else
679 {
680 #ifndef NDEBUG
681 /* perform check that no new rows are added - this is forbidden */
682 int nrows;
683
684 nrows = QSget_rowcount(lpi->prob);
685 for (i = 0; i < nnonz; ++i)
686 {
687 assert( 0 <= ind[i] && ind[i] < nrows );
688 assert( val[i] != 0.0 );
689 }
690 #endif
691
692 /* compute column lengths */
693 for( i = 0; i < ncols - 1; ++i )
694 {
695 lpi->iccnt[i] = beg[i+1] - beg[i];
696 assert(lpi->iccnt[i] >= 0);
697 }
698
699 lpi->iccnt[ncols-1] = nnonz - beg[ncols-1];
700 assert(lpi->iccnt[ncols-1] >= 0);
701 lbeg = (int*) beg;
702 }
703
704 /* add the columns */
705 QS_CONDRET( QSadd_cols(lpi->prob, ncols, lpi->iccnt, (int*) lbeg, (int*) ind, (SCIP_Real*) val, (SCIP_Real*) obj,
706 (SCIP_Real*) lb, (SCIP_Real*) ub, (const char**)colnames) );
707
708 /* possibly free space */
709 if ( nnonz == 0 )
710 {
711 BMSfreeMemoryArray(&lbeg);
712 }
713
714 return SCIP_OKAY;
715 }
716
717 /** deletes all columns in the given range from LP */
SCIPlpiDelCols(SCIP_LPI * lpi,int firstcol,int lastcol)718 SCIP_RETCODE SCIPlpiDelCols(
719 SCIP_LPI* lpi, /**< LP interface structure */
720 int firstcol, /**< first column to be deleted */
721 int lastcol /**< last column to be deleted */
722 )
723 {
724 int len;
725 register int i;
726
727 assert(lpi != NULL);
728 assert(lpi->prob != NULL);
729
730 len = lastcol - firstcol +1;
731 lpi->solstat = 0;
732
733 assert(0 <= firstcol && len > 0 && lastcol < QSget_colcount(lpi->prob));
734
735 SCIPdebugMessage("deleting %d columns from QSopt\n", len);
736
737 SCIP_CALL( ensureColMem(lpi, len) );
738 for( i = firstcol ; i <= lastcol ; i++ )
739 lpi->iccnt[i-firstcol] = i;
740
741 QS_CONDRET( QSdelete_cols(lpi->prob, len, lpi->iccnt) );
742
743 return SCIP_OKAY;
744 }
745
746 /** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
SCIPlpiDelColset(SCIP_LPI * lpi,int * dstat)747 SCIP_RETCODE SCIPlpiDelColset(
748 SCIP_LPI* lpi, /**< LP interface structure */
749 int* dstat /**< deletion status of columns
750 * input: 1 if column should be deleted, 0 if not
751 * output: new position of column, -1 if column was deleted */
752 )
753 {
754 int ncols;
755 int ccnt;
756 register int i;
757
758 assert(lpi != NULL);
759 assert(lpi->prob != NULL);
760 assert(dstat != NULL);
761
762 ncols = QSget_colcount(lpi->prob);
763 lpi->solstat = 0;
764
765 SCIPdebugMessage("deleting a column set from QSopt\n");
766
767 QS_CONDRET( QSdelete_setcols(lpi->prob,dstat) );
768
769 for( i=0, ccnt=0; i < ncols; i++ )
770 {
771 if( dstat[i] )
772 dstat[i] = -1;
773 else
774 dstat[i] = ccnt++;
775 }
776
777 return SCIP_OKAY;
778 }
779
780
781 /** adds rows to the LP */
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)782 SCIP_RETCODE SCIPlpiAddRows(
783 SCIP_LPI* lpi, /**< LP interface structure */
784 int nrows, /**< number of rows to be added */
785 const SCIP_Real* lhs, /**< left hand sides of new rows */
786 const SCIP_Real* rhs, /**< right hand sides of new rows */
787 char** rownames, /**< row names, or NULL */
788 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
789 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
790 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
791 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
792 )
793 {
794 register int i;
795
796 assert( lpi != NULL );
797 assert( lpi->prob != NULL );
798 assert( nrows >= 0 );
799 assert(lhs != NULL);
800 assert(rhs != NULL);
801
802 lpi->solstat = 0;
803
804 SCIPdebugMessage("adding %d rows with %d nonzeros to QSopt\n", nrows, nnonz);
805
806 if ( nrows <= 0 )
807 return SCIP_OKAY;
808
809 /* add rows with no matrix, and then the columns, first ensure space */
810 SCIP_CALL( ensureRowMem(lpi, nrows) );
811
812 /* convert lhs/rhs into sen/rhs/range tuples */
813 SCIP_CALL( convertSides(lpi, nrows, lhs, rhs) );
814
815 /* compute row count */
816 if( nnonz > 0 )
817 {
818 assert(beg != NULL);
819 assert(ind != NULL);
820 assert(val != NULL);
821
822 #ifndef NDEBUG
823 {
824 /* perform check that no new cols are added - this is forbidden */
825 int ncols;
826
827 ncols = QSget_colcount(lpi->prob);
828 for (i = 0; i < nnonz; ++i)
829 {
830 assert( val[i] != 0.0 );
831 assert( 0 <= ind[i] && ind[i] < ncols );
832 }
833 }
834 #endif
835
836 for( i = 0 ; i < nrows -1 ; i++ )
837 {
838 lpi->ircnt[i] = beg[i+1] - beg[i];
839 assert(lpi->ircnt[i] >= 0);
840 }
841 assert( nrows > 0 );
842 lpi->ircnt[nrows-1] = nnonz - beg[nrows-1];
843 assert(lpi->ircnt[nrows-1] >= 0);
844
845 /* now we add the rows */
846 QS_CONDRET( QSadd_ranged_rows(lpi->prob, nrows, lpi->ircnt, (int*) beg, (int*) ind, (SCIP_Real*) val, lpi->irhs,
847 lpi->isen, lpi->irng, (const char**)rownames) );
848 }
849 else
850 {
851 for( i = 0; i < nrows -1; ++i )
852 {
853 lpi->ircnt[i] = 0;
854 lpi->irbeg[i] = 0;
855 }
856
857 /* now we add the rows */
858 QS_CONDRET( QSadd_ranged_rows(lpi->prob, nrows, lpi->ircnt, lpi->irbeg, (int*) ind, (SCIP_Real*) val, lpi->irhs,
859 lpi->isen, lpi->irng, (const char**)rownames) );
860 }
861
862 return SCIP_OKAY;
863 }
864
865 /** gets column names */
SCIPlpiGetColNames(SCIP_LPI * lpi,int firstcol,int lastcol,char ** colnames,char * namestorage,int namestoragesize,int * storageleft)866 SCIP_RETCODE SCIPlpiGetColNames(
867 SCIP_LPI* lpi, /**< LP interface structure */
868 int firstcol, /**< first column to get name from LP */
869 int lastcol, /**< last column to get name from LP */
870 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
871 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
872 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
873 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
874 )
875 {
876 char** cnames;
877 char* s;
878 int ncols;
879 int rval;
880 int j;
881 int sizeleft;
882
883 assert(lpi != NULL);
884 assert(lpi->prob != NULL);
885 assert(colnames != NULL || namestoragesize == 0);
886 assert(namestorage != NULL || namestoragesize == 0);
887 assert(namestoragesize >= 0);
888 assert(storageleft != NULL);
889 assert(0 <= firstcol && firstcol <= lastcol && lastcol < QSget_colcount(lpi->prob));
890
891 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
892
893 ncols = QSget_colcount(lpi->prob);
894 SCIP_ALLOC( BMSallocMemoryArray(&cnames, ncols) );
895
896 rval = QSget_colnames(lpi->prob, cnames);
897 QS_ERROR(rval, "failed getting column names");
898
899 /* copy column names */
900 s = namestorage;
901 sizeleft = namestoragesize;
902 for( j = firstcol; j <= lastcol; ++j )
903 {
904 const char* t;
905
906 assert( s != NULL );
907
908 t = cnames[j];
909 if( colnames != NULL )
910 colnames[j-firstcol] = s;
911 while( *t != '\0' )
912 {
913 if( sizeleft > 0 )
914 *(s++) = *(t++);
915 --sizeleft;
916 }
917 *(s++) = '\0';
918 }
919 *storageleft = sizeleft;
920
921 /* free space */
922 for( j = 0; j < ncols; ++j )
923 free(cnames[j]);
924
925 return SCIP_OKAY;
926 }
927
928 /** gets row names */
SCIPlpiGetRowNames(SCIP_LPI * lpi,int firstrow,int lastrow,char ** rownames,char * namestorage,int namestoragesize,int * storageleft)929 SCIP_RETCODE SCIPlpiGetRowNames(
930 SCIP_LPI* lpi, /**< LP interface structure */
931 int firstrow, /**< first row to get name from LP */
932 int lastrow, /**< last row to get name from LP */
933 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
934 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
935 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
936 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
937 )
938 {
939 char** rnames;
940 char* s;
941 int nrows;
942 int rval;
943 int i;
944 int sizeleft;
945
946 assert(lpi != NULL);
947 assert(lpi->prob != NULL);
948 assert(rownames != NULL || namestoragesize == 0);
949 assert(namestorage != NULL || namestoragesize == 0);
950 assert(namestoragesize >= 0);
951 assert(storageleft != NULL);
952 assert(0 <= firstrow && firstrow <= lastrow && lastrow < QSget_rowcount(lpi->prob));
953
954 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
955
956 nrows = QSget_rowcount(lpi->prob);
957 SCIP_ALLOC( BMSallocMemoryArray(&rnames, nrows) );
958
959 rval = QSget_rownames(lpi->prob, rnames);
960 QS_ERROR(rval, "failed getting row names");
961
962 s = namestorage;
963 sizeleft = namestoragesize;
964 for( i = firstrow; i <= lastrow; ++i )
965 {
966 const char* t;
967
968 assert( s != NULL );
969
970 t = rnames[i];
971 if( rownames != NULL )
972 rownames[i-firstrow] = s;
973 while( *t != '\0' )
974 {
975 if( sizeleft > 0 )
976 *(s++) = *(t++);
977 --sizeleft;
978 }
979 *(s++) = '\0';
980 }
981 *storageleft = sizeleft;
982
983 /* free space */
984 for( i = 0; i < nrows; ++i )
985 free(rnames[i]);
986
987 return SCIP_OKAY;
988 }
989
990 /** deletes all rows in the given range from LP */
SCIPlpiDelRows(SCIP_LPI * lpi,int firstrow,int lastrow)991 SCIP_RETCODE SCIPlpiDelRows(
992 SCIP_LPI* lpi, /**< LP interface structure */
993 int firstrow, /**< first row to be deleted */
994 int lastrow /**< last row to be deleted */
995 )
996 {
997 const int len = lastrow - firstrow +1;
998 register int i;
999
1000 assert(lpi != NULL);
1001 assert(lpi->prob != NULL);
1002
1003 lpi->solstat = 0;
1004
1005 assert(0 <= firstrow && len > 0 && lastrow < QSget_rowcount (lpi->prob));
1006
1007 SCIPdebugMessage("deleting %d rows from QSopt\n", len);
1008
1009 SCIP_CALL( ensureRowMem(lpi, len) );
1010 for( i = firstrow; i <= lastrow; i++ )
1011 lpi->ircnt[i-firstrow] = i;
1012 QS_CONDRET( QSdelete_rows(lpi->prob, len, lpi->ircnt) );
1013
1014 return SCIP_OKAY;
1015 }
1016
1017
1018 /** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
SCIPlpiDelRowset(SCIP_LPI * lpi,int * dstat)1019 SCIP_RETCODE SCIPlpiDelRowset(
1020 SCIP_LPI* lpi, /**< LP interface structure */
1021 int* dstat /**< deletion status of rows
1022 * input: 1 if row should be deleted, 0 if not
1023 * output: new position of row, -1 if row was deleted */
1024 )
1025 {
1026 int nrows;
1027 int ccnt;
1028 int ndel = 0;
1029 register int i;
1030
1031 assert(lpi != NULL);
1032 assert(lpi->prob != NULL);
1033
1034 nrows = QSget_rowcount(lpi->prob);
1035 lpi->solstat = 0;
1036
1037 for( i = 0; i < nrows; ++i )
1038 {
1039 if( dstat[i] == 1 )
1040 ndel++;
1041 }
1042
1043 SCIPdebugMessage("deleting a row set from QSopt (%d)\n", ndel);
1044
1045 QS_CONDRET( QSdelete_setrows(lpi->prob,dstat) );
1046
1047 for( i=0, ccnt=0; i < nrows; i++ )
1048 {
1049 if( dstat[i] )
1050 dstat[i] = -1;
1051 else
1052 dstat[i] = ccnt++;
1053 }
1054
1055 return SCIP_OKAY;
1056 }
1057
1058 /** clears the whole LP */
SCIPlpiClear(SCIP_LPI * lpi)1059 SCIP_RETCODE SCIPlpiClear(
1060 SCIP_LPI* lpi /**< LP interface structure */
1061 )
1062 {
1063 char savename[1024];
1064 char* name;
1065 int objsen;
1066
1067 assert(lpi != NULL);
1068 assert(lpi->prob != NULL);
1069
1070 SCIPdebugMessage("clearing QSopt LP\n");
1071 lpi->solstat = 0;
1072
1073 /* save sense and name of problem */
1074 QS_CONDRET( QSget_objsense(lpi->prob, &objsen) );
1075
1076 name = QSget_probname(lpi->prob);
1077 (void)strncpy(savename, name, 1023);
1078 name[1023] = '\0';
1079
1080 QSfree_prob(lpi->prob);
1081 lpi->prob = QScreate_prob(savename, objsen);
1082
1083 return SCIP_OKAY;
1084 }
1085
1086
1087 /** changes lower and upper bounds of columns */
SCIPlpiChgBounds(SCIP_LPI * lpi,int ncols,const int * ind,const SCIP_Real * lb,const SCIP_Real * ub)1088 SCIP_RETCODE SCIPlpiChgBounds(
1089 SCIP_LPI* lpi, /**< LP interface structure */
1090 int ncols, /**< number of columns to change bounds for */
1091 const int* ind, /**< column indices or NULL if ncols is zero */
1092 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
1093 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
1094 )
1095 {
1096 register int i;
1097
1098 assert(lpi != NULL);
1099 assert(lpi->prob != NULL);
1100 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
1101 if( ncols <= 0 )
1102 return SCIP_OKAY;
1103
1104 lpi->solstat = 0;
1105
1106 SCIPdebugMessage("changing %d bounds in QSopt\n", ncols);
1107
1108 for (i = 0; i < ncols; ++i)
1109 {
1110 SCIPdebugPrintf(" col %d: [%g,%g]\n", ind[i], lb[i], ub[i]);
1111
1112 if ( SCIPlpiIsInfinity(lpi, lb[i]) )
1113 {
1114 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
1115 return SCIP_LPERROR;
1116 }
1117 if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
1118 {
1119 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
1120 return SCIP_LPERROR;
1121 }
1122 }
1123
1124 SCIP_CALL(ensureColMem(lpi, ncols));
1125 for( i = 0; i < ncols; ++i )
1126 lpi->iccha[i] = 'L';
1127
1128 QS_CONDRET( QSchange_bounds(lpi->prob, ncols, (int*) ind, lpi->iccha, (SCIP_Real*) lb) );
1129
1130 for( i = 0; i < ncols; ++i )
1131 lpi->iccha[i] = 'U';
1132
1133 QS_CONDRET( QSchange_bounds(lpi->prob, ncols, (int*) ind, lpi->iccha, (SCIP_Real*) ub) );
1134
1135 return SCIP_OKAY;
1136 }
1137
1138 /** changes left and right hand sides of rows */
SCIPlpiChgSides(SCIP_LPI * lpi,int nrows,const int * ind,const SCIP_Real * lhs,const SCIP_Real * rhs)1139 SCIP_RETCODE SCIPlpiChgSides(
1140 SCIP_LPI* lpi, /**< LP interface structure */
1141 int nrows, /**< number of rows to change sides for */
1142 const int* ind, /**< row indices */
1143 const SCIP_Real* lhs, /**< new values for left hand sides */
1144 const SCIP_Real* rhs /**< new values for right hand sides */
1145 )
1146 {
1147 register int i;
1148
1149 assert(lpi != NULL);
1150 assert(lpi->prob != NULL);
1151 assert(ind != NULL);
1152 if( nrows <= 0 )
1153 return SCIP_OKAY;
1154
1155 lpi->solstat = 0;
1156
1157 SCIPdebugMessage("changing %d sides in QSopt\n", nrows);
1158
1159 SCIP_CALL( ensureRowMem(lpi, nrows) );
1160
1161 /* convert lhs/rhs into sen/rhs/range tuples */
1162 SCIP_CALL( convertSides(lpi, nrows, lhs, rhs) );
1163
1164 /* now we change all rows */
1165 for( i = 0; i < nrows; ++i )
1166 {
1167 QS_CONDRET( QSchange_sense(lpi->prob, ind[i], lpi->isen[i]) );
1168
1169 QS_CONDRET( QSchange_rhscoef(lpi->prob, ind[i], lpi->irhs[i]) );
1170
1171 if( lpi->isen[i] == 'R' )
1172 {
1173 QS_CONDRET( QSchange_range(lpi->prob, ind[i], lpi->irng[i]) );
1174 }
1175 }
1176
1177 return SCIP_OKAY;
1178 }
1179
1180 /** changes a single coefficient */
SCIPlpiChgCoef(SCIP_LPI * lpi,int row,int col,SCIP_Real newval)1181 SCIP_RETCODE SCIPlpiChgCoef(
1182 SCIP_LPI* lpi, /**< LP interface structure */
1183 int row, /**< row number of coefficient to change */
1184 int col, /**< column number of coefficient to change */
1185 SCIP_Real newval /**< new value of coefficient */
1186 )
1187 {
1188 assert(lpi != NULL);
1189 assert(lpi->prob != NULL);
1190
1191 lpi->solstat = 0;
1192
1193 SCIPdebugMessage("changing coefficient row %d, column %d in QSopt to %g\n", row, col, newval);
1194
1195 QS_CONDRET( QSchange_coef(lpi->prob, row, col, newval) );
1196
1197 return SCIP_OKAY;
1198 }
1199
1200 /** changes the objective sense */
SCIPlpiChgObjsen(SCIP_LPI * lpi,SCIP_OBJSEN objsen)1201 SCIP_RETCODE SCIPlpiChgObjsen(
1202 SCIP_LPI* lpi, /**< LP interface structure */
1203 SCIP_OBJSEN objsen /**< new objective sense */
1204 )
1205 {
1206 assert(lpi != NULL);
1207 assert(lpi->prob != NULL);
1208
1209 lpi->solstat = 0;
1210 SCIPdebugMessage("changing objective sense in QSopt to %d\n", objsen);
1211
1212 /* set sense */
1213 if( objsen == SCIP_OBJSEN_MAXIMIZE )
1214 {
1215 QS_CONDRET( QSchange_objsense(lpi->prob, QS_MAX) );
1216 }
1217 else
1218 {
1219 QS_CONDRET( QSchange_objsense(lpi->prob, QS_MIN) );
1220 }
1221
1222 return SCIP_OKAY;
1223 }
1224
1225 /** changes objective values of columns in the LP */
SCIPlpiChgObj(SCIP_LPI * lpi,int ncols,const int * ind,const SCIP_Real * obj)1226 SCIP_RETCODE SCIPlpiChgObj(
1227 SCIP_LPI* lpi, /**< LP interface structure */
1228 int ncols, /**< number of columns to change objective value for */
1229 const int* ind, /**< column indices to change objective value for */
1230 const SCIP_Real* obj /**< new objective values for columns */
1231 )
1232 {
1233 register int i;
1234
1235 assert(lpi != NULL);
1236 assert(lpi->prob != NULL);
1237 assert(ind != NULL);
1238 assert(obj != NULL);
1239
1240 lpi->solstat = 0;
1241
1242 SCIPdebugMessage("changing %d objective values in QSopt\n", ncols);
1243
1244 for( i = 0; i < ncols; ++i )
1245 {
1246 QS_CONDRET( QSchange_objcoef(lpi->prob, ind[i], obj[i]) );
1247 }
1248
1249 return SCIP_OKAY;
1250 }
1251
1252 /** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
SCIPlpiScaleRow(SCIP_LPI * lpi,int row,SCIP_Real scaleval)1253 SCIP_RETCODE SCIPlpiScaleRow(
1254 SCIP_LPI* lpi, /**< LP interface structure */
1255 int row, /**< row number to scale */
1256 SCIP_Real scaleval /**< scaling multiplier */
1257 )
1258 {
1259 register int i;
1260 int rowlist[1];
1261 int* rowcnt = NULL, *rowbeg = NULL, *rowind = NULL;
1262 double* rowval = NULL, *rhs = NULL, *range = NULL;
1263 char* sense = NULL;
1264 int rval;
1265
1266 assert(lpi != NULL);
1267 assert(lpi->prob != NULL);
1268
1269 lpi->solstat = 0;
1270
1271 SCIPdebugMessage("scaling row %d with factor %g in QSopt\n", row, scaleval);
1272
1273 rowlist[0] = row;
1274 /* get row */
1275 rval = QSget_ranged_rows_list(lpi->prob, 1, rowlist, &rowcnt, &rowbeg, &rowind, &rowval, &rhs, &sense, &range, 0);
1276 QS_TESTG(rval, CLEANUP, " ");
1277
1278 /* change all coefficients in the constraint */
1279 for( i = 0; i < rowcnt[0]; ++i )
1280 {
1281 rval = QSchange_coef(lpi->prob, row, rowind[i], rowval[i] * scaleval);
1282 QS_TESTG(rval, CLEANUP, " ");
1283 }
1284
1285 /* if we have a positive scalar, we just scale rhs and range */
1286 if( scaleval >= 0 )
1287 {
1288 rval = QSchange_rhscoef(lpi->prob, row, rhs[0] * scaleval);
1289 QS_TESTG(rval, CLEANUP, " ");
1290 if( sense[0] == 'R' )
1291 {
1292 rval = QSchange_range(lpi->prob, row, range[0] * scaleval);
1293 QS_TESTG(rval, CLEANUP, " ");
1294 }
1295 }
1296 /* otherwise, we must change everything */
1297 else
1298 {
1299 switch( sense[0] )
1300 {
1301 case 'E':
1302 rval = QSchange_rhscoef(lpi->prob, row, rhs[0]*scaleval);
1303 QS_TESTG(rval, CLEANUP, " ");
1304 break;
1305 case 'L':
1306 rval = QSchange_rhscoef(lpi->prob, row, rhs[0]*scaleval);
1307 QS_TESTG(rval, CLEANUP, " ");
1308 rval = QSchange_sense(lpi->prob, row, 'G');
1309 QS_TESTG(rval, CLEANUP, " ");
1310 break;
1311 case 'G':
1312 rval = QSchange_rhscoef(lpi->prob, row, rhs[0]*scaleval);
1313 QS_TESTG(rval, CLEANUP, " ");
1314 rval = QSchange_sense(lpi->prob, row, 'L');
1315 QS_TESTG(rval, CLEANUP, " ");
1316 break;
1317 case 'R':
1318 rhs[0] = (rhs[0] + range[0]) * scaleval;
1319 range[0] = fabs(scaleval) * range[0];
1320 rval = QSchange_rhscoef(lpi->prob, row, rhs[0]);
1321 QS_TESTG(rval, CLEANUP, " ");
1322 rval = QSchange_range(lpi->prob, row, range[0]);
1323 QS_TESTG(rval, CLEANUP, " ");
1324 break;
1325 default:
1326 SCIPerrorMessage("Impossible! received sense %c (not E L G R)", sense[0]);
1327 rval = 1;
1328 goto CLEANUP;
1329 }
1330 }
1331
1332 /* now we must free all received arrays */
1333 /* ending */
1334 CLEANUP:
1335 if( rowcnt != NULL )
1336 QSfree(rowcnt);
1337 if( rowbeg != NULL )
1338 QSfree(rowbeg);
1339 if( rowind != NULL )
1340 QSfree(rowind);
1341 if( rowval != NULL )
1342 QSfree(rowval);
1343 if( rhs != NULL )
1344 QSfree(rhs);
1345 if( sense != NULL )
1346 QSfree(sense);
1347 if( range != NULL )
1348 QSfree(range);
1349
1350 QS_RETURN(rval);
1351 }
1352
1353 /** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
1354 * are divided by the scalar; for negative scalars, the column's bounds are switched
1355 */
SCIPlpiScaleCol(SCIP_LPI * lpi,int col,SCIP_Real scaleval)1356 SCIP_RETCODE SCIPlpiScaleCol(
1357 SCIP_LPI* lpi, /**< LP interface structure */
1358 int col, /**< column number to scale */
1359 SCIP_Real scaleval /**< scaling multiplier */
1360 )
1361 {
1362 register int i;
1363 int collist[1];
1364 int* colcnt=0;
1365 int* colbeg=0;
1366 int* colind=0;
1367 double* colval=0;
1368 double* lb=0;
1369 double* ub=0;
1370 double* obj=0;
1371 int rval;
1372
1373 assert(lpi != NULL);
1374 assert(lpi->prob != NULL);
1375
1376 lpi->solstat = 0;
1377
1378 SCIPdebugMessage("scaling column %d with factor %g in QSopt\n", col, scaleval);
1379
1380 /* get the column */
1381 collist[0] = col;
1382 rval = QSget_columns_list(lpi->prob, 1, collist, &colcnt, &colbeg, &colind, &colval, &obj, &lb, &ub, 0);
1383 QS_TESTG(rval, CLEANUP, " ");
1384
1385 /* scale column coefficients */
1386 for( i = 0; i < colcnt[0]; ++i )
1387 {
1388 rval = QSchange_coef(lpi->prob, colind[i], col, colval[i]*scaleval);
1389 QS_TESTG(rval, CLEANUP, " ");
1390 }
1391
1392 /* scale objective value */
1393 rval = QSchange_objcoef(lpi->prob, col, obj[0]*scaleval);
1394 QS_TESTG(rval, CLEANUP, " ");
1395
1396 /* scale column bounds */
1397 if( scaleval < 0 )
1398 {
1399 scaleval = -scaleval;
1400 obj[0] = lb[0];
1401 lb[0] = -ub[0];
1402 ub[0] = -obj[0];
1403 }
1404 if( lb[0] > -QS_MAXDOUBLE )
1405 lb[0] *= scaleval;
1406 if( ub[0] < QS_MAXDOUBLE )
1407 ub[0] *= scaleval;
1408
1409 if( lb[0] < -QS_MAXDOUBLE )
1410 lb[0] = -QS_MAXDOUBLE;
1411 if( ub[0] > QS_MAXDOUBLE )
1412 ub[0] = QS_MAXDOUBLE;
1413
1414 rval = QSchange_bound(lpi->prob, col, 'L', lb[0]);
1415 QS_TESTG(rval, CLEANUP, " ");
1416 rval = QSchange_bound(lpi->prob, col, 'U', ub[0]);
1417 QS_TESTG(rval, CLEANUP, " ");
1418
1419 /* ending */
1420 CLEANUP:
1421 if( colcnt != NULL )
1422 QSfree(colcnt);
1423 if( colbeg != NULL )
1424 QSfree(colbeg);
1425 if( colind != NULL )
1426 QSfree(colind);
1427 if( colval != NULL )
1428 QSfree(colval);
1429 if( obj != NULL )
1430 QSfree(obj);
1431 if( lb != NULL )
1432 QSfree(lb);
1433 if( ub != NULL )
1434 QSfree(ub);
1435
1436 QS_RETURN(rval);
1437 }
1438 /**@} */
1439
1440
1441
1442
1443 /*
1444 * Data Accessing Methods
1445 */
1446
1447 /**@name Data Accessing Methods */
1448 /**@{ */
1449
1450 /** gets the number of rows in the LP */
SCIPlpiGetNRows(SCIP_LPI * lpi,int * nrows)1451 SCIP_RETCODE SCIPlpiGetNRows(
1452 SCIP_LPI* lpi, /**< LP interface structure */
1453 int* nrows /**< pointer to store the number of rows */
1454 )
1455 {
1456 assert(lpi != NULL);
1457 assert(lpi->prob != NULL);
1458 assert(nrows != NULL);
1459
1460 SCIPdebugMessage("getting number of rows\n");
1461
1462 *nrows = QSget_rowcount(lpi->prob);
1463
1464 return SCIP_OKAY;
1465 }
1466
1467 /** gets the number of columns in the LP */
SCIPlpiGetNCols(SCIP_LPI * lpi,int * ncols)1468 SCIP_RETCODE SCIPlpiGetNCols(
1469 SCIP_LPI* lpi, /**< LP interface structure */
1470 int* ncols /**< pointer to store the number of cols */
1471 )
1472 {
1473 assert(lpi != NULL);
1474 assert(lpi->prob != NULL);
1475 assert(ncols != NULL);
1476
1477 SCIPdebugMessage("getting number of columns\n");
1478
1479 *ncols = QSget_colcount(lpi->prob);
1480
1481 return SCIP_OKAY;
1482 }
1483
1484 /** gets the number of nonzero elements in the LP constraint matrix */
SCIPlpiGetNNonz(SCIP_LPI * lpi,int * nnonz)1485 SCIP_RETCODE SCIPlpiGetNNonz(
1486 SCIP_LPI* lpi, /**< LP interface structure */
1487 int* nnonz /**< pointer to store the number of nonzeros */
1488 )
1489 {
1490 assert(lpi != NULL);
1491 assert(lpi->prob != NULL);
1492 assert(nnonz != NULL);
1493
1494 SCIPdebugMessage("getting number of columns\n");
1495
1496 *nnonz = QSget_nzcount(lpi->prob);
1497
1498 return SCIP_OKAY;
1499 }
1500
1501 /** gets columns from LP problem object; the arrays have to be large enough to store all values
1502 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
1503 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1504 */
SCIPlpiGetCols(SCIP_LPI * lpi,int firstcol,int lastcol,SCIP_Real * lb,SCIP_Real * ub,int * nnonz,int * beg,int * ind,SCIP_Real * val)1505 SCIP_RETCODE SCIPlpiGetCols(
1506 SCIP_LPI* lpi, /**< LP interface structure */
1507 int firstcol, /**< first column to get from LP */
1508 int lastcol, /**< last column to get from LP */
1509 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
1510 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
1511 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1512 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1513 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1514 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1515 )
1516 {
1517 int len;
1518 register int i;
1519 double* lval = NULL;
1520 double* llb = NULL;
1521 double* lub = NULL;
1522 int rval;
1523 int* lcnt = NULL;
1524 int* lbeg = NULL;
1525 int* lind = NULL;
1526
1527 assert(lpi != NULL);
1528 assert(lpi->prob != NULL);
1529 assert(0 <= firstcol && firstcol <= lastcol && lastcol < QSget_colcount(lpi->prob));
1530 assert((lb == NULL && ub == NULL) || (lb != NULL && ub != NULL));
1531 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1532
1533 SCIPdebugMessage("getting columns %d to %d\n", firstcol, lastcol);
1534
1535 /* build col-list */
1536 len = lastcol - firstcol + 1;
1537 assert( len > 0 );
1538 SCIP_CALL( ensureColMem(lpi, len) );
1539 for( i = 0; i < len; ++i )
1540 lpi->iccnt[i] = i + firstcol;
1541
1542 /* get data from qsopt */
1543 if ( nnonz != NULL )
1544 rval = QSget_columns_list(lpi->prob, len, lpi->iccnt, &lcnt, &lbeg, &lind, &lval, NULL, lb ? (&llb) : NULL, ub ? (&lub) : NULL, NULL); /*lint !e826*/
1545 else
1546 rval = QSget_columns_list(lpi->prob, len, lpi->iccnt, NULL, NULL, NULL, NULL, NULL, lb ? (&llb) : NULL, ub ? (&lub) : NULL, NULL); /*lint !e826*/
1547
1548 QS_TESTG(rval, CLEANUP, " ");
1549
1550 /* store in the user-provided data */
1551 if( nnonz != NULL )
1552 {
1553 assert(beg != NULL && ind != NULL && val != NULL); /* for lint */
1554
1555 if( lcnt == NULL || lbeg == NULL || lind == NULL || lval == NULL )
1556 {
1557 SCIPerrorMessage("QSget_columns_list() failed to allocate memory.\n");
1558 return SCIP_LPERROR;
1559 }
1560
1561 *nnonz = lbeg[len-1] + lcnt[len-1];
1562 for( i = 0 ; i < len ; i++ )
1563 beg[i] = lbeg[i];
1564 for( i = 0; i < *nnonz; ++i )
1565 {
1566 ind[i] = lind[i];
1567 val[i] = lval[i];
1568 }
1569 }
1570
1571 if( lb != NULL )
1572 {
1573 assert( ub != NULL ); /* for lint */
1574
1575 if( llb == NULL || lub == NULL ) /*lint !e774*/
1576 {
1577 SCIPerrorMessage("QSget_columns_list() failed to allocate memory.\n");
1578 return SCIP_LPERROR;
1579 }
1580
1581 for( i = 0; i < len; ++i )
1582 {
1583 lb[i] = llb[i];
1584 ub[i] = lub[i];
1585 }
1586 }
1587
1588 CLEANUP:
1589 if( lval != NULL )
1590 QSfree(lval);
1591 if( lub != NULL ) /*lint !e831 !e774*/
1592 QSfree(lub);
1593 if( llb != NULL ) /*lint !e831 !e774*/
1594 QSfree(llb);
1595 if( lind != NULL )
1596 QSfree(lind);
1597 if( lbeg != NULL )
1598 QSfree(lbeg);
1599 if( lcnt != NULL )
1600 QSfree(lcnt);
1601
1602 QS_RETURN(rval);
1603 }
1604
1605 /** gets rows from LP problem object; the arrays have to be large enough to store all values.
1606 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
1607 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1608 */
SCIPlpiGetRows(SCIP_LPI * lpi,int firstrow,int lastrow,SCIP_Real * lhs,SCIP_Real * rhs,int * nnonz,int * beg,int * ind,SCIP_Real * val)1609 SCIP_RETCODE SCIPlpiGetRows(
1610 SCIP_LPI* lpi, /**< LP interface structure */
1611 int firstrow, /**< first row to get from LP */
1612 int lastrow, /**< last row to get from LP */
1613 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
1614 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
1615 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1616 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
1617 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
1618 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1619 )
1620 {
1621 const int len = lastrow - firstrow + 1;
1622 register int i;
1623 double* lval = NULL;
1624 double* lrhs = NULL;
1625 double* lrng = NULL;
1626 int rval;
1627 int* lcnt = NULL;
1628 int* lbeg = NULL;
1629 int* lind = NULL;
1630 char* lsense = NULL;
1631
1632 assert(lpi != NULL);
1633 assert(lpi->prob != NULL);
1634 assert(0 <= firstrow && firstrow <= lastrow && lastrow < QSget_rowcount (lpi->prob));
1635 assert((lhs == NULL && rhs == NULL) || (rhs != NULL && lhs != NULL));
1636 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1637
1638 SCIPdebugMessage("getting rows %d to %d\n", firstrow, lastrow);
1639
1640 /* build row-list */
1641 SCIP_CALL( ensureRowMem(lpi, len) );
1642 for( i = 0; i < len; ++i )
1643 lpi->ircnt[i] = i + firstrow;
1644
1645 /* get data from qsopt */
1646 if ( nnonz != NULL )
1647 rval = QSget_ranged_rows_list(lpi->prob, len, lpi->ircnt, &lcnt, &lbeg, &lind, &lval, rhs ? (&lrhs) : NULL, rhs ? (&lsense) : NULL, rhs ? (&lrng) : NULL, NULL); /*lint !e826*/
1648 else
1649 rval = QSget_ranged_rows_list(lpi->prob, len, lpi->ircnt, NULL, NULL, NULL, NULL, rhs ? (&lrhs) : NULL, rhs ? (&lsense) : NULL, rhs ? (&lrng) : NULL, NULL); /*lint !e826*/
1650
1651 QS_TESTG(rval, CLEANUP, " ");
1652
1653 /* store in the user-provided data */
1654 if( nnonz != NULL )
1655 {
1656 assert( beg != NULL && ind != NULL && val != NULL ); /* for lint */
1657
1658 if( lcnt == NULL || lbeg == NULL || lind == NULL || lval == NULL )
1659 {
1660 SCIPerrorMessage("QSget_ranged_rows_list() failed to allocate memory.\n");
1661 return SCIP_LPERROR;
1662 }
1663
1664 *nnonz = lbeg[len-1] + lcnt[len-1];
1665 for( i = 0 ; i < len; i++ )
1666 beg[i] = lbeg[i];
1667 for( i = 0; i < *nnonz; ++i )
1668 {
1669 ind[i] = lind[i];
1670 val[i] = lval[i];
1671 }
1672 }
1673
1674 if( rhs != NULL )
1675 {
1676 if( lrhs == NULL || lrng == NULL || lsense == NULL ) /*lint !e774*/
1677 {
1678 SCIPerrorMessage("QSget_ranged_rows_list() failed to allocate memory.\n");
1679 return SCIP_LPERROR;
1680 }
1681
1682 assert( lhs != NULL ); /* for lint */
1683
1684 for( i = 0; i < len; ++i )
1685 {
1686 switch( lsense[i] )
1687 {
1688 case 'R':
1689 lhs[i] = lrhs[i];
1690 rhs[i] = lrhs[i] + lrng[i];
1691 break;
1692 case 'E':
1693 lhs[i] = lrhs[i];
1694 rhs[i] = lrhs[i];
1695 break;
1696 case 'L':
1697 rhs[i] = lrhs[i];
1698 lhs[i] = -QS_MAXDOUBLE;
1699 break;
1700 case 'G':
1701 lhs[i] = lrhs[i];
1702 rhs[i] = QS_MAXDOUBLE;
1703 break;
1704 default:
1705 SCIPerrorMessage("Unknown sense %c from QSopt", lsense[i]);
1706 SCIPABORT();
1707 return SCIP_INVALIDDATA; /*lint !e527*/
1708 }
1709 }
1710 }
1711
1712 CLEANUP:
1713 if( lsense != NULL ) /*lint !e774*/
1714 QSfree(lsense);
1715 if( lrng != NULL ) /*lint !e774*/
1716 QSfree(lrng);
1717 if( lrhs != NULL ) /*lint !e774*/
1718 QSfree(lrhs);
1719 if( lval != NULL )
1720 QSfree(lval);
1721 if( lind != NULL )
1722 QSfree(lind);
1723 if( lbeg != NULL )
1724 QSfree(lbeg);
1725 if( lcnt != NULL )
1726 QSfree(lcnt);
1727
1728 QS_RETURN(rval);
1729 }
1730
1731 /** gets the objective sense of the LP */
SCIPlpiGetObjsen(SCIP_LPI * lpi,SCIP_OBJSEN * objsen)1732 SCIP_RETCODE SCIPlpiGetObjsen(
1733 SCIP_LPI* lpi, /**< LP interface structure */
1734 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
1735 )
1736 {
1737 int sense;
1738
1739 assert(lpi != NULL);
1740 assert(lpi->prob != NULL);
1741 assert( objsen != NULL );
1742
1743 QS_CONDRET( QSget_objsense(lpi->prob, &sense) );
1744 if ( sense == QS_MIN )
1745 *objsen = SCIP_OBJSEN_MINIMIZE;
1746 else
1747 *objsen = SCIP_OBJSEN_MAXIMIZE;
1748
1749 return SCIP_OKAY;
1750 }
1751
1752 /** gets objective coefficients from LP problem object */
SCIPlpiGetObj(SCIP_LPI * lpi,int firstcol,int lastcol,SCIP_Real * vals)1753 SCIP_RETCODE SCIPlpiGetObj(
1754 SCIP_LPI* lpi, /**< LP interface structure */
1755 int firstcol, /**< first column to get objective coefficient for */
1756 int lastcol, /**< last column to get objective coefficient for */
1757 SCIP_Real* vals /**< array to store objective coefficients */
1758 )
1759 { /*lint --e{715}*/
1760 int len;
1761 register int i;
1762 double* qsoptvals;
1763
1764 assert(lpi != NULL);
1765 assert(lpi->prob != NULL);
1766 assert(vals != NULL);
1767 assert(0 <= firstcol && firstcol <= lastcol && lastcol < QSget_colcount (lpi->prob));
1768
1769 SCIPdebugMessage("getting objective values %d to %d\n", firstcol, lastcol);
1770
1771 /* build col-list */
1772 len = lastcol - firstcol + 1;
1773 SCIP_CALL(ensureColMem(lpi,len));
1774 for( i = 0; i < len; ++i )
1775 lpi->iccnt[i] = i + firstcol;
1776
1777 /* get data from qsopt */
1778
1779 /* There seems to be a bug in qsopt: The function QSget_obj_list might return values for slack variables. We
1780 * therefore have to use a workarround. */
1781 #ifdef SCIP_DISABLED_CODE
1782 QS_CONDRET( QSget_obj_list(lpi->prob, len, lpi->iccnt, vals) );
1783 #endif
1784
1785 QS_CONDRET( QSget_columns_list(lpi->prob, len, lpi->iccnt, NULL, NULL, NULL, NULL, &qsoptvals, NULL, NULL, NULL) );
1786 for (i = 0; i < len; ++i)
1787 vals[i] = qsoptvals[i];
1788 free( qsoptvals );
1789
1790 return SCIP_OKAY;
1791 }
1792
1793 /** gets current bounds from LP problem object */
SCIPlpiGetBounds(SCIP_LPI * lpi,int firstcol,int lastcol,SCIP_Real * lbs,SCIP_Real * ubs)1794 SCIP_RETCODE SCIPlpiGetBounds(
1795 SCIP_LPI* lpi, /**< LP interface structure */
1796 int firstcol, /**< first column to get objective value for */
1797 int lastcol, /**< last column to get objective value for */
1798 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
1799 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
1800 )
1801 {
1802 const int len = lastcol - firstcol + 1;
1803 register int i;
1804
1805 assert(lpi != NULL);
1806 assert(lpi->prob != NULL);
1807 assert(0 <= firstcol && firstcol <= lastcol&& lastcol < QSget_colcount (lpi->prob));
1808
1809 SCIPdebugMessage("getting bound values %d to %d\n", firstcol, lastcol);
1810
1811 /* build col-list */
1812 SCIP_CALL(ensureColMem(lpi,len));
1813 for( i = 0; i < len; ++i )
1814 lpi->iccnt[i] = i + firstcol;
1815
1816 /* get data from qsopt */
1817 QS_CONDRET( QSget_bounds_list(lpi->prob, len, lpi->iccnt, lbs, ubs) );
1818
1819 return SCIP_OKAY;
1820 }
1821
1822 /** gets current row sides from LP problem object */
SCIPlpiGetSides(SCIP_LPI * lpi,int firstrow,int lastrow,SCIP_Real * lhss,SCIP_Real * rhss)1823 SCIP_RETCODE SCIPlpiGetSides(
1824 SCIP_LPI* lpi, /**< LP interface structure */
1825 int firstrow, /**< first row to get sides for */
1826 int lastrow, /**< last row to get sides for */
1827 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
1828 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
1829 )
1830 {
1831 const int len = lastrow - firstrow + 1;
1832 register int i;
1833 double* lrhs=0, *lrng=0;
1834 int rval;
1835 char* lsense=0;
1836
1837 assert(lpi != NULL);
1838 assert(lpi->prob != NULL);
1839 assert(0 <= firstrow && firstrow <= lastrow && lastrow < QSget_rowcount (lpi->prob));
1840 assert(rhss != NULL);
1841 assert(lhss != NULL);
1842
1843 SCIPdebugMessage("getting row sides %d to %d\n", firstrow, lastrow);
1844
1845 /* build row-list */
1846 SCIP_CALL( ensureRowMem(lpi, len) );
1847 for( i = 0; i < len; ++i )
1848 lpi->ircnt[i] = i + firstrow;
1849
1850 /* get data from qsopt */
1851 rval = QSget_ranged_rows_list(lpi->prob, len, lpi->ircnt, 0, 0, 0, 0, &lrhs, &lsense, &lrng, 0);
1852 QS_TESTG(rval, CLEANUP, " ");
1853
1854 /* store in the user-provided data */
1855 for( i = 0; i < len; ++i )
1856 {
1857 switch( lsense[i] )
1858 {
1859 case 'R':
1860 lhss[i] = lrhs[i];
1861 rhss[i] = lrhs[i] + lrng[i];
1862 break;
1863 case 'E':
1864 lhss[i] = rhss[i] = lrhs[i];
1865 break;
1866 case 'L':
1867 rhss[i] = lrhs[i];
1868 lhss[i] = -QS_MAXDOUBLE;
1869 break;
1870 case 'G':
1871 lhss[i] = lrhs[i];
1872 rhss[i] = QS_MAXDOUBLE;
1873 break;
1874 default:
1875 SCIPerrorMessage("Unknown sense %c from QSopt", lsense[i]);
1876 SCIPABORT();
1877 return SCIP_INVALIDDATA; /*lint !e527*/
1878 }
1879 }
1880
1881 CLEANUP:
1882 if( lsense != NULL )
1883 QSfree(lsense);
1884 if( lrng != NULL )
1885 QSfree(lrng);
1886 if( lrhs != NULL )
1887 QSfree(lrhs);
1888
1889 QS_RETURN(rval);
1890 }
1891
1892 /** gets a single coefficient */
SCIPlpiGetCoef(SCIP_LPI * lpi,int row,int col,SCIP_Real * val)1893 SCIP_RETCODE SCIPlpiGetCoef(
1894 SCIP_LPI* lpi, /**< LP interface structure */
1895 int row, /**< row number of coefficient */
1896 int col, /**< column number of coefficient */
1897 SCIP_Real* val /**< pointer to store the value of the coefficient */
1898 )
1899 {
1900 assert(lpi != NULL);
1901 assert(lpi->prob != NULL);
1902 assert(val != NULL);
1903
1904 SCIPdebugMessage("getting coefficient of row %d col %d\n", row, col);
1905
1906 QS_CONDRET( QSget_coef(lpi->prob, row, col, val) );
1907
1908 return SCIP_OKAY;
1909 }
1910
1911 /**@} */
1912
1913
1914
1915
1916 /*
1917 * Solving Methods
1918 */
1919
1920 /**@name Solving Methods */
1921 /**@{ */
1922
1923 /** calls primal simplex to solve the LP */
SCIPlpiSolvePrimal(SCIP_LPI * lpi)1924 SCIP_RETCODE SCIPlpiSolvePrimal(
1925 SCIP_LPI* lpi /**< LP interface structure */
1926 )
1927 {
1928 assert(lpi != NULL);
1929 assert(lpi->prob != NULL);
1930
1931 SCIPdebugMessage("calling QSopt primal simplex: %d cols, %d rows, %d nz\n", QSget_colcount(lpi->prob),
1932 QSget_rowcount(lpi->prob), QSget_nzcount(lpi->prob));
1933
1934 QS_CONDRET( QSopt_primal(lpi->prob, &(lpi->solstat)) );
1935 lpi->algo = LPI_QSOPT_ALGO_PRIMAL;
1936
1937 return SCIP_OKAY;
1938 }
1939
1940 /** calls dual simplex to solve the LP */
SCIPlpiSolveDual(SCIP_LPI * lpi)1941 SCIP_RETCODE SCIPlpiSolveDual(
1942 SCIP_LPI* lpi /**< LP interface structure */
1943 )
1944 {
1945 assert(lpi != NULL);
1946 assert(lpi->prob != NULL);
1947
1948 SCIPdebugMessage("calling QSopt dual simplex: %d cols, %d rows, %d nz\n", QSget_colcount(lpi->prob),
1949 QSget_rowcount(lpi->prob), QSget_nzcount(lpi->prob));
1950
1951 QS_CONDRET( QSopt_dual(lpi->prob, &(lpi->solstat)) );
1952 lpi->algo = LPI_QSOPT_ALGO_DUAL;
1953
1954 return SCIP_OKAY;
1955 }
1956
1957 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
SCIPlpiSolveBarrier(SCIP_LPI * lpi,SCIP_Bool crossover)1958 SCIP_RETCODE SCIPlpiSolveBarrier(
1959 SCIP_LPI* lpi, /**< LP interface structure */
1960 SCIP_Bool crossover /**< perform crossover */
1961 )
1962 { /*lint --e{715}*/
1963 assert(lpi != NULL);
1964 assert(lpi->prob != NULL);
1965 SCIP_UNUSED( crossover );
1966
1967 return SCIPlpiSolveDual(lpi);
1968 }
1969
1970 /** start strong branching - call before any strong branching */
SCIPlpiStartStrongbranch(SCIP_LPI * lpi)1971 SCIP_RETCODE SCIPlpiStartStrongbranch(
1972 SCIP_LPI* lpi /**< LP interface structure */
1973 )
1974 { /*lint --e{715}*/
1975 assert(lpi != NULL);
1976 assert(lpi->prob != NULL);
1977
1978 /* currently do nothing */
1979 return SCIP_OKAY;
1980 }
1981
1982 /** end strong branching - call after any strong branching */
SCIPlpiEndStrongbranch(SCIP_LPI * lpi)1983 SCIP_RETCODE SCIPlpiEndStrongbranch(
1984 SCIP_LPI* lpi /**< LP interface structure */
1985 )
1986 { /*lint --e{715}*/
1987 assert(lpi != NULL);
1988 assert(lpi->prob != NULL);
1989
1990 /* currently do nothing */
1991 return SCIP_OKAY;
1992 }
1993
1994 /** performs strong branching iterations on one @b fractional candidate */
SCIPlpiStrongbranchFrac(SCIP_LPI * lpi,int col,SCIP_Real psol,int itlim,SCIP_Real * down,SCIP_Real * up,SCIP_Bool * downvalid,SCIP_Bool * upvalid,int * iter)1995 SCIP_RETCODE SCIPlpiStrongbranchFrac(
1996 SCIP_LPI* lpi, /**< LP interface structure */
1997 int col, /**< column to apply strong branching on */
1998 SCIP_Real psol, /**< fractional current primal solution value of column */
1999 int itlim, /**< iteration limit for strong branchings */
2000 SCIP_Real* down, /**< stores dual bound after branching column down */
2001 SCIP_Real* up, /**< stores dual bound after branching column up */
2002 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2003 * otherwise, it can only be used as an estimate value */
2004 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2005 * otherwise, it can only be used as an estimate value */
2006 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2007 )
2008 {
2009 int nit;
2010
2011 assert(lpi != NULL);
2012 assert(lpi->prob != NULL);
2013 assert(down != NULL);
2014 assert(up != NULL);
2015 assert(downvalid != NULL);
2016 assert(upvalid != NULL);
2017
2018 SCIPdebugMessage("calling QSopt strong branching on variable %d with fractional value (%d it lim)\n", col, itlim);
2019
2020 /* results of QSopt are valid in any case */
2021 *downvalid = TRUE;
2022 *upvalid = TRUE;
2023
2024 assert( ! EPSISINT(psol, FEASTOL) );
2025
2026 /* call QSopt */
2027 QS_CONDRET( QSopt_strongbranch(lpi->prob, 1, &col, &psol, down, up, itlim, QS_MAXDOUBLE) );
2028
2029 QS_CONDRET( QSget_itcnt(lpi->prob, 0, 0, 0, 0, &nit) );
2030
2031 if( iter )
2032 *iter = nit - lpi->previt;
2033 lpi->previt = nit;
2034
2035 return SCIP_OKAY;
2036 }
2037
2038 /** performs strong branching iterations on given @b fractional candidates */
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)2039 SCIP_RETCODE SCIPlpiStrongbranchesFrac(
2040 SCIP_LPI* lpi, /**< LP interface structure */
2041 int* cols, /**< columns to apply strong branching on */
2042 int ncols, /**< number of columns */
2043 SCIP_Real* psols, /**< fractional current primal solution values of columns */
2044 int itlim, /**< iteration limit for strong branchings */
2045 SCIP_Real* down, /**< stores dual bounds after branching columns down */
2046 SCIP_Real* up, /**< stores dual bounds after branching columns up */
2047 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2048 * otherwise, they can only be used as an estimate values */
2049 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2050 * otherwise, they can only be used as an estimate values */
2051 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2052 )
2053 {
2054 int nit;
2055 int j;
2056
2057 assert(lpi != NULL);
2058 assert(lpi->prob != NULL);
2059 assert(cols != NULL);
2060 assert(psols != NULL);
2061 assert(down != NULL);
2062 assert(up != NULL);
2063 assert(downvalid != NULL);
2064 assert(upvalid != NULL);
2065
2066 SCIPdebugMessage("calling QSopt strong branching on %d variables with fractional value (%d it lim)\n", ncols, itlim);
2067
2068 /* results of QSopt are valid in any case */
2069 for( j = 0; j < ncols; ++j )
2070 {
2071 downvalid[j] = TRUE;
2072 upvalid[j] = TRUE;
2073 assert( ! EPSISINT(psols[j], FEASTOL) );
2074 }
2075
2076 /* call QSopt */
2077 QS_CONDRET( QSopt_strongbranch(lpi->prob, ncols, cols, psols, down, up, itlim, QS_MAXDOUBLE) );
2078
2079 QS_CONDRET( QSget_itcnt(lpi->prob, 0, 0, 0, 0, &nit) );
2080
2081 if( iter )
2082 *iter = nit - lpi->previt;
2083 lpi->previt = nit;
2084
2085 return SCIP_OKAY;
2086 }
2087
2088 /** performs strong branching iterations on one candidate with @b integral value */
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)2089 SCIP_RETCODE SCIPlpiStrongbranchInt(
2090 SCIP_LPI* lpi, /**< LP interface structure */
2091 int col, /**< column to apply strong branching on */
2092 SCIP_Real psol, /**< current integral primal solution value of column */
2093 int itlim, /**< iteration limit for strong branchings */
2094 SCIP_Real* down, /**< stores dual bound after branching column down */
2095 SCIP_Real* up, /**< stores dual bound after branching column up */
2096 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2097 * otherwise, it can only be used as an estimate value */
2098 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2099 * otherwise, it can only be used as an estimate value */
2100 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2101 )
2102 {
2103 SCIP_Real objval;
2104
2105 assert(lpi != NULL);
2106 assert(lpi->prob != NULL);
2107 assert(down != NULL);
2108 assert(up != NULL);
2109 assert(downvalid != NULL);
2110 assert(upvalid != NULL);
2111
2112 SCIPdebugMessage("calling QSopt strong branching on variable %d with integral value (%d it lim)\n", col, itlim);
2113
2114 assert(EPSISINT(psol, FEASTOL));
2115
2116 /* QSopt cannot directly strong branch on integral values! We thus return the current objective
2117 * value for both cases. Could also implement a manual search as in lpi_cpx.c
2118 */
2119 QS_CONDRET( QSget_objval(lpi->prob, &objval) );
2120
2121 *down = objval;
2122 *up = objval;
2123 *downvalid = TRUE;
2124 *upvalid = TRUE;
2125
2126 if( iter )
2127 *iter = 0;
2128
2129 return SCIP_OKAY;
2130 }
2131
2132 /** performs strong branching iterations on given candidates with @b integral values */
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)2133 SCIP_RETCODE SCIPlpiStrongbranchesInt(
2134 SCIP_LPI* lpi, /**< LP interface structure */
2135 int* cols, /**< columns to apply strong branching on */
2136 int ncols, /**< number of columns */
2137 SCIP_Real* psols, /**< current integral primal solution values of columns */
2138 int itlim, /**< iteration limit for strong branchings */
2139 SCIP_Real* down, /**< stores dual bounds after branching columns down */
2140 SCIP_Real* up, /**< stores dual bounds after branching columns up */
2141 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2142 * otherwise, they can only be used as an estimate values */
2143 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2144 * otherwise, they can only be used as an estimate values */
2145 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2146 )
2147 { /*lint --e{715}*/
2148 SCIP_Real objval;
2149 int j;
2150
2151 assert(lpi != NULL);
2152 assert(lpi->prob != NULL);
2153 assert(down != NULL);
2154 assert(up != NULL);
2155 assert(downvalid != NULL);
2156 assert(upvalid != NULL);
2157 SCIP_UNUSED( cols );
2158
2159 SCIPdebugMessage("calling QSopt strong branching on %d variables with integral value (%d it lim)\n", ncols, itlim);
2160
2161 /* QSopt cannot directly strong branch on integral values! We thus return the current objective
2162 * value for all cases. Could also implement a manual search as in lpi_cpx.c. */
2163 QS_CONDRET( QSget_objval(lpi->prob, &objval) );
2164
2165 for( j = 0; j < ncols; ++j )
2166 {
2167 assert(EPSISINT(psols[j], FEASTOL));
2168 down[j] = objval;
2169 up[j] = objval;
2170 downvalid[j] = TRUE;
2171 upvalid[j] = TRUE;
2172 }
2173
2174 if( iter )
2175 *iter = 0;
2176
2177 return SCIP_OKAY;
2178 }
2179 /**@} */
2180
2181
2182
2183
2184 /*
2185 * Solution Information Methods
2186 */
2187
2188 /**@name Solution Information Methods */
2189 /**@{ */
2190
2191 /** returns whether a solve method was called after the last modification of the LP */
SCIPlpiWasSolved(SCIP_LPI * lpi)2192 SCIP_Bool SCIPlpiWasSolved(
2193 SCIP_LPI* lpi /**< LP interface structure */
2194 )
2195 {
2196 assert(lpi!=NULL);
2197 assert(lpi->prob!=NULL);
2198
2199 return (lpi->solstat != 0 && lpi->solstat != QS_LP_MODIFIED);
2200 }
2201
2202 /** gets information about primal and dual feasibility of the current LP solution
2203 *
2204 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
2205 * returns true. If the LP is changed, this information might be invalidated.
2206 *
2207 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
2208 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
2209 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
2210 * the problem might actually be feasible).
2211 */
SCIPlpiGetSolFeasibility(SCIP_LPI * lpi,SCIP_Bool * primalfeasible,SCIP_Bool * dualfeasible)2212 SCIP_RETCODE SCIPlpiGetSolFeasibility(
2213 SCIP_LPI* lpi, /**< LP interface structure */
2214 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
2215 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
2216 )
2217 {
2218 assert(lpi != NULL);
2219 assert(lpi->prob != NULL);
2220 assert(lpi->solstat != 0);
2221 assert(primalfeasible != NULL);
2222 assert(dualfeasible != NULL);
2223
2224 SCIPdebugMessage("getting solution feasibility\n");
2225
2226 if( lpi->solstat == QS_LP_OPTIMAL || (lpi->algo == LPI_QSOPT_ALGO_PRIMAL && lpi->solstat == QS_LP_UNBOUNDED) )
2227 *primalfeasible = TRUE;
2228 else
2229 *primalfeasible = FALSE;
2230
2231 if( lpi->solstat == QS_LP_OPTIMAL || (lpi->algo == LPI_QSOPT_ALGO_DUAL && lpi->solstat == QS_LP_INFEASIBLE) || lpi->solstat == QS_LP_OBJ_LIMIT )
2232 *dualfeasible = TRUE;
2233 else
2234 *dualfeasible = FALSE;
2235
2236 return SCIP_OKAY;
2237 }
2238
2239 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
2240 * this does not necessarily mean, that the solver knows and can return the primal ray
2241 */
SCIPlpiExistsPrimalRay(SCIP_LPI * lpi)2242 SCIP_Bool SCIPlpiExistsPrimalRay(
2243 SCIP_LPI* lpi /**< LP interface structure */
2244 )
2245 {
2246 assert(lpi != NULL);
2247 assert(lpi->prob != NULL);
2248
2249 SCIPdebugMessage("checking primal ray existence\n");
2250
2251 return (lpi->solstat == QS_LP_UNBOUNDED);
2252 }
2253
2254 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
2255 * and the solver knows and can return the primal ray
2256 */
SCIPlpiHasPrimalRay(SCIP_LPI * lpi)2257 SCIP_Bool SCIPlpiHasPrimalRay(
2258 SCIP_LPI* lpi /**< LP interface structure */
2259 )
2260 {
2261 assert(lpi != NULL);
2262 assert(lpi->prob != NULL);
2263
2264 SCIPdebugMessage("checking for primal ray\n");
2265
2266 /* the current version of QSopt cannot give a primal certificate of unboundedness */
2267 return FALSE;
2268 }
2269
2270 /** returns TRUE iff LP is proven to be primal unbounded */
SCIPlpiIsPrimalUnbounded(SCIP_LPI * lpi)2271 SCIP_Bool SCIPlpiIsPrimalUnbounded(
2272 SCIP_LPI* lpi /**< LP interface structure */
2273 )
2274 {
2275 assert(lpi != NULL);
2276 assert(lpi->prob != NULL);
2277
2278 SCIPdebugMessage("checking for primal unboundedness\n");
2279
2280 return (lpi->algo == LPI_QSOPT_ALGO_PRIMAL && lpi->solstat == QS_LP_UNBOUNDED);
2281 }
2282
2283 /** returns TRUE iff LP is proven to be primal infeasible */
SCIPlpiIsPrimalInfeasible(SCIP_LPI * lpi)2284 SCIP_Bool SCIPlpiIsPrimalInfeasible(
2285 SCIP_LPI* lpi /**< LP interface structure */
2286 )
2287 {
2288 assert(lpi != NULL);
2289 assert(lpi->prob != NULL);
2290
2291 SCIPdebugMessage("checking for primal infeasibility\n");
2292
2293 (void) QSget_status(lpi->prob, &(lpi->solstat));
2294
2295 return (lpi->solstat == QS_LP_INFEASIBLE);
2296 }
2297
2298 /** returns TRUE iff LP is proven to be primal feasible */
SCIPlpiIsPrimalFeasible(SCIP_LPI * lpi)2299 SCIP_Bool SCIPlpiIsPrimalFeasible(
2300 SCIP_LPI* lpi /**< LP interface structure */
2301 )
2302 {
2303 assert(lpi != NULL);
2304 assert(lpi->prob != NULL);
2305
2306 SCIPdebugMessage("checking for primal feasibility\n");
2307
2308 return (lpi->solstat == QS_LP_OPTIMAL || lpi->solstat == QS_LP_UNBOUNDED);
2309 }
2310
2311 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
2312 * this does not necessarily mean, that the solver knows and can return the dual ray
2313 */
SCIPlpiExistsDualRay(SCIP_LPI * lpi)2314 SCIP_Bool SCIPlpiExistsDualRay(
2315 SCIP_LPI* lpi /**< LP interface structure */
2316 )
2317 {
2318 assert(lpi != NULL);
2319 assert(lpi->prob != NULL);
2320
2321 SCIPdebugMessage("checking for dual ray availability\n");
2322
2323 return (lpi->algo == LPI_QSOPT_ALGO_DUAL && lpi->solstat == QS_LP_INFEASIBLE);
2324 }
2325
2326 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
2327 * and the solver knows and can return the dual ray
2328 */
SCIPlpiHasDualRay(SCIP_LPI * lpi)2329 SCIP_Bool SCIPlpiHasDualRay(
2330 SCIP_LPI* lpi /**< LP interface structure */
2331 )
2332 {
2333 assert(lpi != NULL);
2334 assert(lpi->prob != NULL);
2335
2336 SCIPdebugMessage("checking for dual ray availability\n");
2337
2338 return (lpi->algo == LPI_QSOPT_ALGO_DUAL && lpi->solstat == QS_LP_INFEASIBLE);
2339 }
2340
2341 /** returns TRUE iff LP is dual unbounded */
SCIPlpiIsDualUnbounded(SCIP_LPI * lpi)2342 SCIP_Bool SCIPlpiIsDualUnbounded(
2343 SCIP_LPI* lpi /**< LP interface structure */
2344 )
2345 {
2346 assert(lpi != NULL);
2347 assert(lpi->prob != NULL);
2348
2349 SCIPdebugMessage("checking for dual unboundedness\n");
2350
2351 return (lpi->algo == LPI_QSOPT_ALGO_DUAL && lpi->solstat == QS_LP_INFEASIBLE);
2352 }
2353
2354 /** returns TRUE iff LP is dual infeasible */
SCIPlpiIsDualInfeasible(SCIP_LPI * lpi)2355 SCIP_Bool SCIPlpiIsDualInfeasible(
2356 SCIP_LPI* lpi /**< LP interface structure */
2357 )
2358 {
2359 assert(lpi != NULL);
2360 assert(lpi->prob != NULL);
2361
2362 SCIPdebugMessage("checking for dual infeasibility\n");
2363
2364 return (lpi->algo == LPI_QSOPT_ALGO_DUAL && lpi->solstat == QS_LP_INFEASIBLE);
2365 }
2366
2367 /** returns TRUE iff LP is proven to be dual feasible */
SCIPlpiIsDualFeasible(SCIP_LPI * lpi)2368 SCIP_Bool SCIPlpiIsDualFeasible(
2369 SCIP_LPI* lpi /**< LP interface structure */
2370 )
2371 {
2372 assert(lpi != NULL);
2373 assert(lpi->prob != NULL);
2374
2375 SCIPdebugMessage("checking for dual feasibility\n");
2376
2377 return ( lpi->solstat == QS_LP_OPTIMAL || (lpi->algo == LPI_QSOPT_ALGO_DUAL && lpi->solstat == QS_LP_INFEASIBLE) || lpi->solstat == QS_LP_OBJ_LIMIT );
2378 }
2379
2380 /** returns TRUE iff LP was solved to optimality */
SCIPlpiIsOptimal(SCIP_LPI * lpi)2381 SCIP_Bool SCIPlpiIsOptimal(
2382 SCIP_LPI* lpi /**< LP interface structure */
2383 )
2384 {
2385 assert(lpi != NULL);
2386 assert(lpi->prob != NULL);
2387
2388 SCIPdebugMessage("checking for optimality\n");
2389
2390 return (lpi->solstat == QS_LP_OPTIMAL);
2391 }
2392
2393 /** returns TRUE iff current LP solution is stable
2394 *
2395 * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
2396 * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
2397 * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
2398 * SCIPlpiIsStable() should return false.
2399 */
SCIPlpiIsStable(SCIP_LPI * lpi)2400 SCIP_Bool SCIPlpiIsStable(
2401 SCIP_LPI* lpi /**< LP interface structure */
2402 )
2403 {
2404 assert(lpi != NULL);
2405 assert(lpi->prob != NULL);
2406
2407 SCIPdebugMessage("checking for numerical stability\n");
2408
2409 return (lpi->solstat != QS_LP_NUMERR);
2410 }
2411
2412 /** returns TRUE iff the objective limit was reached */
SCIPlpiIsObjlimExc(SCIP_LPI * lpi)2413 SCIP_Bool SCIPlpiIsObjlimExc(
2414 SCIP_LPI* lpi /**< LP interface structure */
2415 )
2416 {
2417 assert(lpi != NULL);
2418 assert(lpi->prob != NULL);
2419
2420 SCIPdebugMessage("checking for objective limit exceeded\n");
2421
2422 return (lpi->solstat == QS_LP_OBJ_LIMIT);
2423 }
2424
2425 /** returns TRUE iff the iteration limit was reached */
SCIPlpiIsIterlimExc(SCIP_LPI * lpi)2426 SCIP_Bool SCIPlpiIsIterlimExc(
2427 SCIP_LPI* lpi /**< LP interface structure */
2428 )
2429 {
2430 assert(lpi != NULL);
2431 assert(lpi->prob != NULL);
2432
2433 SCIPdebugMessage("checking for iteration limit exceeded\n");
2434
2435 return (lpi->solstat == QS_LP_ITER_LIMIT);
2436 }
2437
2438 /** returns TRUE iff the time limit was reached */
SCIPlpiIsTimelimExc(SCIP_LPI * lpi)2439 SCIP_Bool SCIPlpiIsTimelimExc(
2440 SCIP_LPI* lpi /**< LP interface structure */
2441 )
2442 {
2443 assert(lpi != NULL);
2444 assert(lpi->prob != NULL);
2445
2446 SCIPdebugMessage("checking for time limit exceeded\n");
2447
2448 return (lpi->solstat == QS_LP_TIME_LIMIT);
2449 }
2450
2451 /** returns the internal solution status of the solver */
SCIPlpiGetInternalStatus(SCIP_LPI * lpi)2452 int SCIPlpiGetInternalStatus(
2453 SCIP_LPI* lpi /**< LP interface structure */
2454 )
2455 {
2456 assert(lpi != NULL);
2457 assert(lpi->prob != NULL);
2458
2459 SCIPdebugMessage("getting internal solution status\n");
2460
2461 return lpi->solstat;
2462 }
2463
2464 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
SCIPlpiIgnoreInstability(SCIP_LPI * lpi,SCIP_Bool * success)2465 SCIP_RETCODE SCIPlpiIgnoreInstability(
2466 SCIP_LPI* lpi, /**< LP interface structure */
2467 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
2468 )
2469 {
2470 assert(lpi != NULL);
2471 assert(lpi->prob != NULL);
2472 assert(success != NULL);
2473
2474 SCIPdebugMessage("ignore instability (will fail)\n");
2475
2476 /* it seems that in QSopt this does not make much sense */
2477 *success = FALSE;
2478
2479 return SCIP_OKAY;
2480 }
2481
2482 /** gets objective value of solution */
SCIPlpiGetObjval(SCIP_LPI * lpi,SCIP_Real * objval)2483 SCIP_RETCODE SCIPlpiGetObjval(
2484 SCIP_LPI* lpi, /**< LP interface structure */
2485 SCIP_Real* objval /**< stores the objective value */
2486 )
2487 {
2488 assert(lpi != NULL);
2489 assert(lpi->prob != NULL);
2490 assert(objval != NULL);
2491
2492 SCIPdebugMessage("getting solution's objective value\n");
2493
2494 QS_CONDRET( QSget_objval(lpi->prob, objval) );
2495
2496 return SCIP_OKAY;
2497 }
2498
2499 /** gets primal and dual solution vectors for feasible LPs
2500 *
2501 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
2502 * SCIPlpiIsOptimal() returns true.
2503 */
SCIPlpiGetSol(SCIP_LPI * lpi,SCIP_Real * objval,SCIP_Real * primsol,SCIP_Real * dualsol,SCIP_Real * activity,SCIP_Real * redcost)2504 SCIP_RETCODE SCIPlpiGetSol(
2505 SCIP_LPI* lpi, /**< LP interface structure */
2506 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
2507 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
2508 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
2509 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
2510 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
2511 )
2512 {
2513 int nrows;
2514 register int i;
2515
2516 assert(lpi != NULL);
2517 assert(lpi->prob != NULL);
2518
2519 SCIPdebugMessage("getting solution\n");
2520
2521 /* Do nothing if the status is not optimal, e.g., if we reached the objective limit or the problem is
2522 * infeasible. QSopt cannot return a solution in this case.*/
2523 if ( lpi->solstat != QS_LP_OPTIMAL )
2524 return SCIP_OKAY;
2525
2526 nrows = QSget_rowcount(lpi->prob);
2527 SCIP_CALL( ensureRowMem(lpi, nrows) );
2528
2529 QS_CONDRET( QSget_solution(lpi->prob, objval, primsol, dualsol, lpi->irng, redcost) );
2530
2531 /* build back the activity */
2532 if( activity )
2533 {
2534 QS_CONDRET( QSget_rhs(lpi->prob, lpi->irhs) );
2535 QS_CONDRET( QSget_senses(lpi->prob, lpi->isen) );
2536
2537 for( i = 0; i < nrows; ++i )
2538 {
2539 switch( lpi->isen[i] )
2540 {
2541 case 'R':
2542 case 'E':
2543 case 'G':
2544 activity[i] = lpi->irhs[i] + lpi->irng[i];
2545 break;
2546 case 'L':
2547 activity[i] = lpi->irhs[i] - lpi->irng[i];
2548 break;
2549 default:
2550 SCIPerrorMessage("unknown sense %c\n", lpi->isen[i]);
2551 SCIPABORT();
2552 return SCIP_INVALIDDATA; /*lint !e527*/
2553 }
2554 }
2555 }
2556
2557 #ifdef SCIP_DISABLED_CODE
2558 {
2559 int stat;
2560 int ncols;
2561 int sense;
2562 char* icstat;
2563 char* irstat;
2564
2565 QSget_status(lpi->prob, &stat);
2566 if( stat == QS_LP_OPTIMAL )
2567 {
2568 QS_CONDRET( QSget_objsense(lpi->prob, &sense) );
2569 ncols = QSget_colcount(lpi->prob);
2570
2571 SCIP_CALL(ensureTabMem(lpi, nrows + ncols));
2572 icstat = lpi->ibas;
2573 irstat = lpi->ibas + ncols;
2574
2575 QS_CONDRET( QSget_basis_array(lpi->prob,icstat, irstat) );
2576
2577 for( i = ncols ; i-- ; )
2578 {
2579 switch( icstat[i] )
2580 {
2581 case QS_COL_BSTAT_BASIC:
2582 case QS_COL_BSTAT_FREE:
2583 if( fabs(redcost[i])> FEASTOL )
2584 {
2585 SCIPerrorMessage("stat col[%d] = %c, rd[%d] = %lg sense %d\n", i, icstat[i], i, redcost[i] * sense, sense);
2586 SCIPABORT();
2587 return SCIP_INVALIDDATA; /*lint !e527*/
2588 }
2589 break;
2590 case QS_COL_BSTAT_UPPER:
2591 if( redcost[i] * sense > FEASTOL )
2592 {
2593 SCIPerrorMessage("stat col[%d] = %c, rd[%d] = %lg sense %d\n", i, icstat[i], i, redcost[i] * sense, sense);
2594 SCIPABORT();
2595 return SCIP_INVALIDDATA; /*lint !e527*/
2596 }
2597 break;
2598 case QS_COL_BSTAT_LOWER:
2599 if( redcost[i] * sense < -FEASTOL )
2600 {
2601 SCIPerrorMessage("stat col[%d] = %c, rd[%d] = %lg sense %d\n", i, icstat[i], i, redcost[i] * sense, sense);
2602 SCIPABORT();
2603 return SCIP_INVALIDDATA; /*lint !e527*/
2604 }
2605 break;
2606 default:
2607 SCIPerrorMessage("unknown stat col[%d] = %c, rd[%d] = %lg\n", i, icstat[i], i, redcost[i] * sense);
2608 SCIPABORT();
2609 return SCIP_INVALIDDATA; /*lint !e527*/
2610 }
2611 }
2612 }
2613 }
2614 #endif
2615
2616 return SCIP_OKAY;
2617 }
2618
2619 /** gets primal ray for unbounded LPs */
SCIPlpiGetPrimalRay(SCIP_LPI * lpi,SCIP_Real * ray)2620 SCIP_RETCODE SCIPlpiGetPrimalRay(
2621 SCIP_LPI* lpi, /**< LP interface structure */
2622 SCIP_Real* ray /**< primal ray */
2623 )
2624 { /*lint --e{715}*/
2625 assert(lpi != NULL);
2626 assert(lpi->prob != NULL);
2627 assert(ray != NULL);
2628
2629 SCIPerrorMessage("SCIPlpiGetPrimalRay() not supported by QSopt.\n");
2630
2631 return SCIP_LPERROR;
2632 }
2633
2634 /** gets dual Farkas proof for infeasibility */
SCIPlpiGetDualfarkas(SCIP_LPI * lpi,SCIP_Real * dualfarkas)2635 SCIP_RETCODE SCIPlpiGetDualfarkas(
2636 SCIP_LPI* lpi, /**< LP interface structure */
2637 SCIP_Real* dualfarkas /**< dual Farkas row multipliers */
2638 )
2639 {
2640 assert(lpi != NULL);
2641 assert(lpi->prob != NULL);
2642 assert(dualfarkas != NULL);
2643
2644 SCIPdebugMessage("calling QSopt dual Farkas: %d cols, %d rows, %d non zeros\n", QSget_colcount (lpi->prob),
2645 QSget_rowcount(lpi->prob), QSget_nzcount(lpi->prob));
2646
2647 QS_CONDRET( QSget_infeas_array(lpi->prob, dualfarkas) );
2648
2649 return SCIP_OKAY;
2650 }
2651
2652 /** gets the number of LP iterations of the last solve call */
SCIPlpiGetIterations(SCIP_LPI * lpi,int * iterations)2653 SCIP_RETCODE SCIPlpiGetIterations(
2654 SCIP_LPI* lpi, /**< LP interface structure */
2655 int* iterations /**< pointer to store the number of iterations of the last solve call */
2656 )
2657 {
2658 int nit;
2659
2660 assert(lpi != NULL);
2661 assert(lpi->prob != NULL);
2662 assert(iterations != NULL);
2663
2664 QS_CONDRET( QSget_itcnt(lpi->prob, 0, 0, 0, 0, &nit) );
2665
2666 *iterations = nit - lpi->previt;
2667 lpi->previt = nit;
2668
2669 return SCIP_OKAY;
2670 }
2671
2672 /** gets information about the quality of an LP solution
2673 *
2674 * Such information is usually only available, if also a (maybe not optimal) solution is available.
2675 * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
2676 */
SCIPlpiGetRealSolQuality(SCIP_LPI * lpi,SCIP_LPSOLQUALITY qualityindicator,SCIP_Real * quality)2677 SCIP_RETCODE SCIPlpiGetRealSolQuality(
2678 SCIP_LPI* lpi, /**< LP interface structure */
2679 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
2680 SCIP_Real* quality /**< pointer to store quality number */
2681 )
2682 { /*lint --e{715}*/
2683 assert(lpi != NULL);
2684 assert(quality != NULL);
2685 SCIP_UNUSED( qualityindicator );
2686
2687 *quality = SCIP_INVALID;
2688
2689 return SCIP_OKAY;
2690 }
2691
2692 /**@} */
2693
2694
2695
2696
2697 /*
2698 * LP Basis Methods
2699 */
2700
2701 /**@name LP Basis Methods */
2702 /**@{ */
2703
2704 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
SCIPlpiGetBase(SCIP_LPI * lpi,int * cstat,int * rstat)2705 SCIP_RETCODE SCIPlpiGetBase(
2706 SCIP_LPI* lpi, /**< LP interface structure */
2707 int* cstat, /**< array to store column basis status, or NULL */
2708 int* rstat /**< array to store row basis status, or NULL */
2709 )
2710 {
2711 int ncols;
2712 int nrows;
2713 char* icstat;
2714 char* irstat;
2715 register int i;
2716
2717 assert(lpi != NULL);
2718 assert(lpi->prob != NULL);
2719
2720 SCIPdebugMessage("saving QSopt basis into %p/%p\n", (void*)cstat, (void*)rstat);
2721
2722 ncols = QSget_colcount(lpi->prob);
2723 nrows = QSget_rowcount(lpi->prob);
2724
2725 SCIP_CALL( ensureTabMem(lpi, nrows + ncols) );
2726 SCIP_CALL( ensureRowMem(lpi, nrows) );
2727
2728 /* get senses */
2729 QS_CONDRET( QSget_senses(lpi->prob, lpi->isen) );
2730
2731 /* get basis */
2732 icstat = lpi->ibas;
2733 irstat = lpi->ibas + ncols;
2734 QS_CONDRET( QSget_basis_array(lpi->prob, icstat, irstat) );
2735
2736 /* Now we must transform QSopt codes into SCIP codes.
2737 * We have the following cases:
2738 * 'G': b <= ax -> b = ax - s, s >= 0
2739 * 'L': ax <= b -> b = ax + s, s >= 0
2740 * 'R': b <= ax <= c -> c - b = ax + s, 0 <= s <= c - b
2741 */
2742 for( i = 0; i < nrows; ++i )
2743 {
2744 switch( irstat[i] )
2745 {
2746 case QS_ROW_BSTAT_LOWER:
2747 if ( lpi->isen[i] == 'L' )
2748 rstat[i] = (char) SCIP_BASESTAT_UPPER;
2749 else
2750 rstat[i] = (char) SCIP_BASESTAT_LOWER;
2751 break;
2752 case QS_ROW_BSTAT_BASIC:
2753 rstat[i] = (char) SCIP_BASESTAT_BASIC;
2754 break;
2755 case QS_ROW_BSTAT_UPPER:
2756 rstat[i] = (char) SCIP_BASESTAT_UPPER;
2757 break;
2758 default:
2759 SCIPerrorMessage("Unknown row basic status %c", rstat[i]);
2760 SCIPABORT();
2761 return SCIP_INVALIDDATA; /*lint !e527*/
2762 }
2763 }
2764 for( i = 0; i < ncols; ++i )
2765 {
2766 switch( icstat[i] )
2767 {
2768 case QS_COL_BSTAT_LOWER:
2769 cstat[i] = (char) SCIP_BASESTAT_LOWER;
2770 break;
2771 case QS_COL_BSTAT_BASIC:
2772 cstat[i] = (char) SCIP_BASESTAT_BASIC;
2773 break;
2774 case QS_COL_BSTAT_UPPER:
2775 cstat[i] = (char) SCIP_BASESTAT_UPPER;
2776 break;
2777 case QS_COL_BSTAT_FREE:
2778 cstat[i] = (char) SCIP_BASESTAT_ZERO;
2779 break;
2780 default:
2781 SCIPerrorMessage("Unknown column basic status %c", cstat[i]);
2782 SCIPABORT();
2783 return SCIP_INVALIDDATA; /*lint !e527*/
2784 }
2785 }
2786 return SCIP_OKAY;
2787 }
2788
2789 /** sets current basis status for columns and rows */
SCIPlpiSetBase(SCIP_LPI * lpi,const int * cstat,const int * rstat)2790 SCIP_RETCODE SCIPlpiSetBase(
2791 SCIP_LPI* lpi, /**< LP interface structure */
2792 const int* cstat, /**< array with column basis status */
2793 const int* rstat /**< array with row basis status */
2794 )
2795 {
2796 int ncols;
2797 int nrows;
2798 register int i;
2799 char* icstat;
2800 char* irstat;
2801
2802 assert(lpi != NULL);
2803 assert(lpi->prob != NULL);
2804
2805 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
2806 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
2807
2808 assert(cstat != NULL || ncols == 0);
2809 assert(rstat != NULL || nrows == 0);
2810
2811 SCIPdebugMessage("loading basis %p/%p into QSopt\n", (void*)cstat, (void*)rstat);
2812
2813 SCIP_CALL( ensureTabMem(lpi, ncols) );
2814 SCIP_CALL( ensureRowMem(lpi, nrows) );
2815
2816 /* get senses */
2817 QS_CONDRET( QSget_senses(lpi->prob, lpi->isen) );
2818
2819 icstat = lpi->ibas;
2820 irstat = lpi->ibas + ncols;
2821
2822 /* now we must transform QSopt codes into SCIP codes */
2823 for( i = 0; i < nrows; ++i )
2824 {
2825 switch( rstat[i] ) /*lint !e613*/
2826 {
2827 case SCIP_BASESTAT_LOWER:
2828 irstat[i] = QS_ROW_BSTAT_LOWER;
2829 break;
2830 case SCIP_BASESTAT_BASIC:
2831 irstat[i] = QS_ROW_BSTAT_BASIC;
2832 break;
2833 case SCIP_BASESTAT_UPPER:
2834 if ( lpi->isen[i] == 'L' )
2835 irstat[i] = QS_ROW_BSTAT_LOWER;
2836 else
2837 irstat[i] = QS_ROW_BSTAT_UPPER;
2838 break;
2839 default:
2840 SCIPerrorMessage("Unknown row basic status %d", rstat[i]); /*lint !e613*/
2841 SCIPABORT();
2842 return SCIP_INVALIDDATA; /*lint !e527*/
2843 }
2844 }
2845 for( i = 0; i < ncols; ++i )
2846 {
2847 switch( cstat[i] ) /*lint !e613*/
2848 {
2849 case SCIP_BASESTAT_LOWER:
2850 icstat[i] = QS_COL_BSTAT_LOWER;
2851 break;
2852 case SCIP_BASESTAT_BASIC:
2853 icstat[i] = QS_COL_BSTAT_BASIC;
2854 break;
2855 case SCIP_BASESTAT_UPPER:
2856 icstat[i] = QS_COL_BSTAT_UPPER;
2857 break;
2858 case SCIP_BASESTAT_ZERO:
2859 icstat[i] = QS_COL_BSTAT_FREE;
2860 break;
2861 default:
2862 SCIPerrorMessage("Unknown column basic status %d", cstat[i]); /*lint !e613*/
2863 SCIPABORT();
2864 return SCIP_INVALIDDATA; /*lint !e527*/
2865 }
2866 }
2867
2868 /* set the basis */
2869 QS_CONDRET( QSload_basis_array(lpi->prob, icstat, irstat) );
2870
2871 return SCIP_OKAY;
2872 }
2873
2874 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
SCIPlpiGetBasisInd(SCIP_LPI * lpi,int * bind)2875 SCIP_RETCODE SCIPlpiGetBasisInd(
2876 SCIP_LPI* lpi, /**< LP interface structure */
2877 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
2878 )
2879 {
2880 int nrows;
2881 int ncols;
2882 int stat;
2883 register int i;
2884
2885 assert(lpi!=NULL);
2886 assert(lpi->prob!=NULL);
2887 assert(bind != NULL);
2888
2889 SCIPdebugMessage("getting basis information\n");
2890
2891 nrows = QSget_rowcount(lpi->prob);
2892 ncols = QSget_colcount(lpi->prob);
2893
2894 QS_CONDRET( QSget_status(lpi->prob, &stat) );
2895 if ( stat == QS_LP_UNSOLVED || stat == QS_LP_MODIFIED || stat == QS_LP_NUMERR )
2896 {
2897 QS_CONDRET( QSopt_dual(lpi->prob, &(lpi->solstat)) );
2898 }
2899
2900 QS_CONDRET( QSget_basis_order(lpi->prob, bind) );
2901
2902 /* transform QSopt basis header into SCIP format */
2903 for( i = 0; i < nrows; ++i )
2904 {
2905 if( bind[i] >= ncols )
2906 bind[i] = -(bind[i] - ncols) - 1;
2907 }
2908
2909 return SCIP_OKAY;
2910 }
2911
2912 /** get row of inverse basis matrix B^-1
2913 *
2914 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2915 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2916 * see also the explanation in lpi.h.
2917 *
2918 * @todo check that the result is in terms of the LP interface definition
2919 */
SCIPlpiGetBInvRow(SCIP_LPI * lpi,int r,SCIP_Real * coef,int * inds,int * ninds)2920 SCIP_RETCODE SCIPlpiGetBInvRow(
2921 SCIP_LPI* lpi, /**< LP interface structure */
2922 int r, /**< row number */
2923 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
2924 int* inds, /**< array to store the non-zero indices, or NULL */
2925 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2926 * (-1: if we do not store sparsity information) */
2927 )
2928 { /*lint --e{715} */
2929 int nrows;
2930 int i;
2931
2932 assert(lpi!=NULL);
2933 assert(lpi->prob!=NULL);
2934 assert(coef != NULL);
2935 SCIP_UNUSED( inds );
2936
2937 nrows = QSget_rowcount(lpi->prob);
2938 assert( 0 <= r && r < nrows );
2939
2940 SCIPdebugMessage("getting binv-row %d from Qsopt %d cols, %d rows, %d nonz\n", r, QSget_colcount(lpi->prob),
2941 QSget_rowcount(lpi->prob), QSget_nzcount(lpi->prob));
2942
2943 /* can only return dense result */
2944 if ( ninds != NULL )
2945 *ninds = -1;
2946
2947 QS_CONDRET( QSget_binv_row(lpi->prob, r, coef) );
2948
2949 for (i = 0; i < nrows; i++)
2950 coef[i] *= -1.0;
2951
2952 return SCIP_OKAY;
2953 }
2954
2955 /** get column of inverse basis matrix B^-1
2956 *
2957 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2958 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2959 * see also the explanation in lpi.h.
2960 *
2961 * @todo check that the result is in terms of the LP interface definition
2962 */
SCIPlpiGetBInvCol(SCIP_LPI * lpi,int c,SCIP_Real * coef,int * inds,int * ninds)2963 SCIP_RETCODE SCIPlpiGetBInvCol(
2964 SCIP_LPI* lpi, /**< LP interface structure */
2965 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
2966 * you have to call SCIPlpiGetBasisInd() to get the array which links the
2967 * B^-1 column numbers to the row and column numbers of the LP!
2968 * c must be between 0 and nrows-1, since the basis has the size
2969 * nrows * nrows */
2970 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
2971 int* inds, /**< array to store the non-zero indices, or NULL */
2972 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2973 * (-1: if we do not store sparsity information) */
2974 )
2975 { /*lint --e{715} */
2976 assert(lpi!=NULL);
2977 assert(lpi->prob!=NULL);
2978 assert(coef != NULL);
2979 SCIP_UNUSED( c );
2980 SCIP_UNUSED( inds );
2981 SCIP_UNUSED( ninds );
2982
2983 SCIPerrorMessage("SCIPlpiGetBInvCol() not supported by QSopt.\n");
2984
2985 /* QSopt does not provide an interface for this yet */
2986 return SCIP_LPERROR;
2987 }
2988
2989 /** get row of inverse basis matrix times constraint matrix B^-1 * A
2990 *
2991 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2992 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2993 * see also the explanation in lpi.h.
2994 *
2995 * @todo check that the result is in terms of the LP interface definition
2996 */
SCIPlpiGetBInvARow(SCIP_LPI * lpi,int r,const SCIP_Real * binvrow,SCIP_Real * coef,int * inds,int * ninds)2997 SCIP_RETCODE SCIPlpiGetBInvARow(
2998 SCIP_LPI* lpi, /**< LP interface structure */
2999 int r, /**< row number */
3000 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
3001 SCIP_Real* coef, /**< vector to return coefficients of the row */
3002 int* inds, /**< array to store the non-zero indices, or NULL */
3003 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3004 * (-1: if we do not store sparsity information) */
3005 )
3006 { /*lint --e{715} */
3007 int ncols;
3008 int nrows;
3009 int i;
3010
3011 assert(lpi != NULL);
3012 assert(lpi->prob != NULL);
3013 assert(coef != NULL);
3014 SCIP_UNUSED( binvrow );
3015 SCIP_UNUSED( inds );
3016
3017 SCIPdebugMessage("getting binva-row %d\n", r);
3018
3019 /* can only return dense result */
3020 if ( ninds != NULL )
3021 *ninds = -1;
3022
3023 ncols = QSget_colcount(lpi->prob);
3024 nrows = QSget_rowcount(lpi->prob);
3025
3026 SCIP_CALL( ensureTabMem(lpi, nrows + ncols) );
3027
3028 QS_CONDRET( QSget_tableau_row(lpi->prob, r, lpi->itab) );
3029
3030 /* copy local information to the outside */
3031 BMScopyMemoryArray(coef, lpi->itab, ncols);
3032
3033 for (i = 0; i < ncols; ++i)
3034 coef[i] *= -1.0;
3035
3036 return SCIP_OKAY;
3037 }
3038
3039 /** get column of inverse basis matrix times constraint matrix B^-1 * A
3040 *
3041 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3042 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3043 * see also the explanation in lpi.h.
3044 *
3045 * @todo check that the result is in terms of the LP interface definition
3046 */
SCIPlpiGetBInvACol(SCIP_LPI * lpi,int c,SCIP_Real * coef,int * inds,int * ninds)3047 SCIP_RETCODE SCIPlpiGetBInvACol(
3048 SCIP_LPI* lpi, /**< LP interface structure */
3049 int c, /**< column number */
3050 SCIP_Real* coef, /**< vector to return coefficients of the column */
3051 int* inds, /**< array to store the non-zero indices, or NULL */
3052 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3053 * (-1: if we do not store sparsity information) */
3054 )
3055 { /*lint --e{715} */
3056 assert(lpi!=NULL);
3057 assert(lpi->prob!=NULL);
3058 assert(coef != NULL);
3059 assert(c >= 0);
3060 SCIP_UNUSED( inds );
3061 SCIP_UNUSED( ninds );
3062
3063 SCIPerrorMessage("SCIPlpiGetBInvACol() not supported by QSopt.\n");
3064
3065 /* QSopt does not provide an interface for this yet */
3066 return SCIP_LPERROR;
3067 }
3068
3069 /**@} */
3070
3071
3072
3073
3074 /*
3075 * LP State Methods
3076 */
3077
3078 /**@name LP State Methods */
3079 /**@{ */
3080
3081 /** stores LPi state (like basis information) into lpistate object */
SCIPlpiGetState(SCIP_LPI * lpi,BMS_BLKMEM * blkmem,SCIP_LPISTATE ** lpistate)3082 SCIP_RETCODE SCIPlpiGetState(
3083 SCIP_LPI* lpi, /**< LP interface structure */
3084 BMS_BLKMEM* blkmem, /**< block memory */
3085 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3086 )
3087 {
3088 int ncols, nrows;
3089
3090 assert(lpi != NULL);
3091 assert(lpi->prob != NULL);
3092 assert(blkmem != NULL);
3093 assert(lpistate != NULL);
3094
3095 ncols = QSget_colcount(lpi->prob);
3096 nrows = QSget_rowcount(lpi->prob);
3097
3098 assert(ncols >= 0);
3099 assert(nrows >= 0);
3100
3101 /* allocate lpistate data */
3102 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows));
3103 SCIPdebugMessage("storing QSopt LPI state in %p (%d cols, %d rows)\n", (void*)*lpistate, ncols, nrows);
3104
3105 /* get unpacked basis information from QSopt */
3106 SCIP_CALL( ensureColMem(lpi, ncols) );
3107 SCIP_CALL( ensureRowMem(lpi, nrows) );
3108 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->iccnt, lpi->ircnt) );
3109
3110 /* pack LPi state data */
3111 (*lpistate)->ncols = ncols;
3112 (*lpistate)->nrows = nrows;
3113 lpistatePack(*lpistate, lpi->iccnt, lpi->ircnt);
3114
3115 return SCIP_OKAY;
3116 }
3117
3118 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
3119 * columns and rows since the state was stored with SCIPlpiGetState()
3120 */
SCIPlpiSetState(SCIP_LPI * lpi,BMS_BLKMEM * blkmem,const SCIP_LPISTATE * lpistate)3121 SCIP_RETCODE SCIPlpiSetState(
3122 SCIP_LPI* lpi, /**< LP interface structure */
3123 BMS_BLKMEM* blkmem, /**< block memory */
3124 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
3125 )
3126 { /*lint --e{715} */
3127 char* icstat;
3128 char* irstat;
3129 int i;
3130 int ncols;
3131 int nrows;
3132
3133 assert(lpi != NULL);
3134 assert(lpi->prob != NULL);
3135 assert(blkmem != NULL);
3136
3137 /* if there was no basis information available, LPI state was not stored */
3138 if( lpistate == NULL )
3139 return SCIP_OKAY;
3140
3141 /* continue test */
3142 ncols = QSget_colcount(lpi->prob);
3143 nrows = QSget_rowcount(lpi->prob);
3144
3145 assert(ncols >= 0);
3146 assert(nrows >= 0);
3147 assert(lpistate->ncols <= ncols);
3148 assert(lpistate->nrows <= nrows);
3149
3150 SCIPdebugMessage("loading LPI state %p (%d cols, %d rows) into QSopt LP with %d cols and %d rows\n", (void*)lpistate, lpistate->ncols,
3151 lpistate->nrows, ncols, nrows);
3152
3153 if( lpistate->ncols == 0 || lpistate->nrows == 0 )
3154 return SCIP_OKAY;
3155
3156 /* allocate enough memory for storing uncompressed basis information */
3157 SCIP_CALL( ensureColMem(lpi, ncols) );
3158 SCIP_CALL( ensureRowMem(lpi, nrows) );
3159 SCIP_CALL( ensureTabMem(lpi, nrows + ncols) );
3160
3161 icstat = lpi->ibas;
3162 irstat = lpi->ibas + ncols;
3163
3164 /* get senses */
3165 QS_CONDRET( QSget_senses(lpi->prob, lpi->isen) );
3166
3167 /* unpack LPi state data */
3168 lpistateUnpack(lpistate, lpi->iccnt, lpi->ircnt);
3169
3170 /* extend the basis to the current LP beyond the previously existing columns */
3171 for( i = lpistate->ncols; i < ncols; ++i )
3172 {
3173 SCIP_Real lb;
3174 SCIP_Real ub;
3175
3176 /* get bounds from qsopt */
3177 QS_CONDRET( QSget_bounds_list(lpi->prob, 1, &i, &lb, &ub) );
3178 if ( SCIPlpiIsInfinity(lpi, REALABS(lb)) )
3179 {
3180 /* if lower bound is +/- infinity -> try upper bound */
3181 if ( SCIPlpiIsInfinity(lpi, REALABS(ub)) )
3182 lpi->iccnt[i] = (int) SCIP_BASESTAT_ZERO; /* variable is free */
3183 else
3184 lpi->iccnt[i] = (int) SCIP_BASESTAT_UPPER; /* use finite upper bound */
3185 }
3186 else
3187 lpi->iccnt[i] = (int) SCIP_BASESTAT_LOWER; /* use finite lower bound */
3188 }
3189 for( i = lpistate->nrows; i < nrows; ++i ) /*lint !e850*/
3190 lpi->ircnt[i] = (int) SCIP_BASESTAT_BASIC;
3191
3192 /* convert the loaded basis into QSopt format */
3193 for( i = 0; i < nrows; ++i )
3194 {
3195 switch( lpi->ircnt[i] )
3196 {
3197 case SCIP_BASESTAT_LOWER:
3198 irstat[i] = QS_ROW_BSTAT_LOWER;
3199 break;
3200 case SCIP_BASESTAT_BASIC:
3201 irstat[i] = QS_ROW_BSTAT_BASIC;
3202 break;
3203 case SCIP_BASESTAT_UPPER:
3204 if ( lpi->isen[i] == 'L' )
3205 irstat[i] = QS_ROW_BSTAT_LOWER;
3206 else
3207 irstat[i] = QS_ROW_BSTAT_UPPER;
3208 break;
3209 default:
3210 SCIPerrorMessage("Unknown row basic status %d", lpi->ircnt[i]);
3211 SCIPABORT();
3212 return SCIP_INVALIDDATA; /*lint !e527*/
3213 }
3214 }
3215
3216 for( i = 0; i < ncols; ++i )
3217 {
3218 switch( lpi->iccnt[i] )
3219 {
3220 case SCIP_BASESTAT_LOWER:
3221 icstat[i] = QS_COL_BSTAT_LOWER;
3222 break;
3223 case SCIP_BASESTAT_BASIC:
3224 icstat[i] = QS_COL_BSTAT_BASIC;
3225 break;
3226 case SCIP_BASESTAT_UPPER:
3227 icstat[i] = QS_COL_BSTAT_UPPER;
3228 break;
3229 case SCIP_BASESTAT_ZERO:
3230 icstat[i] = QS_COL_BSTAT_FREE;
3231 break;
3232 default:
3233 SCIPerrorMessage("Unknown column basic status %d", lpi->iccnt[i]);
3234 SCIPABORT();
3235 return SCIP_INVALIDDATA; /*lint !e527*/
3236 }
3237 }
3238
3239 /* set the basis */
3240 QS_CONDRET( QSload_basis_array(lpi->prob, icstat, irstat) );
3241
3242 return SCIP_OKAY;
3243 }
3244
3245 /** clears current LPi state (like basis information) of the solver */
SCIPlpiClearState(SCIP_LPI * lpi)3246 SCIP_RETCODE SCIPlpiClearState(
3247 SCIP_LPI* lpi /**< LP interface structure */
3248 )
3249 {
3250 int ncols;
3251 int nrows;
3252 int* cstat;
3253 int* rstat;
3254 int i;
3255
3256 assert( lpi != NULL );
3257 assert( lpi->prob != NULL );
3258
3259 SCIPdebugMessage("SCIPlpiClearState()\n");
3260
3261 ncols = QSget_colcount(lpi->prob);
3262 nrows = QSget_rowcount(lpi->prob);
3263
3264 if ( ncols == 0 || nrows == 0 )
3265 return SCIP_OKAY;
3266
3267 SCIP_ALLOC( BMSallocMemoryArray(&cstat, ncols) );
3268 SCIP_ALLOC( BMSallocMemoryArray(&rstat, nrows) );
3269
3270 for (i = 0; i < ncols; ++i)
3271 cstat[i] = (char) SCIP_BASESTAT_LOWER;
3272 for (i = 0; i < nrows; ++i)
3273 rstat[i] = (char) SCIP_BASESTAT_BASIC;
3274
3275 SCIP_CALL( SCIPlpiSetBase(lpi, cstat, rstat) );
3276
3277 BMSfreeMemoryArray(&cstat);
3278 BMSfreeMemoryArray(&rstat);
3279
3280 return SCIP_OKAY;
3281 }
3282
3283 /** frees LPi state information */
SCIPlpiFreeState(SCIP_LPI * lpi,BMS_BLKMEM * blkmem,SCIP_LPISTATE ** lpistate)3284 SCIP_RETCODE SCIPlpiFreeState(
3285 SCIP_LPI* lpi, /**< LP interface structure */
3286 BMS_BLKMEM* blkmem, /**< block memory */
3287 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3288 )
3289 {
3290 assert(lpi != NULL);
3291 assert(lpistate != NULL);
3292 assert(blkmem != NULL);
3293
3294 if( *lpistate != NULL )
3295 lpistateFree(lpistate, blkmem);
3296
3297 return SCIP_OKAY;
3298 }
3299
3300 /** checks, whether the given LP state contains simplex basis information */
SCIPlpiHasStateBasis(SCIP_LPI * lpi,SCIP_LPISTATE * lpistate)3301 SCIP_Bool SCIPlpiHasStateBasis(
3302 SCIP_LPI* lpi, /**< LP interface structure */
3303 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
3304 )
3305 { /*lint --e{715} */
3306 assert(lpi != NULL);
3307 return (lpistate != NULL);
3308 }
3309
3310 /** reads LP state (like basis information from a file */
SCIPlpiReadState(SCIP_LPI * lpi,const char * fname)3311 SCIP_RETCODE SCIPlpiReadState(
3312 SCIP_LPI* lpi, /**< LP interface structure */
3313 const char* fname /**< file name */
3314 )
3315 {
3316 int rval;
3317
3318 assert(lpi != NULL);
3319 assert(lpi->prob != NULL);
3320 assert(fname != NULL);
3321
3322 SCIPdebugMessage("reading QSopt LP state from file <%s>\n", fname);
3323
3324 rval = QSread_and_load_basis(lpi->prob, fname);
3325 if( rval )
3326 {
3327 SCIPerrorMessage("Error while loading basis from file <%s>.\n", fname);
3328 return SCIP_READERROR;
3329 }
3330
3331 return SCIP_OKAY;
3332 }
3333
3334 /** writes LPi state (i.e. basis information) to a file */
SCIPlpiWriteState(SCIP_LPI * lpi,const char * fname)3335 SCIP_RETCODE SCIPlpiWriteState(
3336 SCIP_LPI* lpi, /**< LP interface structure */
3337 const char* fname /**< file name */
3338 )
3339 {
3340 QSbas bas;
3341 int rval;
3342
3343 assert(lpi != NULL);
3344 assert(lpi->prob != NULL);
3345 assert(fname != NULL);
3346
3347 SCIPdebugMessage("writing QSopt LP state to file <%s>\n", fname);
3348
3349 bas = QSget_basis(lpi->prob);
3350 QS_ERROR(bas == 0, "Could not get basis from problem."); /*lint !e820*/
3351 assert(bas);
3352
3353 rval = QSwrite_basis(lpi->prob, bas, fname);
3354 QSfree(bas);
3355 if( rval )
3356 {
3357 SCIPerrorMessage("Could not write basis to file <%s>.\n", fname);
3358 return SCIP_WRITEERROR;
3359 }
3360
3361 return SCIP_OKAY;
3362 }
3363
3364 /**@} */
3365
3366
3367
3368
3369 /*
3370 * LP Pricing Norms Methods
3371 */
3372
3373 /**@name LP Pricing Norms Methods */
3374 /**@{ */
3375
3376 /** stores LPi pricing norms information
3377 * @todo should we store norm information?
3378 */
SCIPlpiGetNorms(SCIP_LPI * lpi,BMS_BLKMEM * blkmem,SCIP_LPINORMS ** lpinorms)3379 SCIP_RETCODE SCIPlpiGetNorms(
3380 SCIP_LPI* lpi, /**< LP interface structure */
3381 BMS_BLKMEM* blkmem, /**< block memory */
3382 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
3383 )
3384 { /*lint --e{715} */
3385 int ncols;
3386 int nrows;
3387
3388 assert( lpi != NULL );
3389 assert( lpi->prob != NULL );
3390 assert( lpinorms != NULL );
3391 assert( blkmem != NULL );
3392
3393 ncols = QSget_colcount(lpi->prob);
3394 nrows = QSget_rowcount(lpi->prob);
3395
3396 /* allocate lpinorms data */
3397 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
3398 (*lpinorms)->ncols = ncols;
3399 (*lpinorms)->nrows = nrows;
3400
3401 if ( QStest_row_norms(lpi->prob) )
3402 {
3403 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->cstat, ncols) );
3404 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->rstat, nrows) );
3405 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows) );
3406
3407 QS_CONDRET( QSget_basis_and_row_norms_array(lpi->prob, (*lpinorms)->cstat, (*lpinorms)->rstat, (*lpinorms)->norms) );
3408 }
3409 else
3410 {
3411 (*lpinorms)->cstat = NULL;
3412 (*lpinorms)->rstat = NULL;
3413 (*lpinorms)->norms = NULL;
3414 }
3415
3416 return SCIP_OKAY;
3417 }
3418
3419 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
3420 * columns and rows since the state was stored with SCIPlpiGetNorms()
3421 */
SCIPlpiSetNorms(SCIP_LPI * lpi,BMS_BLKMEM * blkmem,const SCIP_LPINORMS * lpinorms)3422 SCIP_RETCODE SCIPlpiSetNorms(
3423 SCIP_LPI* lpi, /**< LP interface structure */
3424 BMS_BLKMEM* blkmem, /**< block memory */
3425 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
3426 )
3427 { /*lint --e{715} */
3428 int ncols;
3429 int nrows;
3430
3431 assert( lpi != NULL );
3432 assert( lpi->prob != NULL );
3433 SCIP_UNUSED( blkmem );
3434
3435 if ( lpinorms->norms == NULL )
3436 return SCIP_OKAY;
3437
3438 ncols = QSget_colcount(lpi->prob);
3439 nrows = QSget_rowcount(lpi->prob);
3440 if ( nrows != lpinorms->nrows || ncols != lpinorms->ncols )
3441 return SCIP_OKAY;
3442
3443 /* load row norms */
3444 assert( lpinorms->cstat != NULL && lpinorms->rstat != NULL && lpinorms->norms != NULL );
3445 QS_CONDRET( QSload_basis_and_row_norms_array(lpi->prob, lpinorms->cstat, lpinorms->rstat, lpinorms->norms) );
3446
3447 return SCIP_OKAY;
3448 }
3449
3450 /** frees pricing norms information */
SCIPlpiFreeNorms(SCIP_LPI * lpi,BMS_BLKMEM * blkmem,SCIP_LPINORMS ** lpinorms)3451 SCIP_RETCODE SCIPlpiFreeNorms(
3452 SCIP_LPI* lpi, /**< LP interface structure */
3453 BMS_BLKMEM* blkmem, /**< block memory */
3454 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
3455 )
3456 { /*lint --e{715} */
3457 assert( lpinorms != NULL );
3458 assert( lpi != NULL );
3459
3460 if ( (*lpinorms)->norms != NULL )
3461 {
3462 assert( (*lpinorms)->cstat != NULL && (*lpinorms)->rstat != NULL );
3463 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows);
3464 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->rstat, (*lpinorms)->nrows);
3465 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->cstat, (*lpinorms)->ncols);
3466 }
3467 BMSfreeBlockMemory(blkmem, lpinorms);
3468
3469 return SCIP_OKAY;
3470 }
3471
3472 /**@} */
3473
3474
3475
3476
3477 /*
3478 * Parameter Methods
3479 */
3480
3481 /**@name Parameter Methods */
3482 /**@{ */
3483
3484 /** gets integer parameter of LP */
SCIPlpiGetIntpar(SCIP_LPI * lpi,SCIP_LPPARAM type,int * ival)3485 SCIP_RETCODE SCIPlpiGetIntpar(
3486 SCIP_LPI* lpi, /**< LP interface structure */
3487 SCIP_LPPARAM type, /**< parameter number */
3488 int* ival /**< buffer to store the parameter value */
3489 )
3490 {
3491 assert(lpi != NULL);
3492 assert(lpi->prob != NULL);
3493 assert(ival != NULL);
3494
3495 SCIPdebugMessage("getting int parameter %d\n", type);
3496
3497 switch( type )
3498 {
3499 case SCIP_LPPAR_FROMSCRATCH:
3500 case SCIP_LPPAR_FASTMIP:
3501 case SCIP_LPPAR_PRESOLVING:
3502 return SCIP_PARAMETERUNKNOWN;
3503 case SCIP_LPPAR_SCALING:
3504 QS_CONDRET( QSget_param(lpi->prob, QS_PARAM_SIMPLEX_SCALING, ival) );
3505 assert((*ival) == 0 || (*ival) == 1);
3506
3507 break;
3508 case SCIP_LPPAR_PRICING:
3509 *ival = lpi->pricing;
3510 break;
3511 case SCIP_LPPAR_LPINFO:
3512 QS_CONDRET( QSget_param(lpi->prob, QS_PARAM_SIMPLEX_DISPLAY, ival) );
3513 if( *ival )
3514 *ival = TRUE;
3515 else
3516 *ival = FALSE;
3517 break;
3518 case SCIP_LPPAR_LPITLIM:
3519 QS_CONDRET( QSget_param(lpi->prob, QS_PARAM_SIMPLEX_MAX_ITERATIONS, ival) );
3520 break;
3521 default:
3522 return SCIP_PARAMETERUNKNOWN;
3523 } /*lint !e788*/
3524
3525 return SCIP_OKAY;
3526 }
3527
3528 /** sets integer parameter of LP */
SCIPlpiSetIntpar(SCIP_LPI * lpi,SCIP_LPPARAM type,int ival)3529 SCIP_RETCODE SCIPlpiSetIntpar(
3530 SCIP_LPI* lpi, /**< LP interface structure */
3531 SCIP_LPPARAM type, /**< parameter number */
3532 int ival /**< parameter value */
3533 )
3534 {
3535 assert(lpi != NULL);
3536 assert(lpi->prob != NULL);
3537
3538 SCIPdebugMessage("setting int parameter %d to %d\n", type, ival);
3539
3540 switch( type )
3541 {
3542 case SCIP_LPPAR_SCALING:
3543 if( ival == 0 )
3544 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_SIMPLEX_SCALING, 0) );
3545 else
3546 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_SIMPLEX_SCALING, 1) );
3547 break;
3548 case SCIP_LPPAR_PRICING:
3549 lpi->pricing = ival;
3550 switch( ival )
3551 {
3552 case SCIP_PRICING_AUTO:
3553 case SCIP_PRICING_LPIDEFAULT:
3554 case SCIP_PRICING_FULL:
3555 case SCIP_PRICING_STEEP:
3556 case SCIP_PRICING_STEEPQSTART:
3557 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_PRIMAL_PRICING, QS_PRICE_PSTEEP) );
3558 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_DUAL_PRICING, QS_PRICE_DSTEEP) );
3559 break;
3560 case SCIP_PRICING_PARTIAL:
3561 QS_CONDRET( QSset_param(lpi->prob,QS_PARAM_PRIMAL_PRICING,QS_PRICE_PMULTPARTIAL) );
3562 QS_CONDRET( QSset_param(lpi->prob,QS_PARAM_DUAL_PRICING,QS_PRICE_DMULTPARTIAL) );
3563 break;
3564 case SCIP_PRICING_DEVEX:
3565 QS_CONDRET( QSset_param(lpi->prob,QS_PARAM_PRIMAL_PRICING,QS_PRICE_PDEVEX) );
3566 QS_CONDRET( QSset_param(lpi->prob,QS_PARAM_DUAL_PRICING,QS_PRICE_DDEVEX) );
3567 break;
3568 default:
3569 return SCIP_LPERROR;
3570 }
3571 break;
3572 case SCIP_LPPAR_LPINFO:
3573 if( ival )
3574 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_SIMPLEX_DISPLAY, 1) );
3575 else
3576 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_SIMPLEX_DISPLAY, 0) );
3577 break;
3578 case SCIP_LPPAR_LPITLIM:
3579 /* The maximum number of pivots allowed in the algorithm can be set with the QS_PARAM_SIMPLEX_MAX_ITERATIONS parameter.
3580 * ival can be any positive integer, 0 stopping immediately */
3581 assert( ival >= 0 );
3582 QS_CONDRET( QSset_param(lpi->prob, QS_PARAM_SIMPLEX_MAX_ITERATIONS, ival) );
3583 break;
3584 default:
3585 return SCIP_PARAMETERUNKNOWN;
3586 } /*lint !e788*/
3587
3588 return SCIP_OKAY;
3589 }
3590
3591 /** gets floating point parameter of LP */
SCIPlpiGetRealpar(SCIP_LPI * lpi,SCIP_LPPARAM type,SCIP_Real * dval)3592 SCIP_RETCODE SCIPlpiGetRealpar(
3593 SCIP_LPI* lpi, /**< LP interface structure */
3594 SCIP_LPPARAM type, /**< parameter number */
3595 SCIP_Real* dval /**< buffer to store the parameter value */
3596 )
3597 {
3598 assert(lpi != NULL);
3599 assert(lpi->prob != NULL);
3600 assert(dval != NULL);
3601
3602 SCIPdebugMessage("getting real parameter %d\n", type);
3603
3604 switch( type )
3605 {
3606 case SCIP_LPPAR_OBJLIM:
3607 {
3608 int sense;
3609 QS_CONDRET( QSget_objsense(lpi->prob, &sense) );
3610 if ( sense == QS_MIN )
3611 {
3612 QS_CONDRET( QSget_param_double(lpi->prob, QS_PARAM_OBJULIM, dval) );
3613 }
3614 else
3615 {
3616 QS_CONDRET( QSget_param_double(lpi->prob, QS_PARAM_OBJLLIM, dval) );
3617 }
3618 break;
3619 }
3620 case SCIP_LPPAR_LPTILIM:
3621 QS_CONDRET( QSget_param_double(lpi->prob, QS_PARAM_SIMPLEX_MAX_TIME, dval) );
3622 break;
3623 default:
3624 case SCIP_LPPAR_MARKOWITZ:
3625 case SCIP_LPPAR_BARRIERCONVTOL:
3626 case SCIP_LPPAR_DUALFEASTOL:
3627 case SCIP_LPPAR_FEASTOL:
3628 return SCIP_PARAMETERUNKNOWN;
3629 } /*lint !e788*/
3630
3631 return SCIP_OKAY;
3632 }
3633
3634 /** sets floating point parameter of LP */
SCIPlpiSetRealpar(SCIP_LPI * lpi,SCIP_LPPARAM type,SCIP_Real dval)3635 SCIP_RETCODE SCIPlpiSetRealpar(
3636 SCIP_LPI* lpi, /**< LP interface structure */
3637 SCIP_LPPARAM type, /**< parameter number */
3638 SCIP_Real dval /**< parameter value */
3639 )
3640 {
3641 assert(lpi != NULL);
3642 assert(lpi->prob != NULL);
3643
3644 SCIPdebugMessage("setting real parameter %d to %g\n", type, dval);
3645
3646 switch( type )
3647 {
3648 case SCIP_LPPAR_LPTILIM:
3649 assert( dval > 0.0 );
3650
3651 /* qso requires dval >= 0
3652 *
3653 * However for consistency we assert the timelimit to be strictly positive.
3654 */
3655 QS_CONDRET( QSset_param_double(lpi->prob, QS_PARAM_SIMPLEX_MAX_TIME, dval) );
3656 break;
3657 case SCIP_LPPAR_OBJLIM:
3658 {
3659 int sense;
3660 QS_CONDRET( QSget_objsense(lpi->prob, &sense) );
3661 if ( sense == QS_MIN )
3662 {
3663 QS_CONDRET( QSset_param_double(lpi->prob, QS_PARAM_OBJULIM, dval) );
3664 }
3665 else
3666 {
3667 QS_CONDRET( QSset_param_double(lpi->prob, QS_PARAM_OBJLLIM, dval) );
3668 }
3669 break;
3670 }
3671 case SCIP_LPPAR_FEASTOL:
3672 case SCIP_LPPAR_DUALFEASTOL:
3673 case SCIP_LPPAR_BARRIERCONVTOL:
3674 case SCIP_LPPAR_MARKOWITZ:
3675 default:
3676 return SCIP_PARAMETERUNKNOWN;
3677 } /*lint !e788*/
3678
3679 return SCIP_OKAY;
3680 }
3681
3682 /**@} */
3683
3684
3685
3686
3687 /*
3688 * Numerical Methods
3689 */
3690
3691 /**@name Numerical Methods */
3692 /**@{ */
3693
3694 /** returns value treated as infinity in the LP solver */
SCIPlpiInfinity(SCIP_LPI * lpi)3695 SCIP_Real SCIPlpiInfinity(
3696 SCIP_LPI* lpi /**< LP interface structure */
3697 )
3698 { /*lint --e{715} */
3699 assert(lpi != NULL);
3700 return QS_MAXDOUBLE;
3701 }
3702
3703 /** checks if given value is treated as infinity in the LP solver */
SCIPlpiIsInfinity(SCIP_LPI * lpi,SCIP_Real val)3704 SCIP_Bool SCIPlpiIsInfinity(
3705 SCIP_LPI* lpi, /**< LP interface structure */
3706 SCIP_Real val /**< value to be checked for infinity */
3707 )
3708 { /*lint --e{715} */
3709 assert(lpi != NULL);
3710 return (val >= QS_MAXDOUBLE);
3711 }
3712
3713 /**@} */
3714
3715
3716
3717
3718 /*
3719 * File Interface Methods
3720 */
3721
3722 /**@name File Interface Methods */
3723 /**@{ */
3724
3725 /** reads LP from a file */
SCIPlpiReadLP(SCIP_LPI * lpi,const char * fname)3726 SCIP_RETCODE SCIPlpiReadLP(
3727 SCIP_LPI* lpi, /**< LP interface structure */
3728 const char* fname /**< file name */
3729 )
3730 {
3731 assert(lpi != NULL);
3732 assert(lpi->prob != NULL);
3733 assert(fname != NULL);
3734
3735 SCIPdebugMessage("reading LP from file <%s>\n", fname);
3736
3737 if( lpi->prob != NULL )
3738 QSfree_prob(lpi->prob);
3739
3740 lpi->solstat = 0;
3741 lpi->previt = 0;
3742
3743 lpi->prob = QSread_prob(fname, "LP");
3744 if( lpi->prob == 0 )
3745 return SCIP_READERROR;
3746
3747 return SCIP_OKAY;
3748 }
3749
3750 /** writes LP to a file */
SCIPlpiWriteLP(SCIP_LPI * lpi,const char * fname)3751 SCIP_RETCODE SCIPlpiWriteLP(
3752 SCIP_LPI* lpi, /**< LP interface structure */
3753 const char* fname /**< file name */
3754 )
3755 {
3756 assert(lpi != NULL);
3757 assert(lpi->prob != NULL);
3758 assert(fname != NULL);
3759
3760 SCIPdebugMessage("writing LP to file <%s>\n", fname);
3761
3762 if( QSwrite_prob (lpi->prob, fname, "LP") )
3763 return SCIP_WRITEERROR;
3764
3765 return SCIP_OKAY;
3766 }
3767
3768 /**@} */
3769