Scippy

SCIP

Solving Constraint Integer Programs

lpi_spx2.cpp
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file lpi_spx2.cpp
26 * @ingroup LPIS
27 * @brief LP interface for SoPlex version 2.0 and higher
28 * @author Matthias Miltenberger
29 * @author Ambros Gleixner
30 *
31 * This is an implementation of SCIP's LP interface for SoPlex using the extended and improved interface of SoPlex 2.0
32 *
33 * For debugging purposes, the SoPlex results can be double checked with CPLEX if SCIP_WITH_LPSCHECK is defined. This may
34 * yield false positives, since the LP is dumped to a file for transfering it to CPLEX, hence, precision may be lost.
35 */
36
37/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
38
39#define STRONGBRANCH_RESTOREBASIS /**< if defined then in SCIPlpiStrongbranch() we restore the basis after the
40 * down branch and after the up branch; if false only after the end of a
41 * strong branching phase, which however seems to mostly increase strong
42 * branching time and iterations */
43
44/*
45 * include build configuration flags
46 */
47#include "scip/config.h"
48
49/* in this case the SoPlex results are double checked using CPLEX */
50#ifdef SCIP_WITH_LPSCHECK
51#include <cplex.h>
52
53#define CHECK_SPXSOLVE true /**< shall the SoPlex results in spxSolve() be double checked using CPLEX? */
54#define CHECK_SPXSTRONGBRANCH true /**< shall the SoPlex results in SCIPlpStrongbranch() be double checked using CPLEX? */
55#define CHECK_START 0 /**< skip first CHECK_START number of checks */
56#define EXIT_AT_WRONG_RESULT false/**< shall program be exited if CPLEX returns different result than SoPlex? */
57#define EXIT_AT_CPXERROR false/**< shall program be exited if CPLEX returns an error? */
58
59#define CPX_CALL(x) do \
60 { \
61 int _cpxstat_; \
62 if( (_cpxstat_ = (x)) != 0 ) \
63 { \
64 SCIPmessagePrintWarning(_messagehdlr, "CPLEX error <%d>; SoPlex result unchecked\n", _cpxstat_); \
65 if( EXIT_AT_CPXERROR ) \
66 { \
67 exit(1); \
68 } \
69 else \
70 { \
71 goto ENDCHECK; \
72 } \
73 } \
74 } \
75 while( false )
76#endif
77
78/* check the return value of setParam methods */
79#define CHECK_SOPLEX_PARAM(x) \
80 if( !x ) \
81 { \
82 SCIPmessagePrintWarning(_messagehdlr, "SoPlex: unsupported parameter value\n"); \
83 }
84
85/* remember the original value of the SCIP_DEBUG define and undefine it */
86#ifdef SCIP_DEBUG
87#define ___DEBUG
88#undef SCIP_DEBUG
89#endif
90
91/* compile the SoPlex header with visibility=default because the SoPlex lib has been compiled that way */
92#ifdef __GNUC__
93#pragma GCC visibility push(default)
94#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
95#endif
96
97/* include SoPlex solver */
98#include "soplex.h"
99
100/* define subversion for versions <= 1.5.0.1 */
101#ifndef SOPLEX_SUBVERSION
102#define SOPLEX_SUBVERSION 0
103#endif
104/* define API version for versions <= 3.0.0 */
105#ifndef SOPLEX_APIVERSION
106#define SOPLEX_APIVERSION 0
107#endif
108
109/* check version */
110#if (SOPLEX_VERSION < 200 || (SOPLEX_VERSION == 200 && SOPLEX_SUBVERSION < 2) || (SOPLEX_VERSION > 200 && SOPLEX_VERSION < 201))
111#error "This interface is not compatible with SoPlex versions prior to 2.0.0.2"
112#endif
113
114#if (SOPLEX_APIVERSION <= 5)
115#include "spxgithash.h"
116#endif
117
118/* reset the SCIP_DEBUG define to its original SCIP value */
119#undef SCIP_DEBUG
120#ifdef ___DEBUG
121#define SCIP_DEBUG
122#undef ___DEBUG
123#endif
124
125/* define snprintf when using a too old MSVC version */
126#if defined(_MSC_VER) && _MSC_VER < 1900
127#ifndef snprintf
128#define snprintf _snprintf
129#endif
130#endif
131
132#define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
133
134#include "scip/pub_message.h"
135
136/********************************************************************/
137/*----------------------------- C++ --------------------------------*/
138/********************************************************************/
139
140/* in C++ we have to use "0" instead of "(void*)0" */
141#undef NULL
142#define NULL 0
143
144#include <cassert>
145using namespace soplex;
146
147
148/** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
149 * make no distinction between different exception types, e.g., between memory allocation and other
150 * exceptions.
151 */
152#ifndef NDEBUG
153#define SOPLEX_TRY(messagehdlr, x) do \
154 { \
155 try \
156 { \
157 (x); \
158 } \
159 catch( const SPxMemoryException& E ) \
160 { \
161 std::string s = E.what(); \
162 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
163 return SCIP_ERROR; \
164 } \
165 catch( const SPxException& E ) \
166 { \
167 std::string s = E.what(); \
168 SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
169 return SCIP_LPERROR; \
170 } \
171 } \
172 while( FALSE )
173
174#else
175#define SOPLEX_TRY(messagehdlr, x) do \
176 { \
177 try \
178 { \
179 (x); \
180 } \
181 catch( const SPxMemoryException& E ) \
182 { \
183 std::string s = E.what(); \
184 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
185 return SCIP_ERROR; \
186 } \
187 catch( const SPxException& ) \
188 { \
189 return SCIP_LPERROR; \
190 } \
191 } \
192 while( FALSE )
193#endif
194
195/* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
196 * arise. SCIP_ABORT() is not accessible here.
197 */
198#define SOPLEX_TRY_ABORT(x) do \
199 { \
200 try \
201 { \
202 (x); \
203 } \
204 catch( const SPxException& E ) \
205 { \
206 std::string s = E.what(); \
207 SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
208 abort(); \
209 } \
210 } \
211 while( FALSE )
212
213
214
215/** SCIP's SoPlex class */
216class SPxSCIP : public SoPlex
217{/*lint !e1790*/
218 bool _lpinfo;
219 bool _fromscratch;
220 bool _interrupt;
221 char* _probname;
222 DataArray<SPxSolver::VarStatus> _colStat; /**< column basis status used for strong branching */
223 DataArray<SPxSolver::VarStatus> _rowStat; /**< row basis status used for strong branching */
224#ifdef SCIP_WITH_LPSCHECK
225 int _checknum;
226 bool _doublecheck;
227 CPXENVptr _cpxenv; /**< CPLEX memory environment */
228 CPXLPptr _cpxlp; /**< CPLEX lp structure */
229#endif
230 SCIP_MESSAGEHDLR* _messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
231
232public:
233 SPxSCIP(
234 SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
235 const char* probname = NULL /**< name of problem */
236 )
237 : _lpinfo(false),
238 _fromscratch(false),
239 _probname(NULL),
240 _colStat(0),
241 _rowStat(0),
242 _messagehdlr(messagehdlr)
243 {
244 if ( probname != NULL )
245 SOPLEX_TRY_ABORT( setProbname(probname) );
246
247#if SOPLEX_APIVERSION >= 2
248 (void)setBoolParam(SoPlex::ENSURERAY, true);
249#endif
250
251#ifdef SCIP_WITH_LPSCHECK
252 int cpxstat;
253 _checknum = 0;
254 _doublecheck = false;
255 _cpxenv = CPXopenCPLEX(&cpxstat);
256 assert(_cpxenv != NULL);
257 _cpxlp = CPXcreateprob(_cpxenv, &cpxstat, probname != NULL ? probname : "spxcheck");
258 (void) CPXsetintparam(_cpxenv, CPX_PARAM_SCRIND, 0);
259#endif
260 }
261
262 virtual ~SPxSCIP()
263 {
264 if( _probname != NULL )
265 spx_free(_probname); /*lint !e1551*/
266
267 freePreStrongbranchingBasis(); /*lint !e1551*/
268
269#ifdef SCIP_WITH_LPSCHECK
270 (void) CPXfreeprob(_cpxenv, &_cpxlp);
271 (void) CPXcloseCPLEX(&_cpxenv);
272#endif
273 }/*lint -e1579*/
274
275 // we might need these methods to return the original values SCIP provided, even if they could not be set
276 /** return feastol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
277 Real feastol() const
278 {
279 return realParam(FEASTOL);
280 }
281
282 /** set feastol and store value in case SoPlex only accepts a larger tolerance */
283 void setFeastol(
284 const Real d
285 )
286 {
287 CHECK_SOPLEX_PARAM(setRealParam(FEASTOL, d));
288 }
289
290 /** return opttol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
291 Real opttol() const
292 {
293 return realParam(OPTTOL);
294 }
295
296 /** set opttol and store value in case SoPlex only accepts a larger tolerance */
297 void setOpttol(
298 const Real d
299 )
300 {
301 CHECK_SOPLEX_PARAM(setRealParam(OPTTOL, d));
302 }
303
304 /** get objective limit according to objective sense */
305 Real getObjLimit() const
306 {
307 return (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE)
308 ? realParam(SoPlex::OBJLIMIT_UPPER)
309 : realParam(SoPlex::OBJLIMIT_LOWER);
310 }
311
312 // @todo realize this with a member variable as before
313 bool getFromScratch() const
314 {
315 return _fromscratch;
316 }
317
318 void setFromScratch(bool fs)
319 {
320 _fromscratch = fs;
321 }
322
323 void setInterrupt(bool interrupt)
324 {
325 _interrupt = interrupt;
326 }
327
328 bool* getInterrupt()
329 {
330 return &_interrupt;
331 }
332
333 // @todo member variable?
334 bool getLpInfo() const
335 {
336 return _lpinfo;
337 }
338
339 void setLpInfo(bool lpinfo)
340 {
341 _lpinfo = lpinfo;
342 }
343
344 // @todo member variable?
345 void setProbname(const char* probname)
346 {
347 size_t len;
348
349 assert(probname != NULL);
350 if( _probname != NULL )
351 spx_free(_probname);
352
353 len = strlen(probname);
354 spx_alloc(_probname, len + 1);
355 memcpy(_probname, probname, len + 1);
356 }
357
358 void setRep(SPxSolver::Representation p_rep)
359 {
360 if( p_rep == SPxSolver::COLUMN && intParam(REPRESENTATION) == REPRESENTATION_ROW )
361 {
362 SCIPdebugMessage("switching to column representation of the basis\n");
363 CHECK_SOPLEX_PARAM(setIntParam(REPRESENTATION, REPRESENTATION_COLUMN));
364 }
365 else if( (p_rep == SPxSolver::ROW && intParam(REPRESENTATION) == REPRESENTATION_COLUMN) )
366 {
367 SCIPdebugMessage("switching to row representation of the basis\n");
368 CHECK_SOPLEX_PARAM(setIntParam(REPRESENTATION, REPRESENTATION_ROW));
369 }
370 }
371
372#ifdef SCIP_WITH_LPSCHECK
373 bool getDoubleCheck()
374 {
375 _checknum++;
376 return _doublecheck && _checknum + 1 >= CHECK_START;
377 }
378
379 void setDoubleCheck(bool dc)
380 {
381 _doublecheck = dc;
382 }
383
384 const char* spxStatusString(const SPxSolver::Status stat) const
385 {
386 switch( stat )
387 {
388 case SPxSolver::ABORT_TIME:
389 return "ABORT_TIME";
390 case SPxSolver::ABORT_ITER:
391 return "ABORT_ITER";
392 case SPxSolver::ABORT_VALUE:
393 return "ABORT_VALUE";
394 case SPxSolver::SINGULAR:
395 return "SINGULAR";
396 case SPxSolver::REGULAR:
397 return "REGULAR";
399 return "UNKNOWN";
400 case SPxSolver::OPTIMAL:
401 return "OPTIMAL";
402#if SOPLEX_APIVERSION >= 3
403 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
404 return "OPTIMAL_UNSCALED_VIOLATIONS";
405#endif
406 case SPxSolver::UNBOUNDED:
407 return "UNBOUNDED";
408 case SPxSolver::INFEASIBLE:
409 return "INFEASIBLE";
410 default:
411 return "UNKNOWN";
412 } /*lint !e788*/
413 }
414
415 const char* cpxStatusString(const int stat) const
416 {
417 switch( stat )
418 {
419 case CPX_STAT_ABORT_TIME_LIM:
420 return "ABORT_TIME";
421 case CPX_STAT_ABORT_IT_LIM:
422 return "ABORT_ITER";
423 case CPX_STAT_ABORT_OBJ_LIM:
424 return "ABORT_VALUE";
425 case CPX_STAT_OPTIMAL:
426 return "OPTIMAL";
427 case CPX_STAT_OPTIMAL_INFEAS:
428 return "CPX_STAT_OPTIMAL_INFEAS: OPT SOL INFEASIBLE AFTER UNSCALING";
429 case CPX_STAT_UNBOUNDED:
430 return "UNBOUNDED";
431 case CPX_STAT_INFEASIBLE:
432 return "INFEASIBLE";
433 case CPX_STAT_INForUNBD:
434 return "INFEASIBLE or UNBOUNDED";
435 case CPX_STAT_NUM_BEST:
436 return "CPX_STAT_NUM_BEST: SOL AVAILABLE BUT NOT PROVEN OPTIMAL DUE TO NUM TROUBLE";
437 default:
438 return "UNKNOWN";
439 } /*lint !e788*/
440 }
441#endif
442
443#ifndef NDEBUG
444 bool checkConsistentBounds() const
445 {
446 for( int i = 0; i < numColsReal(); ++i )
447 {
448 if( lowerReal(i) > upperReal(i) + realParam(SoPlex::EPSILON_ZERO) )
449 {
450 SCIPerrorMessage("inconsistent bounds on column %d: lower=%.17g, upper=%.17g\n",
451 i, lowerReal(i), upperReal(i));
452 return false;
453 }
454 }
455
456 return true;
457 }
458
459 bool checkConsistentSides() const
460 {
461 for( int i = 0; i < numRowsReal(); ++i )
462 {
463 if( lhsReal(i) > rhsReal(i) + realParam(SoPlex::EPSILON_ZERO) )
464 {
465 SCIPerrorMessage("inconsistent sides on row %d: lhs=%.17g, rhs=%.17g\n",
466 i, lhsReal(i), rhsReal(i));
467 return false;
468 }
469 }
470
471 return true;
472 }
473#endif
474
475 void trySolve(bool printwarning = true)
476 {
477 Real timespent;
478 Real timelimit;
479
480 try
481 {
482#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
483#if SOPLEX_APIVERSION > 11
484 (void) optimize(&_interrupt);
485#else
486 (void) optimize();
487#endif
488#else
489 (void) solve();
490#endif
491 }
492 catch(const SPxException& x)
493 {
494 std::string s = x.what();
495 if( printwarning )
496 {
497 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
498 }
499
500 /* since it is not clear if the status in SoPlex are set correctly
501 * we want to make sure that if an error is thrown the status is
502 * not OPTIMAL anymore.
503 */
504 assert(status() != SPxSolver::OPTIMAL);
505 }
506
507 assert(intParam(ITERLIMIT) < 0 || numIterations() <= intParam(ITERLIMIT));
508
509 /* update time limit */
510 timespent = solveTime();
511 if( timespent > 0 )
512 {
513 /* get current time limit */
514 timelimit = realParam(TIMELIMIT);
515 if( timelimit > timespent )
516 timelimit -= timespent;
517 else
518 timelimit = 0;
519 /* set new time limit */
520 assert(timelimit >= 0);
521 CHECK_SOPLEX_PARAM(setRealParam(TIMELIMIT, timelimit));
522 }
523 }
524
525 SPxSolver::Status doSolve(bool printwarning = true)
526 {
527 SPxOut::Verbosity verbosity;
528
529 SPxSolver::Status spxStatus;
530
531 /* store and set verbosity */
532 verbosity = spxout.getVerbosity();
533 spxout.setVerbosity((SPxOut::Verbosity)(getLpInfo() ? SOPLEX_VERBLEVEL : 0));
534
535 assert(checkConsistentBounds());
536 assert(checkConsistentSides());
537
538#ifdef SCIP_WITH_LPSCHECK
539 /* dump LP with current basis and settings saved in SoPlex */
540 if( getDoubleCheck() )
541 writeStateReal("spxcheck", NULL, NULL);
542#endif
543
544 trySolve(printwarning);
545 spxStatus = status();
546
547 /* for safety reset iteration limit */
548// setTerminationIter(_itlim);
549
550#ifdef SCIP_WITH_LPSCHECK
551 bool minimize = intParam(OBJSENSE) == OBJSENSE_MINIMIZE;
552 Real objLimitUpper = realParam(OBJLIMIT_UPPER);
553 Real objLimitLower = realParam(OBJLIMIT_LOWER);
554
555 /* if SoPlex gave a definite answer, we double check if it is consistent with CPLEX's answer */
556 if( getDoubleCheck() && (spxStatus == SPxSolver::OPTIMAL || spxStatus == SPxSolver::UNBOUNDED || spxStatus == SPxSolver::INFEASIBLE || spxStatus == SPxSolver::ABORT_VALUE) )
557 {
558 SCIP_Real cpxobj;
559 int cpxstat;
560
561 /* read LP with basis */
562 CPX_CALL( CPXreadcopyprob(_cpxenv, _cpxlp, "spxcheck.mps", NULL) );
563 CPX_CALL( CPXreadcopybase(_cpxenv, _cpxlp, "spxcheck.bas") );
564
565 /* set tolerances */
566 CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPOPT, MAX(opttol(), 1e-9)) );
567 CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPRHS, MAX(feastol(), 1e-9)) );
568
569 /* solve LP */
570 CPX_CALL( CPXlpopt(_cpxenv, _cpxlp) );
571
572 /* get solution status and objective value */
573 CPX_CALL( CPXsolution(_cpxenv, _cpxlp, &cpxstat, &cpxobj, NULL, NULL, NULL, NULL) );
574 if( !minimize )
575 cpxobj *= -1.0;
576
577 /* check for inconsistent statuses */
578 if( cpxstat == CPX_STAT_OPTIMAL_INFEAS )
579 {
580 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s)\n",
581 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat));
582 if( EXIT_AT_CPXERROR )
583 exit(1);
584 }
585 else if( (spxStatus == SPxSolver::OPTIMAL && cpxstat != CPX_STAT_OPTIMAL)
586 || (spxStatus == SPxSolver::UNBOUNDED && cpxstat != CPX_STAT_UNBOUNDED)
587 || (spxStatus == SPxSolver::INFEASIBLE && cpxstat != CPX_STAT_INFEASIBLE) )
588 {
589 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
590 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
591 if( EXIT_AT_WRONG_RESULT )
592 exit(1);
593 }
594 else if( spxStatus == SPxSolver::ABORT_VALUE )
595 {
596 switch( cpxstat )
597 {
598 case CPX_STAT_OPTIMAL:
599 if( (minimize && LTrel(cpxobj, objLimitUpper, 2*opttol()))
600 || (!minimize && GTrel(cpxobj, objLimitLower, 2*opttol())) )
601 {
602 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
603 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
604 minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
605 if( EXIT_AT_WRONG_RESULT )
606 exit(1);
607 }
608 else if( (minimize && cpxobj < objLimitUpper) || (!minimize && cpxobj > objLimitLower) )
609 {
610 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
611 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize? "<" : ">",
612 minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
613 }
614 break;
615 case CPX_STAT_OPTIMAL_INFEAS:
616 case CPX_STAT_NUM_BEST:
617 if( (minimize && cpxobj < objLimitUpper) || (!minimize && cpxobj > objLimitLower) )
618 {
619 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
620 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
621 minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
622 }
623 break;
624 case CPX_STAT_INFEASIBLE:
625 break;
626 case CPX_STAT_UNBOUNDED:
627 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
628 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
629 if( EXIT_AT_WRONG_RESULT )
630 exit(1);
631 break;
632 case CPX_STAT_INForUNBD:
633 default:
634 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
635 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
636 break;
637 } /*lint !e788*/
638 }
639 /* check for same objective values */
640 else if( spxStatus == SPxSolver::OPTIMAL )
641 {
642 if( (minimize && LTrel(objValueReal(), cpxobj, 2*opttol()))
643 || (!minimize && GTrel(objValueReal(), cpxobj, 2*opttol())) )
644 {
645 /* SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f too good (checknum=%d)\n", value(),
646 _probname, getSense() == SPxSolver::MINIMIZE ? "<" : ">", cpxobj, _checknum); */
647 }
648 else if( (minimize && GTrel(objValueReal(), cpxobj, 2*opttol()))
649 || (!minimize && LTrel(objValueReal(), cpxobj, 2*opttol())) )
650 {
651 SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f suboptimal (checknum=%d)\n", _probname, objValueReal(),
652 minimize ? ">" : "<", cpxobj, _checknum);
653 if( EXIT_AT_WRONG_RESULT )
654 exit(1);
655 }
656 }
657 }
658
659 ENDCHECK:
660#endif
661
662 /* restore verbosity */
663 spxout.setVerbosity(verbosity);
664
665 return spxStatus;
666 }
667
668 /** save the current basis */
669 void savePreStrongbranchingBasis()
670 {
671 _rowStat.reSize(numRowsReal());
672 _colStat.reSize(numColsReal());
673
674 try
675 {
676 getBasis(_rowStat.get_ptr(), _colStat.get_ptr());
677 }
678#ifndef NDEBUG
679 catch(const SPxException& x)
680 {
681 std::string s = x.what();
682 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
683
684 /* since it is not clear if the status in SoPlex are set correctly
685 * we want to make sure that if an error is thrown the status is
686 * not OPTIMAL anymore.
687 */
688 assert(status() != SPxSolver::OPTIMAL);
689 }
690#else
691 catch(const SPxException&)
692 { }
693#endif
694 }
695
696 /** restore basis */
697 void restorePreStrongbranchingBasis()
698 {
699 assert(_rowStat.size() == numRowsReal());
700 assert(_colStat.size() == numColsReal());
701
702 try
703 {
704 setBasis(_rowStat.get_ptr(), _colStat.get_ptr());
705 }
706#ifndef NDEBUG
707 catch(const SPxException& x)
708 {
709 std::string s = x.what();
710 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
711#else
712 catch(const SPxException&)
713 {
714#endif
715 /* since it is not clear if the status in SoPlex are set correctly
716 * we want to make sure that if an error is thrown the status is
717 * not OPTIMAL anymore.
718 */
719 assert(status() != SPxSolver::OPTIMAL);
720 }
721 }
722
723 /** if basis is in store, delete it without restoring it */
724 void freePreStrongbranchingBasis()
725 {
726 _rowStat.clear();
727 _colStat.clear();
728 }
729
730 /** is pre-strong-branching basis freed? */
731 bool preStrongbranchingBasisFreed() const
732 {
733 return ((_rowStat.size() == 0 ) && (_colStat.size() == 0));
734 }
735
736 /** provides access for temporary storage of basis status of rows */
737 DataArray<SPxSolver::VarStatus>& rowStat()
738 {
739 return _rowStat; /*lint !e1536*/
740 }
741
742 /** provides access for temporary storage of basis status or columns */
743 DataArray<SPxSolver::VarStatus>& colStat()
744 {
745 return _colStat; /*lint !e1536*/
746 }
747
748}; /*lint !e1748*/
749
750
751
752
753/********************************************************************/
754/*----------------------------- C --------------------------------*/
755/********************************************************************/
756
757#include "lpi/lpi.h"
758#include "scip/bitencode.h"
759
760typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
761#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
762typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
763#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
764
765
766
767/** LP interface */
768struct SCIP_LPi
769{
770 SPxSCIP* spx; /**< our SoPlex implementation */
771 int* cstat; /**< array for storing column basis status */
772 int* rstat; /**< array for storing row basis status */
773 int cstatsize; /**< size of cstat array */
774 int rstatsize; /**< size of rstat array */
775 SCIP_PRICING pricing; /**< current pricing strategy */
776 SCIP_Bool solved; /**< was the current LP solved? */
777 SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
778 SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
779 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
780};
781
782/** LPi state stores basis information */
783struct SCIP_LPiState
784{
785 int ncols; /**< number of LP columns */
786 int nrows; /**< number of LP rows */
787 COLPACKET* packcstat; /**< column basis status in compressed form */
788 ROWPACKET* packrstat; /**< row basis status in compressed form */
789};
790
791/** LPi norms to store dual steepest edge */
792struct SCIP_LPiNorms
793{
794 int nrows; /**< number of stored norms corresponding to rows */
795 int ncols; /**< number of stored norms corresponding to cols */
796 SCIP_Real* norms; /**< norms to be (re)stored */
797};
798
799
800
801/*
802 * dynamic memory arrays
803 */
804
805/** resizes cstat array to have at least num entries */
806static
808 SCIP_LPI* lpi, /**< LP interface structure */
809 int num /**< minimal number of entries in array */
810 )
811{
812 assert(lpi != NULL);
813
814 if( num > lpi->cstatsize )
815 {
816 int newsize;
817
818 newsize = MAX(2*lpi->cstatsize, num);
819 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
820 lpi->cstatsize = newsize;
821 }
822 assert(num <= lpi->cstatsize);
823
824 return SCIP_OKAY;
825}
826
827/** resizes rstat array to have at least num entries */
828static
830 SCIP_LPI* lpi, /**< LP interface structure */
831 int num /**< minimal number of entries in array */
832 )
833{
834 assert(lpi != NULL);
835
836 if( num > lpi->rstatsize )
837 {
838 int newsize;
839
840 newsize = MAX(2*lpi->rstatsize, num);
841 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
842 lpi->rstatsize = newsize;
843 }
844 assert(num <= lpi->rstatsize);
845
846 return SCIP_OKAY;
847}
848
849
850
851
852/*
853 * LPi state methods
854 */
855
856/** returns the number of packets needed to store column packet information */
857static
859 int ncols /**< number of columns to store */
860 )
861{
862 return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
863}
864
865/** returns the number of packets needed to store row packet information */
866static
868 int nrows /**< number of rows to store */
869 )
870{
871 return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
872}
873
874/** store row and column basis status in a packed LPi state object */
875static
877 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
878 const int* cstat, /**< basis status of columns in unpacked format */
879 const int* rstat /**< basis status of rows in unpacked format */
880 )
881{
882 assert(lpistate != NULL);
883 assert(lpistate->packcstat != NULL);
884 assert(lpistate->packrstat != NULL);
885
886 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
887 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
888}
889
890/** unpacks row and column basis status from a packed LPi state object */
891static
893 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
894 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
895 int* rstat /**< buffer for storing basis status of rows in unpacked format */
896 )
897{
898 assert(lpistate != NULL);
899 assert(lpistate->packcstat != NULL);
900 assert(lpistate->packrstat != NULL);
901
902 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
903 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
904}
905
906/** creates LPi state information object */
907static
909 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
910 BMS_BLKMEM* blkmem, /**< block memory */
911 int ncols, /**< number of columns to store */
912 int nrows /**< number of rows to store */
913 )
914{
915 assert(lpistate != NULL);
916 assert(blkmem != NULL);
917 assert(ncols >= 0);
918 assert(nrows >= 0);
919
920 int nColPackets = colpacketNum(ncols);
921 int nRowPackets = rowpacketNum(nrows);
922
923 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
924 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
925 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
926
927 return SCIP_OKAY;
928}
929
930/** frees LPi state information */
931static
933 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
934 BMS_BLKMEM* blkmem /**< block memory */
935 )
936{
937 assert(blkmem != NULL);
938 assert(lpistate != NULL);
939 assert(*lpistate != NULL);
940
941 int nColPackets = colpacketNum((*lpistate)->ncols);
942 int nRowPackets = rowpacketNum((*lpistate)->nrows);
943
944 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
945 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
946 BMSfreeBlockMemory(blkmem, lpistate);
947}
948
949
950
951
952/*
953 * local methods
954 */
955
956
957/** marks the current LP to be unsolved */
958static
960{
961 assert(lpi != NULL);
962 lpi->solved = FALSE;
963}
964
965
966
967/*
968 * LP Interface Methods
969 */
970
971
972/*
973 * Miscellaneous Methods
974 */
975
976#if (SOPLEX_SUBVERSION > 0)
977 const static char spxname[20] = {'S', 'o', 'p', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '.', SOPLEX_SUBVERSION + '0', '\0'};
978#else
979 const static char spxname[20] = {'S', 'o', 'p', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '\0'};
980#endif
981const static char spxdesc[200] = {'L', 'i', 'n', 'e', 'a', 'r', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g',
982 ' ', 'S', 'o', 'l', 'v', 'e', 'r', ' ' , 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'd',
983 ' ', 'a', 't', ' ', 'Z', 'u', 's', 'e', ' ', 'I', 'n', 's', 't', 'i', 't', 'u', 't', 'e',
984 ' ', 'B', 'e', 'r', 'l', 'i', 'n', ' ', '(', 's', 'o', 'p', 'l', 'e', 'x', '.', 'z', 'i', 'b', '.', 'd', 'e', ')',
985#ifdef SCIP_WITH_LPSCHECK
986 ' ', '-', ' ', 'i', 'n', 'c', 'l', 'u', 'd', 'i', 'n', 'g', ' ', 'C','P','L', 'E', 'X',
987 ' ', 'd', 'o', 'u', 'b', 'l', 'e', ' ', 'c', 'h', 'e', 'c', 'k',
988#endif
989 ' ', '[', 'G', 'i', 't', 'H', 'a', 's', 'h', ':', ' ',
990 getGitHash()[0], getGitHash()[1], getGitHash()[2], getGitHash()[3],
991 getGitHash()[4], getGitHash()[5], getGitHash()[6], getGitHash()[7],
992 ']', '\0'};
993
994/**@name Miscellaneous Methods */
995/**@{ */
996
997/** gets name and version of LP solver */
999 void
1000 )
1001{
1002 SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
1003 return spxname;
1004}
1005
1006/** gets description of LP solver (developer, webpage, ...) */
1008 void
1009 )
1010{
1011 return spxdesc;
1012}
1013
1014/** gets pointer for LP solver - use only with great care */
1016 SCIP_LPI* lpi /**< pointer to an LP interface structure */
1017 )
1018{
1019 return (void*) lpi->spx;
1020}
1021
1022/** pass integrality information about variables to the solver */
1024 SCIP_LPI* lpi, /**< pointer to an LP interface structure */
1025 int ncols, /**< length of integrality array */
1026 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
1027 )
1028{
1029 assert( lpi != NULL );
1030 assert( ncols >= 0 );
1031 assert( ncols == 0 || intInfo != NULL );
1032
1033#if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1034 assert(ncols == lpi->spx->numColsReal() || (ncols == 0 && intInfo == NULL));
1035 lpi->spx->setIntegralityInformation(ncols, intInfo);
1036 return SCIP_OKAY;
1037#else
1038 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1039 return SCIP_LPERROR;
1040#endif
1041}
1042
1043/** informs about availability of a primal simplex solving method */
1045 void
1046 )
1047{
1048 return TRUE;
1049}
1050
1051/** informs about availability of a dual simplex solving method */
1053 void
1054 )
1055{
1056 return TRUE;
1057}
1058
1059/** informs about availability of a barrier solving method */
1061 void
1062 )
1063{
1064 return FALSE;
1065}
1066
1067/**@} */
1068
1069
1070
1071
1072/*
1073 * LPI Creation and Destruction Methods
1074 */
1075
1076/**@name LPI Creation and Destruction Methods */
1077/**@{ */
1078
1079/** creates an LP problem object */
1081 SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1082 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1083 const char* name, /**< problem name */
1084 SCIP_OBJSEN objsen /**< objective sense */
1085 )
1086{
1087 assert(lpi != NULL);
1088 assert(name != NULL);
1089
1090 /* create SoPlex object */
1091 SCIP_ALLOC( BMSallocMemory(lpi) );
1092
1093 /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1094 (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1095 SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1096 (void) (*lpi)->spx->setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_ONLYREAL);
1097 (void) (*lpi)->spx->setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_REAL);
1098 (void) (*lpi)->spx->setIntParam(SoPlex::REPRESENTATION, SoPlex::REPRESENTATION_AUTO);
1099
1100 /* disable time-measurement for statistics */
1101#if SOPLEX_APIVERSION >= 10
1102 (void) (*lpi)->spx->setIntParam(SoPlex::STATTIMER, 0);
1103#endif
1104
1105 (*lpi)->cstat = NULL;
1106 (*lpi)->rstat = NULL;
1107 (*lpi)->cstatsize = 0;
1108 (*lpi)->rstatsize = 0;
1109 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1110 (*lpi)->conditionlimit = -1.0;
1111 (*lpi)->checkcondition = FALSE;
1112 (*lpi)->messagehdlr = messagehdlr;
1113
1114 invalidateSolution(*lpi);
1115
1116 /* set objective sense */
1117 SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
1118
1119 /* set default pricing */
1120 SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1121
1122 {
1123 (*lpi)->spx->setInterrupt(FALSE);
1124 SPxOut::Verbosity verbosity = (*lpi)->spx->spxout.getVerbosity();
1125 (*lpi)->spx->spxout.setVerbosity((SPxOut::Verbosity)((*lpi)->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
1126 (*lpi)->spx->printVersion();
1127 (*lpi)->spx->spxout.setVerbosity(verbosity);
1128 }
1129
1130 return SCIP_OKAY;
1131}
1132
1133/** deletes an LP problem object */
1135 SCIP_LPI** lpi /**< pointer to an LP interface structure */
1136 )
1137{
1138 assert(lpi != NULL);
1139 assert(*lpi != NULL);
1140 assert((*lpi)->spx != NULL);
1141
1142 /* free LP using destructor and free memory via blockmemshell */
1143 (*lpi)->spx->~SPxSCIP();
1144 BMSfreeMemory(&((*lpi)->spx));
1145
1146 /* free memory */
1147 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1148 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1149 BMSfreeMemory(lpi);
1150
1151 return SCIP_OKAY;
1152}
1153
1154/**@} */
1155
1156
1157
1158
1159/*
1160 * Modification Methods
1161 */
1162
1163/**@name Modification Methods */
1164/**@{ */
1165
1166/** copies LP data with column matrix into LP solver */
1168 SCIP_LPI* lpi, /**< LP interface structure */
1169 SCIP_OBJSEN objsen, /**< objective sense */
1170 int ncols, /**< number of columns */
1171 const SCIP_Real* obj, /**< objective function values of columns */
1172 const SCIP_Real* lb, /**< lower bounds of columns */
1173 const SCIP_Real* ub, /**< upper bounds of columns */
1174 char** colnames, /**< column names, or NULL */
1175 int nrows, /**< number of rows */
1176 const SCIP_Real* lhs, /**< left hand sides of rows */
1177 const SCIP_Real* rhs, /**< right hand sides of rows */
1178 char** /*rownames*/, /**< row names, or NULL */
1179 int nnonz, /**< number of nonzero elements in the constraint matrix */
1180 const int* beg, /**< start index of each column in ind- and val-array */
1181 const int* ind, /**< row indices of constraint matrix entries */
1182 const SCIP_Real* val /**< values of constraint matrix entries */
1183 )
1184{
1185#ifndef NDEBUG
1186 {
1187 int j;
1188 for( j = 0; j < nnonz; j++ )
1189 assert( val[j] != 0 );
1190 }
1191#endif
1192
1193 SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1194
1195 assert(lpi != NULL);
1196 assert(lpi->spx != NULL);
1197 assert(lhs != NULL);
1198 assert(rhs != NULL);
1199 assert(obj != NULL);
1200 assert(lb != NULL);
1201 assert(ub != NULL);
1202 assert(beg != NULL);
1203 assert(ind != NULL);
1204 assert(val != NULL);
1205
1206 invalidateSolution(lpi);
1207 assert(lpi->spx->preStrongbranchingBasisFreed());
1208
1209 try
1210 {
1211 SPxSCIP* spx = lpi->spx;
1212 LPRowSet rows(nrows);
1213 DSVector emptyVector(0);
1214 int i;
1215
1216 spx->clearLPReal();
1217
1218 /* set objective sense */
1219 (void) spx->setIntParam(SoPlex::OBJSENSE, (objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE));
1220
1221 /* create empty rows with given sides */
1222 for( i = 0; i < nrows; ++i )
1223 rows.add(lhs[i], emptyVector, rhs[i]);
1224 spx->addRowsReal(rows);
1225
1226 /* create column vectors with coefficients and bounds */
1227 SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1228 }
1229#ifndef NDEBUG
1230 catch( const SPxException& x )
1231 {
1232 std::string s = x.what();
1233 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1234#else
1235 catch( const SPxException& )
1236 {
1237#endif
1238 return SCIP_LPERROR;
1239 }
1240
1241 return SCIP_OKAY;
1242}
1243
1244/** adds columns to the LP */
1246 SCIP_LPI* lpi, /**< LP interface structure */
1247 int ncols, /**< number of columns to be added */
1248 const SCIP_Real* obj, /**< objective function values of new columns */
1249 const SCIP_Real* lb, /**< lower bounds of new columns */
1250 const SCIP_Real* ub, /**< upper bounds of new columns */
1251 char** /*colnames*/, /**< column names, or NULL */
1252 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1253 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1254 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1255 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1256 )
1257{
1258 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1259
1260 assert(lpi != NULL);
1261 assert(lpi->spx != NULL);
1262 assert(obj != NULL);
1263 assert(lb != NULL);
1264 assert(ub != NULL);
1265 assert(nnonz == 0 || beg != NULL);
1266 assert(nnonz == 0 || ind != NULL);
1267 assert(nnonz == 0 || val != NULL);
1268 assert(nnonz >= 0);
1269 assert(ncols >= 0);
1270
1271 invalidateSolution(lpi);
1272
1273 assert( lpi->spx->preStrongbranchingBasisFreed() );
1274
1275#ifndef NDEBUG
1276 if ( nnonz > 0 )
1277 {
1278 /* perform check that no new rows are added - this is likely to be a mistake */
1279 int nrows = lpi->spx->numRowsReal();
1280 for (int j = 0; j < nnonz; ++j)
1281 {
1282 assert( 0 <= ind[j] && ind[j] < nrows );
1283 assert( val[j] != 0.0 );
1284 }
1285 }
1286#endif
1287
1288 SPxSCIP* spx = lpi->spx;
1289 try
1290 {
1291 LPColSet cols(ncols);
1292 DSVector colVector(ncols);
1293 int start;
1294 int last;
1295 int i;
1296
1297 /* create column vectors with coefficients and bounds */
1298 for( i = 0; i < ncols; ++i )
1299 {
1300 colVector.clear();
1301 if( nnonz > 0 )
1302 {
1303 start = beg[i];
1304 last = (i == ncols-1 ? nnonz : beg[i+1]);
1305 colVector.add( last-start, &ind[start], &val[start] );
1306 }
1307 cols.add(obj[i], lb[i], colVector, ub[i]);
1308 }
1309 spx->addColsReal(cols);
1310 }
1311#ifndef NDEBUG
1312 catch( const SPxException& x )
1313 {
1314 std::string s = x.what();
1315 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1316#else
1317 catch( const SPxException& )
1318 {
1319#endif
1320 return SCIP_LPERROR;
1321 }
1322
1323 return SCIP_OKAY;
1324}
1325
1326/** deletes all columns in the given range from LP */
1328 SCIP_LPI* lpi, /**< LP interface structure */
1329 int firstcol, /**< first column to be deleted */
1330 int lastcol /**< last column to be deleted */
1331 )
1332{
1333 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1334
1335 assert(lpi != NULL);
1336 assert(lpi->spx != NULL);
1337 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
1338
1339 invalidateSolution(lpi);
1340
1341 assert( lpi->spx->preStrongbranchingBasisFreed() );
1342
1343 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRangeReal(firstcol, lastcol) );
1344
1345 return SCIP_OKAY;
1346}
1347
1348/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1350 SCIP_LPI* lpi, /**< LP interface structure */
1351 int* dstat /**< deletion status of columns
1352 * input: 1 if column should be deleted, 0 if not
1353 * output: new position of column, -1 if column was deleted */
1354 )
1355{
1356 int ncols;
1357 int i;
1358
1359 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
1360
1361 assert(lpi != NULL);
1362 assert(lpi->spx != NULL);
1363 assert(dstat != NULL);
1364
1365 invalidateSolution(lpi);
1366
1367 assert( lpi->spx->preStrongbranchingBasisFreed() );
1368
1369 ncols = lpi->spx->numColsReal();
1370
1371 /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
1372 for( i = 0; i < ncols; ++i )
1373 dstat[i] *= -1;
1374
1375 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColsReal(dstat) );
1376
1377 return SCIP_OKAY;
1378}
1379
1380/** adds rows to the LP */
1382 SCIP_LPI* lpi, /**< LP interface structure */
1383 int nrows, /**< number of rows to be added */
1384 const SCIP_Real* lhs, /**< left hand sides of new rows */
1385 const SCIP_Real* rhs, /**< right hand sides of new rows */
1386 char** /*rownames*/, /**< row names, or NULL */
1387 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1388 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
1389 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
1390 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1391 )
1392{
1393 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
1394
1395 assert(lpi != NULL);
1396 assert(lpi->spx != NULL);
1397 assert(lhs != NULL);
1398 assert(rhs != NULL);
1399 assert(nnonz == 0 || beg != NULL);
1400 assert(nnonz == 0 || ind != NULL);
1401 assert(nnonz == 0 || val != NULL);
1402
1403 invalidateSolution(lpi);
1404
1405 assert( lpi->spx->preStrongbranchingBasisFreed() );
1406
1407#ifndef NDEBUG
1408 if ( nnonz > 0 )
1409 {
1410 /* perform check that no new columns are added - this is likely to be a mistake */
1411 int ncols = lpi->spx->numColsReal();
1412 for (int j = 0; j < nnonz; ++j)
1413 {
1414 assert( val[j] != 0.0 );
1415 assert( 0 <= ind[j] && ind[j] < ncols );
1416 }
1417 }
1418#endif
1419
1420 try
1421 {
1422 SPxSCIP* spx = lpi->spx;
1423 LPRowSet rows(nrows);
1424 DSVector rowVector;
1425 int start;
1426 int last;
1427 int i;
1428
1429 /* create row vectors with given sides */
1430 for( i = 0; i < nrows; ++i )
1431 {
1432 rowVector.clear();
1433 if( nnonz > 0 )
1434 {
1435 start = beg[i];
1436 last = (i == nrows-1 ? nnonz : beg[i+1]);
1437 rowVector.add( last-start, &ind[start], &val[start] );
1438 }
1439 rows.add(lhs[i], rowVector, rhs[i]);
1440 }
1441 spx->addRowsReal(rows);
1442 }
1443#ifndef NDEBUG
1444 catch( const SPxException& x )
1445 {
1446 std::string s = x.what();
1447 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1448#else
1449 catch( const SPxException& )
1450 {
1451#endif
1452 return SCIP_LPERROR;
1453 }
1454
1455 return SCIP_OKAY;
1456}
1457
1458/** deletes all rows in the given range from LP */
1460 SCIP_LPI* lpi, /**< LP interface structure */
1461 int firstrow, /**< first row to be deleted */
1462 int lastrow /**< last row to be deleted */
1463 )
1464{
1465 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
1466
1467 assert(lpi != NULL);
1468 assert(lpi->spx != NULL);
1469 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
1470
1471 invalidateSolution(lpi);
1472
1473 assert( lpi->spx->preStrongbranchingBasisFreed() );
1474
1475 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRangeReal(firstrow, lastrow) );
1476
1477 return SCIP_OKAY;
1478}
1479
1480/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
1482 SCIP_LPI* lpi, /**< LP interface structure */
1483 int* dstat /**< deletion status of rows
1484 * input: 1 if row should be deleted, 0 if not
1485 * output: new position of row, -1 if row was deleted */
1486 )
1487{
1488 int nrows;
1489 int i;
1490
1491 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
1492
1493 assert(lpi != NULL);
1494 assert(lpi->spx != NULL);
1495
1496 invalidateSolution(lpi);
1497
1498 assert( lpi->spx->preStrongbranchingBasisFreed() );
1499
1500 nrows = lpi->spx->numRowsReal();
1501
1502 /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
1503 for( i = 0; i < nrows; ++i )
1504 dstat[i] *= -1;
1505
1506 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowsReal(dstat) );
1507
1508 return SCIP_OKAY;
1509}
1510
1511/** clears the whole LP */
1513 SCIP_LPI* lpi /**< LP interface structure */
1514 )
1515{
1516 SCIPdebugMessage("calling SCIPlpiClear()\n");
1517
1518 assert(lpi != NULL);
1519 assert(lpi->spx != NULL);
1520
1521 invalidateSolution(lpi);
1522
1523 assert( lpi->spx->preStrongbranchingBasisFreed() );
1524 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clearLPReal() );
1525
1526 return SCIP_OKAY;
1527}
1528
1529/** changes lower and upper bounds of columns */
1531 SCIP_LPI* lpi, /**< LP interface structure */
1532 int ncols, /**< number of columns to change bounds for */
1533 const int* ind, /**< column indices or NULL if ncols is zero */
1534 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
1535 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
1536 )
1537{
1538 int i;
1539
1540 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
1541
1542 assert(lpi != NULL);
1543 assert(lpi->spx != NULL);
1544 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
1545 if( ncols <= 0 )
1546 return SCIP_OKAY;
1547
1548 invalidateSolution(lpi);
1549
1550 assert( lpi->spx->preStrongbranchingBasisFreed() );
1551
1552 try
1553 {
1554 for( i = 0; i < ncols; ++i )
1555 {
1556 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
1557
1558 if ( SCIPlpiIsInfinity(lpi, lb[i]) )
1559 {
1560 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
1561 return SCIP_LPERROR;
1562 }
1563 if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
1564 {
1565 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
1566 return SCIP_LPERROR;
1567 }
1568
1569 lpi->spx->changeBoundsReal(ind[i], lb[i], ub[i]);
1570 assert(lpi->spx->lowerReal(ind[i]) <= lpi->spx->upperReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
1571 }
1572 }
1573#ifndef NDEBUG
1574 catch( const SPxException& x )
1575 {
1576 std::string s = x.what();
1577 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1578#else
1579 catch( const SPxException& )
1580 {
1581#endif
1582 return SCIP_LPERROR;
1583 }
1584
1585 return SCIP_OKAY;
1586}
1587
1588/** changes left and right hand sides of rows */
1590 SCIP_LPI* lpi, /**< LP interface structure */
1591 int nrows, /**< number of rows to change sides for */
1592 const int* ind, /**< row indices */
1593 const SCIP_Real* lhs, /**< new values for left hand sides */
1594 const SCIP_Real* rhs /**< new values for right hand sides */
1595 )
1596{
1597 int i;
1598
1599 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
1600
1601 assert(lpi != NULL);
1602 assert(lpi->spx != NULL);
1603 assert(ind != NULL);
1604 assert(lhs != NULL);
1605 assert(rhs != NULL);
1606 if( nrows <= 0 )
1607 return SCIP_OKAY;
1608
1609 invalidateSolution(lpi);
1610
1611 assert( lpi->spx->preStrongbranchingBasisFreed() );
1612
1613 try
1614 {
1615 for( i = 0; i < nrows; ++i )
1616 {
1617 assert(0 <= ind[i] && ind[i] < lpi->spx->numRowsReal());
1618 lpi->spx->changeRangeReal(ind[i], lhs[i], rhs[i]);
1619 assert(lpi->spx->lhsReal(ind[i]) <= lpi->spx->rhsReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
1620 }
1621 }
1622#ifndef NDEBUG
1623 catch( const SPxException& x )
1624 {
1625 std::string s = x.what();
1626 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1627#else
1628 catch( const SPxException& )
1629 {
1630#endif
1631 return SCIP_LPERROR;
1632 }
1633
1634 return SCIP_OKAY;
1635}
1636
1637/** changes a single coefficient */
1639 SCIP_LPI* lpi, /**< LP interface structure */
1640 int row, /**< row number of coefficient to change */
1641 int col, /**< column number of coefficient to change */
1642 SCIP_Real newval /**< new value of coefficient */
1643 )
1644{
1645 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
1646
1647 assert(lpi != NULL);
1648 assert(lpi->spx != NULL);
1649 assert(0 <= row && row < lpi->spx->numRowsReal());
1650 assert(0 <= col && col < lpi->spx->numColsReal());
1651
1652 invalidateSolution(lpi);
1653
1654 assert( lpi->spx->preStrongbranchingBasisFreed() );
1655
1656 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElementReal(row, col, newval) );
1657
1658 return SCIP_OKAY;
1659}
1660
1661/** changes the objective sense */
1663 SCIP_LPI* lpi, /**< LP interface structure */
1664 SCIP_OBJSEN objsen /**< new objective sense */
1665 )
1666{
1667 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
1668
1669 assert(lpi != NULL);
1670 assert(lpi->spx != NULL);
1671
1672 invalidateSolution(lpi);
1673
1674 assert( lpi->spx->preStrongbranchingBasisFreed() );
1675
1676 SOPLEX_TRY( lpi->messagehdlr, (void) lpi->spx->setIntParam(SoPlex::OBJSENSE, objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE ) );
1677
1678 return SCIP_OKAY;
1679}
1680
1681/** changes objective values of columns in the LP */
1683 SCIP_LPI* lpi, /**< LP interface structure */
1684 int ncols, /**< number of columns to change objective value for */
1685 const int* ind, /**< column indices to change objective value for */
1686 const SCIP_Real* obj /**< new objective values for columns */
1687 )
1688{
1689 int i;
1690
1691 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
1692
1693 assert(lpi != NULL);
1694 assert(lpi->spx != NULL);
1695 assert(ind != NULL);
1696 assert(obj != NULL);
1697
1698 invalidateSolution(lpi);
1699
1700 assert( lpi->spx->preStrongbranchingBasisFreed() );
1701
1702 try
1703 {
1704 for( i = 0; i < ncols; ++i )
1705 {
1706 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
1707 lpi->spx->changeObjReal(ind[i], obj[i]);
1708 }
1709 }
1710#ifndef NDEBUG
1711 catch( const SPxException& x )
1712 {
1713 std::string s = x.what();
1714 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1715#else
1716 catch( const SPxException& )
1717 {
1718#endif
1719 return SCIP_LPERROR;
1720 }
1721
1722 return SCIP_OKAY;
1723}
1724
1725/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
1727 SCIP_LPI* lpi, /**< LP interface structure */
1728 int row, /**< row number to scale */
1729 SCIP_Real scaleval /**< scaling multiplier */
1730 )
1731{
1732 SCIP_Real lhs;
1733 SCIP_Real rhs;
1734
1735 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
1736
1737 assert(lpi != NULL);
1738 assert(lpi->spx != NULL);
1739 assert(scaleval != 0.0);
1740
1741 try
1742 {
1743 invalidateSolution(lpi);
1744
1745 assert( lpi->spx->preStrongbranchingBasisFreed() );
1746
1747 /* get the row vector and the row's sides */
1748#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1749 SVector rowvec = lpi->spx->rowVectorRealInternal(row);
1750#else
1751 SVector rowvec = lpi->spx->rowVectorReal(row);
1752#endif
1753 lhs = lpi->spx->lhsReal(row);
1754 rhs = lpi->spx->rhsReal(row);
1755
1756 /* scale the row vector */
1757 rowvec *= scaleval;
1758
1759 /* adjust the sides */
1760 if( lhs > -lpi->spx->realParam(SoPlex::INFTY) )
1761 lhs *= scaleval;
1762 else if( scaleval < 0.0 )
1763 lhs = lpi->spx->realParam(SoPlex::INFTY);
1764 if( rhs < lpi->spx->realParam(SoPlex::INFTY) )
1765 rhs *= scaleval;
1766 else if( scaleval < 0.0 )
1767 rhs = -lpi->spx->realParam(SoPlex::INFTY);
1768 if( scaleval < 0.0 )
1769 {
1770 SCIP_Real oldlhs = lhs;
1771 lhs = rhs;
1772 rhs = oldlhs;
1773 }
1774
1775 /* create the new row */
1776 LPRow lprow(lhs, rowvec, rhs);
1777
1778 /* change the row in the LP */
1779 lpi->spx->changeRowReal(row, lprow);
1780 assert(lpi->spx->lhsReal(row) <= lpi->spx->rhsReal(row));
1781 }
1782#ifndef NDEBUG
1783 catch( const SPxException& x )
1784 {
1785 std::string s = x.what();
1786 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1787#else
1788 catch( const SPxException& )
1789 {
1790#endif
1791 return SCIP_LPERROR;
1792 }
1793
1794 return SCIP_OKAY;
1795}
1796
1797/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
1798 * are divided by the scalar; for negative scalars, the column's bounds are switched
1799 */
1801 SCIP_LPI* lpi, /**< LP interface structure */
1802 int col, /**< column number to scale */
1803 SCIP_Real scaleval /**< scaling multiplier */
1804 )
1805{
1806 SCIP_Real obj;
1807 SCIP_Real lb;
1808 SCIP_Real ub;
1809
1810 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
1811
1812 assert(lpi != NULL);
1813 assert(lpi->spx != NULL);
1814 assert(scaleval != 0.0);
1815
1816 try
1817 {
1818 invalidateSolution(lpi);
1819
1820 assert( lpi->spx->preStrongbranchingBasisFreed() );
1821
1822 /* get the col vector and the col's bounds and objective value */
1823#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1824 SVector colvec = lpi->spx->colVectorRealInternal(col);
1825#else
1826 SVector colvec = lpi->spx->colVectorReal(col);
1827#endif
1828 obj = lpi->spx->objReal(col);
1829 lb = lpi->spx->lowerReal(col);
1830 ub = lpi->spx->upperReal(col);
1831
1832 /* scale the col vector */
1833 colvec *= scaleval;
1834
1835 /* scale the objective value */
1836 obj *= scaleval;
1837
1838 /* adjust the bounds */
1839 if( lb > -lpi->spx->realParam(SoPlex::INFTY) )
1840 lb /= scaleval;
1841 else if( scaleval < 0.0 )
1842 lb = lpi->spx->realParam(SoPlex::INFTY);
1843 if( ub < lpi->spx->realParam(SoPlex::INFTY) )
1844 ub /= scaleval;
1845 else if( scaleval < 0.0 )
1846 ub = -lpi->spx->realParam(SoPlex::INFTY);
1847 if( scaleval < 0.0 )
1848 {
1849 SCIP_Real oldlb = lb;
1850 lb = ub;
1851 ub = oldlb;
1852 }
1853
1854 /* create the new col (in LPCol's constructor, the upper bound is given first!) */
1855 LPCol lpcol(obj, colvec, ub, lb);
1856
1857 /* change the col in the LP */
1858 lpi->spx->changeColReal(col, lpcol);
1859 assert(lpi->spx->lowerReal(col) <= lpi->spx->upperReal(col));
1860 }
1861#ifndef NDEBUG
1862 catch( const SPxException& x )
1863 {
1864 std::string s = x.what();
1865 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1866#else
1867 catch( const SPxException& )
1868 {
1869#endif
1870 return SCIP_LPERROR;
1871 }
1872
1873 return SCIP_OKAY;
1874}
1875
1876/**@} */
1877
1878
1879
1880
1881/*
1882 * Data Accessing Methods
1883 */
1884
1885/**@name Data Accessing Methods */
1886/**@{ */
1887
1888/** gets the number of rows in the LP */
1890 SCIP_LPI* lpi, /**< LP interface structure */
1891 int* nrows /**< pointer to store the number of rows */
1892 )
1893{
1894 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
1895
1896 assert(lpi != NULL);
1897 assert(lpi->spx != NULL);
1898 assert(nrows != NULL);
1899
1900 *nrows = lpi->spx->numRowsReal();
1901
1902 return SCIP_OKAY;
1903}
1904
1905/** gets the number of columns in the LP */
1907 SCIP_LPI* lpi, /**< LP interface structure */
1908 int* ncols /**< pointer to store the number of cols */
1909 )
1910{
1911 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
1912
1913 assert(lpi != NULL);
1914 assert(lpi->spx != NULL);
1915 assert(ncols != NULL);
1916
1917 *ncols = lpi->spx->numColsReal();
1918
1919 return SCIP_OKAY;
1920}
1921
1922/** gets the number of nonzero elements in the LP constraint matrix */
1924 SCIP_LPI* lpi, /**< LP interface structure */
1925 int* nnonz /**< pointer to store the number of nonzeros */
1926 )
1927{
1928 int i;
1929
1930 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
1931
1932 assert(lpi != NULL);
1933 assert(lpi->spx != NULL);
1934 assert(nnonz != NULL);
1935
1936 /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
1937 *nnonz = 0;
1938 if( lpi->spx->numRowsReal() < lpi->spx->numColsReal() )
1939 {
1940 for( i = 0; i < lpi->spx->numRowsReal(); ++i )
1941#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1942 (*nnonz) += lpi->spx->rowVectorRealInternal(i).size();
1943#else
1944 (*nnonz) += lpi->spx->rowVectorReal(i).size();
1945#endif
1946 }
1947 else
1948 {
1949 for( i = 0; i < lpi->spx->numColsReal(); ++i )
1950#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1951 (*nnonz) += lpi->spx->colVectorRealInternal(i).size();
1952#else
1953 (*nnonz) += lpi->spx->colVectorReal(i).size();
1954#endif
1955 }
1956
1957 return SCIP_OKAY;
1958}
1959
1960/** gets columns from LP problem object; the arrays have to be large enough to store all values
1961 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
1962 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1963 */
1965 SCIP_LPI* lpi, /**< LP interface structure */
1966 int firstcol, /**< first column to get from LP */
1967 int lastcol, /**< last column to get from LP */
1968 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
1969 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
1970 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1971 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1972 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1973 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1974 )
1975{
1976 int i;
1977 int j;
1978
1979 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
1980
1981 assert(lpi != NULL);
1982 assert(lpi->spx != NULL);
1983 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
1984 assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
1985 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1986
1987 if( lb != NULL )
1988 {
1989#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1990 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
1991 {
1992 DVector lbvec(lpi->spx->numColsReal());
1993 DVector ubvec(lpi->spx->numColsReal());
1994 lpi->spx->getLowerReal(lbvec);
1995 lpi->spx->getUpperReal(ubvec);
1996 for( i = firstcol; i <= lastcol; ++i )
1997 {
1998 lb[i-firstcol] = lbvec[i];
1999 ub[i-firstcol] = ubvec[i];
2000 }
2001 }
2002 else
2003 {
2004 const Vector& lbvec = lpi->spx->lowerRealInternal();
2005 const Vector& ubvec = lpi->spx->upperRealInternal();
2006 for( i = firstcol; i <= lastcol; ++i )
2007 {
2008 lb[i-firstcol] = lbvec[i];
2009 ub[i-firstcol] = ubvec[i];
2010 }
2011 }
2012#else
2013 const Vector& lbvec = lpi->spx->lowerReal();
2014 const Vector& ubvec = lpi->spx->upperReal();
2015
2016 for( i = firstcol; i <= lastcol; ++i )
2017 {
2018 lb[i-firstcol] = lbvec[i];
2019 ub[i-firstcol] = ubvec[i];
2020 }
2021#endif
2022 }
2023
2024 if( nnonz != NULL )
2025 {
2026 *nnonz = 0;
2027 for( i = firstcol; i <= lastcol; ++i )
2028 {
2029 beg[i-firstcol] = *nnonz;
2030
2031#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2032 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2033 {
2034 DSVector cvec;
2035 lpi->spx->getColVectorReal(i, cvec);
2036 for( j = 0; j < cvec.size(); ++j )
2037 {
2038 ind[*nnonz] = cvec.index(j);
2039 val[*nnonz] = cvec.value(j);
2040 (*nnonz)++;
2041 }
2042 }
2043 else
2044 {
2045 const SVector& cvec = lpi->spx->colVectorRealInternal(i);
2046 for( j = 0; j < cvec.size(); ++j )
2047 {
2048 ind[*nnonz] = cvec.index(j);
2049 val[*nnonz] = cvec.value(j);
2050 (*nnonz)++;
2051 }
2052 }
2053#else
2054 const SVector& cvec = lpi->spx->colVectorReal(i);
2055 for( j = 0; j < cvec.size(); ++j )
2056 {
2057 ind[*nnonz] = cvec.index(j);
2058 val[*nnonz] = cvec.value(j);
2059 (*nnonz)++;
2060 }
2061#endif
2062 }
2063 }
2064
2065 return SCIP_OKAY;
2066}
2067
2068/** gets rows from LP problem object; the arrays have to be large enough to store all values.
2069 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2070 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2071 */
2073 SCIP_LPI* lpi, /**< LP interface structure */
2074 int firstrow, /**< first row to get from LP */
2075 int lastrow, /**< last row to get from LP */
2076 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2077 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2078 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2079 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2080 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2081 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2082 )
2083{
2084 int i;
2085 int j;
2086
2087 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2088
2089 assert(lpi != NULL);
2090 assert(lpi->spx != NULL);
2091 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
2092 assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2093 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2094
2095 if( lhs != NULL )
2096 {
2097#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2098 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2099 {
2100 DVector lhsvec(lpi->spx->numRowsReal());
2101 DVector rhsvec(lpi->spx->numRowsReal());
2102 lpi->spx->getLhsReal(lhsvec);
2103 lpi->spx->getRhsReal(rhsvec);
2104 for( i = firstrow; i <= lastrow; ++i )
2105 {
2106 lhs[i-firstrow] = lhsvec[i];
2107 rhs[i-firstrow] = rhsvec[i];
2108 }
2109 }
2110 else
2111 {
2112 const Vector& lhsvec = lpi->spx->lhsRealInternal();
2113 const Vector& rhsvec = lpi->spx->rhsRealInternal();
2114 for( i = firstrow; i <= lastrow; ++i )
2115 {
2116 lhs[i-firstrow] = lhsvec[i];
2117 rhs[i-firstrow] = rhsvec[i];
2118 }
2119 }
2120#else
2121 const Vector& lhsvec = lpi->spx->lhsReal();
2122 const Vector& rhsvec = lpi->spx->rhsReal();
2123 for( i = firstrow; i <= lastrow; ++i )
2124 {
2125 lhs[i-firstrow] = lhsvec[i];
2126 rhs[i-firstrow] = rhsvec[i];
2127 }
2128#endif
2129 }
2130
2131 if( nnonz != NULL )
2132 {
2133 *nnonz = 0;
2134 for( i = firstrow; i <= lastrow; ++i )
2135 {
2136 beg[i-firstrow] = *nnonz;
2137
2138#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2139 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2140 {
2141 DSVector rvec;
2142 lpi->spx->getRowVectorReal(i, rvec);
2143 for( j = 0; j < rvec.size(); ++j )
2144 {
2145 ind[*nnonz] = rvec.index(j);
2146 val[*nnonz] = rvec.value(j);
2147 (*nnonz)++;
2148 }
2149 }
2150 else
2151 {
2152 const SVector& rvec = lpi->spx->rowVectorRealInternal(i);
2153 for( j = 0; j < rvec.size(); ++j )
2154 {
2155 ind[*nnonz] = rvec.index(j);
2156 val[*nnonz] = rvec.value(j);
2157 (*nnonz)++;
2158 }
2159 }
2160#else
2161 const SVector& rvec = lpi->spx->rowVectorReal(i);
2162 for( j = 0; j < rvec.size(); ++j )
2163 {
2164 ind[*nnonz] = rvec.index(j);
2165 val[*nnonz] = rvec.value(j);
2166 (*nnonz)++;
2167 }
2168#endif
2169 }
2170 }
2171
2172 return SCIP_OKAY;
2173}
2174
2175/** gets column names */
2177 SCIP_LPI* lpi, /**< LP interface structure */
2178 int firstcol, /**< first column to get name from LP */
2179 int lastcol, /**< last column to get name from LP */
2180 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2181 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2182 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2183 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2184 )
2185{
2186 assert( lpi != NULL );
2187 assert( lpi->spx != NULL );
2188 assert( colnames != NULL || namestoragesize == 0 );
2189 assert( namestorage != NULL || namestoragesize == 0 );
2190 assert( namestoragesize >= 0 );
2191 assert( storageleft != NULL );
2192 assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal() );
2193
2194 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2195
2196// lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2197
2198 return SCIP_OKAY;
2199}
2200
2201/** gets row names */
2203 SCIP_LPI* lpi, /**< LP interface structure */
2204 int firstrow, /**< first row to get name from LP */
2205 int lastrow, /**< last row to get name from LP */
2206 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2207 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2208 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2209 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2210 )
2211{
2212 assert( lpi != NULL );
2213 assert( lpi->spx != NULL );
2214 assert( rownames != NULL || namestoragesize == 0 );
2215 assert( namestorage != NULL || namestoragesize == 0 );
2216 assert( namestoragesize >= 0 );
2217 assert( storageleft != NULL );
2218 assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal() );
2219
2220 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2221
2222// lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2223
2224 return SCIP_OKAY;
2225}
2226
2227/** gets objective sense of the LP */
2229 SCIP_LPI* lpi, /**< LP interface structure */
2230 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2231 )
2232{
2233 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2234
2235 assert(lpi != NULL);
2236 assert(lpi->spx != NULL);
2237 assert(objsen != NULL);
2238
2239 *objsen = (lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2240
2241 return SCIP_OKAY;
2242}
2243
2244/** gets objective coefficients from LP problem object */
2246 SCIP_LPI* lpi, /**< LP interface structure */
2247 int firstcol, /**< first column to get objective coefficient for */
2248 int lastcol, /**< last column to get objective coefficient for */
2249 SCIP_Real* vals /**< array to store objective coefficients */
2250 )
2251{
2252 int i;
2253
2254 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2255
2256 assert(lpi != NULL);
2257 assert(lpi->spx != NULL);
2258 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
2259 assert(vals != NULL);
2260
2261 for( i = firstcol; i <= lastcol; ++i )
2262 vals[i-firstcol] = lpi->spx->objReal(i);
2263
2264 return SCIP_OKAY;
2265}
2266
2267/** gets current bounds from LP problem object */
2269 SCIP_LPI* lpi, /**< LP interface structure */
2270 int firstcol, /**< first column to get objective value for */
2271 int lastcol, /**< last column to get objective value for */
2272 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2273 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2274 )
2275{
2276 int i;
2277
2278 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2279
2280 assert(lpi != NULL);
2281 assert(lpi->spx != NULL);
2282 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
2283
2284 for( i = firstcol; i <= lastcol; ++i )
2285 {
2286 if( lbs != NULL )
2287 lbs[i-firstcol] = lpi->spx->lowerReal(i);
2288 if( ubs != NULL )
2289 ubs[i-firstcol] = lpi->spx->upperReal(i);
2290 }
2291
2292 return SCIP_OKAY;
2293}
2294
2295/** gets current row sides from LP problem object */
2297 SCIP_LPI* lpi, /**< LP interface structure */
2298 int firstrow, /**< first row to get sides for */
2299 int lastrow, /**< last row to get sides for */
2300 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2301 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2302 )
2303{
2304 int i;
2305
2306 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2307
2308 assert(lpi != NULL);
2309 assert(lpi->spx != NULL);
2310 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
2311
2312 for( i = firstrow; i <= lastrow; ++i )
2313 {
2314 if( lhss != NULL )
2315 lhss[i-firstrow] = lpi->spx->lhsReal(i);
2316 if( rhss != NULL )
2317 rhss[i-firstrow] = lpi->spx->rhsReal(i);
2318 }
2319
2320 return SCIP_OKAY;
2321}
2322
2323/** gets a single coefficient */
2325 SCIP_LPI* lpi, /**< LP interface structure */
2326 int row, /**< row number of coefficient */
2327 int col, /**< column number of coefficient */
2328 SCIP_Real* val /**< pointer to store the value of the coefficient */
2329 )
2330{
2331 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2332
2333 assert(lpi != NULL);
2334 assert(lpi->spx != NULL);
2335 assert(0 <= col && col < lpi->spx->numColsReal());
2336 assert(0 <= row && row < lpi->spx->numRowsReal());
2337 assert(val != NULL);
2338
2339#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2340 *val = lpi->spx->coefReal(row, col);
2341#else
2342 *val = lpi->spx->colVectorReal(col)[row];
2343#endif
2344
2345 return SCIP_OKAY;
2346}
2347
2348/**@} */
2349
2350
2351
2352
2353/*
2354 * Solving Methods
2355 */
2356
2357/**@name Solving Methods */
2358/**@{ */
2359
2360/** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2361static
2363 SCIP_LPI* lpi /**< LP interface structure */
2364 )
2365{
2366 assert( lpi != NULL );
2367 assert( lpi->spx != NULL );
2368
2369 SPxOut::Verbosity verbosity;
2370 /* store and set verbosity */
2371 verbosity = lpi->spx->spxout.getVerbosity();
2372 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2373
2374 SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows\n", lpi->spx->numColsReal(), lpi->spx->numRowsReal());
2375
2376 invalidateSolution(lpi);
2377
2378 assert( lpi->spx->preStrongbranchingBasisFreed() );
2379
2380#ifdef SCIP_WITH_LPSCHECK
2381 lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2382#endif
2383
2384 /* delete starting basis if solving from scratch */
2385 if( lpi->spx->getFromScratch() )
2386 {
2387 try
2388 {
2389 lpi->spx->clearBasis();
2390 }
2391#ifndef NDEBUG
2392 catch(const SPxException& x)
2393 {
2394 std::string s = x.what();
2395 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2396#else
2397 catch(const SPxException&)
2398 {
2399#endif
2400 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
2401 return SCIP_LPERROR;
2402 }
2403 }
2404 assert(!lpi->spx->getFromScratch() || lpi->spx->status() == SPxSolver::NO_PROBLEM);
2405
2406 SPxSolver::Status status = lpi->spx->doSolve();
2407 SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->status(), lpi->spx->basisStatus());
2408 lpi->solved = TRUE;
2409
2410 /* restore verbosity */
2411 lpi->spx->spxout.setVerbosity(verbosity);
2412
2413 switch( status )
2414 {
2415 case SPxSolver::ABORT_TIME:
2416 case SPxSolver::ABORT_ITER:
2417 case SPxSolver::ABORT_VALUE:
2418 case SPxSolver::SINGULAR:
2419 case SPxSolver::REGULAR:
2420 case SPxSolver::UNKNOWN:
2421 case SPxSolver::OPTIMAL:
2422#if SOPLEX_APIVERSION >= 3
2423 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2424#endif
2425 case SPxSolver::UNBOUNDED:
2426 case SPxSolver::INFEASIBLE:
2427 return SCIP_OKAY;
2428 default:
2429 return SCIP_LPERROR;
2430 } /*lint !e788*/
2431}
2432
2433/** calls primal simplex to solve the LP */
2435 SCIP_LPI* lpi /**< LP interface structure */
2436 )
2437{
2438 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2439
2440 assert(lpi != NULL);
2441 assert(lpi->spx != NULL);
2442
2443 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_PRIMAL);
2444 return spxSolve(lpi);
2445}
2446
2447/** calls dual simplex to solve the LP */
2449 SCIP_LPI* lpi /**< LP interface structure */
2450 )
2451{
2452 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2453
2454 assert(lpi != NULL);
2455 assert(lpi->spx != NULL);
2456
2457 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2458 return spxSolve(lpi);
2459}
2460
2461/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
2463 SCIP_LPI* lpi, /**< LP interface structure */
2464 SCIP_Bool crossover /**< perform crossover */
2465 )
2466{ /*lint --e{715}*/
2467 assert(lpi != NULL);
2468 assert(lpi->spx != NULL);
2469
2470 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
2471
2472 /* Since SoPlex does not support barrier we switch to DUAL */
2473 return SCIPlpiSolveDual(lpi);
2474}
2475
2476/** start strong branching - call before any strongbranching */
2478 SCIP_LPI* lpi /**< LP interface structure */
2479 )
2480{
2481 assert(lpi != NULL);
2482 assert(lpi->spx != NULL);
2483
2484 assert( lpi->spx->preStrongbranchingBasisFreed() );
2485 lpi->spx->savePreStrongbranchingBasis();
2486
2487 return SCIP_OKAY;
2488}
2489
2490/** end strong branching - call after any strongbranching */
2492 SCIP_LPI* lpi /**< LP interface structure */
2493 )
2494{
2495 assert(lpi != NULL);
2496 assert(lpi->spx != NULL);
2497
2498 assert( ! lpi->spx->preStrongbranchingBasisFreed() );
2499 lpi->spx->restorePreStrongbranchingBasis();
2500 lpi->spx->freePreStrongbranchingBasis();
2501
2502 return SCIP_OKAY;
2503}
2504
2505/** performs strong branching iterations on one arbitrary candidate */
2506static
2508 SCIP_LPI* lpi, /**< LP interface structure */
2509 int col, /**< column to apply strong branching on */
2510 SCIP_Real psol, /**< current primal solution value of column */
2511 int itlim, /**< iteration limit for strong branchings */
2512 SCIP_Real* down, /**< stores dual bound after branching column down */
2513 SCIP_Real* up, /**< stores dual bound after branching column up */
2514 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2515 * otherwise, it can only be used as an estimate value */
2516 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2517 * otherwise, it can only be used as an estimate value */
2518 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2519 )
2520{
2521 assert(lpi != NULL);
2522 assert(lpi->spx != NULL);
2523
2524 SPxSCIP* spx;
2525 SPxSolver::Status status;
2526 SCIP_Real oldlb;
2527 SCIP_Real oldub;
2528 SCIP_Real newlb;
2529 SCIP_Real newub;
2530 bool fromparentbasis;
2531 bool error;
2532 int oldItlim;
2533 SPxOut::Verbosity verbosity;
2534
2535 /* store and set verbosity */
2536 verbosity = lpi->spx->spxout.getVerbosity();
2537 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2538
2539 SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
2540
2541 assert(lpi != NULL);
2542 assert(lpi->spx != NULL);
2543 /* assert(down != NULL);
2544 * assert(up != NULL); temporary hack for cloud branching */
2545 assert(downvalid != NULL);
2546 assert(upvalid != NULL);
2547
2548 spx = lpi->spx;
2549#ifndef STRONGBRANCH_RESTOREBASIS
2550 fromparentbasis = false;
2551#endif
2552 error = false;
2553 oldItlim = spx->intParam(SoPlex::ITERLIMIT);
2554
2555 /* get current bounds of column */
2556 oldlb = spx->lowerReal(col);
2557 oldub = spx->upperReal(col);
2558
2559 *downvalid = FALSE;
2560 *upvalid = FALSE;
2561
2562 if( iter != NULL )
2563 *iter = 0;
2564
2565 /* set the algorithm type to use dual simplex */
2566 (void) spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2567
2568 /* down branch */
2569 newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
2570 if( newub >= oldlb - 0.5 && down != NULL )
2571 {
2572 SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
2573
2574 spx->changeUpperReal(col, newub);
2575 assert(spx->lowerReal(col) <= spx->upperReal(col));
2576
2577 (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2578 do
2579 {
2580#ifndef STRONGBRANCH_RESTOREBASIS
2581 SCIP_Bool repeatstrongbranching;
2582#endif
2583#ifdef SCIP_WITH_LPSCHECK
2584 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2585#endif
2586#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2587#if SOPLEX_APIVERSION > 11
2588 status = spx->optimize(spx->getInterrupt());
2589#else
2590 status = spx->optimize();
2591#endif
2592#else
2593 status = spx->solve();
2594#endif
2595 SCIPdebugMessage(" --> Terminate with status %d\n", status);
2596 switch( status )
2597 {
2598 case SPxSolver::OPTIMAL:
2599 *down = spx->objValueReal();
2600 *downvalid = TRUE;
2601 SCIPdebugMessage(" --> Terminate with value %f\n", *down);
2602 break;
2603 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2604 case SPxSolver::ABORT_ITER:
2605 case SPxSolver::ABORT_CYCLING:
2606#if SOPLEX_APIVERSION >= 3
2607 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2608#endif
2609 *down = spx->objValueReal();
2610 break;
2611 case SPxSolver::ABORT_VALUE:
2612 case SPxSolver::INFEASIBLE:
2613 *down = spx->getObjLimit();
2614 *downvalid = TRUE;
2615 break;
2616 default:
2617 error = true;
2618 break;
2619 } /*lint !e788*/
2620 if( iter != NULL )
2621 (*iter) += spx->numIterations();
2622
2623#ifdef STRONGBRANCH_RESTOREBASIS
2624 /* we restore the pre-strong-branching basis by default (and don't solve again) */
2625 assert( ! spx->preStrongbranchingBasisFreed() );
2626 spx->restorePreStrongbranchingBasis();
2627 fromparentbasis = false;
2628#else
2629 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2630 * pre-strong-branching basis and try again with reduced iteration limit */
2631#if SOPLEX_APIVERSION >= 3
2632 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
2633 || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
2634#else
2635 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
2636 && !fromparentbasis && spx->numIterations() < itlim);
2637#endif
2638 if( repeatstrongbranching )
2639 {
2640 SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n",
2641 itlim - spx->numIterations());
2642 spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2643 spx->restorePreStrongbranchingBasis();
2644 fromparentbasis = true;
2645 error = false;
2646 }
2647 /* otherwise don't solve again */
2648 else
2649 fromparentbasis = false;
2650#endif
2651 }
2652 while( fromparentbasis );
2653
2654 spx->changeUpperReal(col, oldub);
2655 assert(spx->lowerReal(col) <= spx->upperReal(col));
2656 }
2657 else if( down != NULL )
2658 {
2659 *down = spx->getObjLimit();
2660 *downvalid = TRUE;
2661 }
2662 else
2663 *downvalid = TRUE;
2664
2665 /* up branch */
2666 if( !error )
2667 {
2668 newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
2669 if( newlb <= oldub + 0.5 && up != NULL )
2670 {
2671 SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
2672
2673 spx->changeLowerReal(col, newlb);
2674 assert(spx->lowerReal(col) <= spx->upperReal(col));
2675
2676 (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2677 do
2678 {
2679#ifndef STRONGBRANCH_RESTOREBASIS
2680 SCIP_Bool repeatstrongbranching;
2681#endif
2682#ifdef SCIP_WITH_LPSCHECK
2683 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2684#endif
2685#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2686#if SOPLEX_APIVERSION > 11
2687 status = spx->optimize(spx->getInterrupt());
2688#else
2689 status = spx->optimize();
2690#endif
2691#else
2692 status = spx->solve();
2693#endif
2694 SCIPdebugMessage(" --> Terminate with status %d\n", status);
2695 switch( status )
2696 {
2697 case SPxSolver::OPTIMAL:
2698 *up = spx->objValueReal();
2699 *upvalid = TRUE;
2700 SCIPdebugMessage(" --> Terminate with value %f\n", spx->objValueReal());
2701 break;
2702 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2703 case SPxSolver::ABORT_ITER:
2704 case SPxSolver::ABORT_CYCLING:
2705#if SOPLEX_APIVERSION >= 3
2706 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2707#endif
2708 *up = spx->objValueReal();
2709 break;
2710 case SPxSolver::ABORT_VALUE:
2711 case SPxSolver::INFEASIBLE:
2712 *up = spx->getObjLimit();
2713 *upvalid = TRUE;
2714 break;
2715 default:
2716 error = true;
2717 break;
2718 } /*lint !e788*/
2719 if( iter != NULL )
2720 (*iter) += spx->numIterations();
2721
2722#ifdef STRONGBRANCH_RESTOREBASIS
2723 /* we restore the pre-strong-branching basis by default (and don't solve again) */
2724 assert( ! spx->preStrongbranchingBasisFreed() );
2725 spx->restorePreStrongbranchingBasis();
2726 fromparentbasis = false;
2727#else
2728 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2729 * pre-strong-branching basis and try again with reduced iteration limit */
2730#if SOPLEX_APIVERSION >= 3
2731 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
2732 || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
2733#else
2734 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
2735 && !fromparentbasis && spx->numIterations() < itlim);
2736#endif
2737 if( repeatstrongbranching )
2738 {
2739 SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->numIterations());
2740 spx->restorePreStrongbranchingBasis();
2741 spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2742 error = false;
2743 fromparentbasis = true;
2744 }
2745 /* otherwise don't solve again */
2746 else
2747 fromparentbasis = false;
2748#endif
2749 }
2750 while( fromparentbasis );
2751
2752 spx->changeLowerReal(col, oldlb);
2753 assert(spx->lowerReal(col) <= spx->upperReal(col));
2754 }
2755 else if( up != NULL )
2756 {
2757 *up = spx->getObjLimit();
2758 *upvalid = TRUE;
2759 }
2760 else
2761 *upvalid = TRUE;
2762 }
2763
2764 /* reset old iteration limit */
2765 (void) spx->setIntParam(SoPlex::ITERLIMIT, oldItlim);
2766
2767 /* restore verbosity */
2768 lpi->spx->spxout.setVerbosity(verbosity);
2769
2770 if( error )
2771 {
2772 SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status)); /*lint !e644*/
2773 return SCIP_LPERROR;
2774 }
2775
2776 return SCIP_OKAY;
2777}
2778
2779/** performs strong branching iterations on one @b fractional candidate */
2781 SCIP_LPI* lpi, /**< LP interface structure */
2782 int col, /**< column to apply strong branching on */
2783 SCIP_Real psol, /**< fractional current primal solution value of column */
2784 int itlim, /**< iteration limit for strong branchings */
2785 SCIP_Real* down, /**< stores dual bound after branching column down */
2786 SCIP_Real* up, /**< stores dual bound after branching column up */
2787 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2788 * otherwise, it can only be used as an estimate value */
2789 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2790 * otherwise, it can only be used as an estimate value */
2791 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2792 )
2793{
2794 SCIP_RETCODE retcode;
2795
2796 /* pass call on to lpiStrongbranch() */
2797 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2798
2799 /* pass SCIP_LPERROR to SCIP without a back trace */
2800 if( retcode == SCIP_LPERROR )
2801 return SCIP_LPERROR;
2802
2803 /* evaluate retcode */
2804 SCIP_CALL( retcode );
2805
2806 return SCIP_OKAY;
2807}
2808
2809/** performs strong branching iterations on given @b fractional candidates */
2811 SCIP_LPI* lpi, /**< LP interface structure */
2812 int* cols, /**< columns to apply strong branching on */
2813 int ncols, /**< number of columns */
2814 SCIP_Real* psols, /**< fractional current primal solution values of columns */
2815 int itlim, /**< iteration limit for strong branchings */
2816 SCIP_Real* down, /**< stores dual bounds after branching columns down */
2817 SCIP_Real* up, /**< stores dual bounds after branching columns up */
2818 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2819 * otherwise, they can only be used as an estimate values */
2820 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2821 * otherwise, they can only be used as an estimate values */
2822 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2823 )
2824{
2825 SCIP_RETCODE retcode;
2826
2827 assert( cols != NULL );
2828 assert( psols != NULL );
2829 assert( down != NULL );
2830 assert( up != NULL );
2831 assert( downvalid != NULL );
2832 assert( upvalid != NULL );
2833 assert( down != NULL );
2834
2835 if ( iter != NULL )
2836 *iter = 0;
2837
2838 for (int j = 0; j < ncols; ++j)
2839 {
2840 /* pass call on to lpiStrongbranch() */
2841 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2842
2843 /* pass SCIP_LPERROR to SCIP without a back trace */
2844 if( retcode == SCIP_LPERROR )
2845 return SCIP_LPERROR;
2846
2847 /* evaluate retcode */
2848 SCIP_CALL( retcode );
2849 }
2850 return SCIP_OKAY;
2851}
2852
2853/** performs strong branching iterations on one candidate with @b integral value */
2855 SCIP_LPI* lpi, /**< LP interface structure */
2856 int col, /**< column to apply strong branching on */
2857 SCIP_Real psol, /**< current integral primal solution value of column */
2858 int itlim, /**< iteration limit for strong branchings */
2859 SCIP_Real* down, /**< stores dual bound after branching column down */
2860 SCIP_Real* up, /**< stores dual bound after branching column up */
2861 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2862 * otherwise, it can only be used as an estimate value */
2863 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2864 * otherwise, it can only be used as an estimate value */
2865 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2866 )
2867{
2868 SCIP_RETCODE retcode;
2869
2870 /* pass call on to lpiStrongbranch() */
2871 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2872
2873 /* pass SCIP_LPERROR to SCIP without a back trace */
2874 if( retcode == SCIP_LPERROR )
2875 return SCIP_LPERROR;
2876
2877 /* evaluate retcode */
2878 SCIP_CALL( retcode );
2879
2880 return SCIP_OKAY;
2881}
2882
2883/** performs strong branching iterations on given candidates with @b integral values */
2885 SCIP_LPI* lpi, /**< LP interface structure */
2886 int* cols, /**< columns to apply strong branching on */
2887 int ncols, /**< number of columns */
2888 SCIP_Real* psols, /**< current integral primal solution values of columns */
2889 int itlim, /**< iteration limit for strong branchings */
2890 SCIP_Real* down, /**< stores dual bounds after branching columns down */
2891 SCIP_Real* up, /**< stores dual bounds after branching columns up */
2892 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2893 * otherwise, they can only be used as an estimate values */
2894 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2895 * otherwise, they can only be used as an estimate values */
2896 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2897 )
2898{
2899 SCIP_RETCODE retcode;
2900
2901 assert( cols != NULL );
2902 assert( psols != NULL );
2903 assert( down != NULL );
2904 assert( up != NULL );
2905 assert( downvalid != NULL );
2906 assert( upvalid != NULL );
2907 assert( down != NULL );
2908
2909 if ( iter != NULL )
2910 *iter = 0;
2911
2912 for (int j = 0; j < ncols; ++j)
2913 {
2914 /* pass call on to lpiStrongbranch() */
2915 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2916
2917 /* pass SCIP_LPERROR to SCIP without a back trace */
2918 if( retcode == SCIP_LPERROR )
2919 return SCIP_LPERROR;
2920
2921 /* evaluate retcode */
2922 SCIP_CALL( retcode );
2923 }
2924
2925 return SCIP_OKAY;
2926}
2927/**@} */
2928
2929
2930
2931
2932/*
2933 * Solution Information Methods
2934 */
2935
2936/**@name Solution Information Methods */
2937/**@{ */
2938
2939/** returns whether a solve method was called after the last modification of the LP */
2941 SCIP_LPI* lpi /**< LP interface structure */
2942 )
2943{
2944 assert(lpi != NULL);
2945
2946 return lpi->solved;
2947}
2948
2949/** gets information about primal and dual feasibility of the current LP solution
2950 *
2951 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
2952 * returns true. If the LP is changed, this information might be invalidated.
2953 *
2954 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
2955 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
2956 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
2957 * the problem might actually be feasible).
2958 */
2960 SCIP_LPI* lpi, /**< LP interface structure */
2961 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
2962 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
2963 )
2964{
2965 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
2966
2967 assert(lpi != NULL);
2968 assert(primalfeasible != NULL);
2969 assert(dualfeasible != NULL);
2970
2971 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
2972 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
2973
2974 return SCIP_OKAY;
2975}
2976
2977/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
2978 * this does not necessarily mean, that the solver knows and can return the primal ray
2979 */
2981 SCIP_LPI* lpi /**< LP interface structure */
2982 )
2983{
2984 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
2985
2986 assert(lpi != NULL);
2987 assert(lpi->spx != NULL);
2988
2989 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2990}
2991
2992/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
2993 * and the solver knows and can return the primal ray
2994 */
2996 SCIP_LPI* lpi /**< LP interface structure */
2997 )
2998{
2999 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
3000
3001 assert(lpi != NULL);
3002 assert(lpi->spx != NULL);
3003
3004 return lpi->spx->hasPrimalRay();
3005}
3006
3007/** returns TRUE iff LP is proven to be primal unbounded */
3009 SCIP_LPI* lpi /**< LP interface structure */
3010 )
3011{
3012 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
3013
3014 assert(lpi != NULL);
3015 assert(lpi->spx != NULL);
3016
3017 assert(lpi->spx->status() != SPxSolver::UNBOUNDED || lpi->spx->basisStatus() == SPxBasis::UNBOUNDED);
3018
3019 /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
3020 * feasible point; hence we have to check the perturbation
3021 */
3022 return lpi->spx->status() == SPxSolver::UNBOUNDED;
3023}
3024
3025/** returns TRUE iff LP is proven to be primal infeasible */
3027 SCIP_LPI* lpi /**< LP interface structure */
3028 )
3029{
3030 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3031
3032 assert(lpi != NULL);
3033 assert(lpi->spx != NULL);
3034
3035 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
3036}
3037
3038/** returns TRUE iff LP is proven to be primal feasible */
3040 SCIP_LPI* lpi /**< LP interface structure */
3041 )
3042{
3043 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3044
3045 assert(lpi != NULL);
3046 assert(lpi->spx != NULL);
3047
3048 return lpi->spx->basisStatus() == SPxBasis::OPTIMAL || lpi->spx->basisStatus() == SPxBasis::PRIMAL;
3049}
3050
3051/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3052 * this does not necessarily mean, that the solver knows and can return the dual ray
3053 */
3055 SCIP_LPI* lpi /**< LP interface structure */
3056 )
3057{
3058 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3059
3060 assert(lpi != NULL);
3061 assert(lpi->spx != NULL);
3062
3063 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
3064}
3065
3066/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3067 * and the solver knows and can return the dual ray
3068 */
3070 SCIP_LPI* lpi /**< LP interface structure */
3071 )
3072{
3073 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3074
3075 assert(lpi != NULL);
3076 assert(lpi->spx != NULL);
3077
3078 return lpi->spx->hasDualFarkas();
3079}
3080
3081/** returns TRUE iff LP is dual unbounded */
3083 SCIP_LPI* lpi /**< LP interface structure */
3084 )
3085{
3086 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3087
3088 assert(lpi != NULL);
3089 assert(lpi->spx != NULL);
3090
3091 return lpi->spx->status() == SPxSolver::INFEASIBLE && lpi->spx->basisStatus() == SPxBasis::DUAL;
3092}
3093
3094/** returns TRUE iff LP is dual infeasible */
3096 SCIP_LPI* lpi /**< LP interface structure */
3097 )
3098{
3099 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3100
3101 assert(lpi != NULL);
3102 assert(lpi->spx != NULL);
3103
3104 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
3105}
3106
3107/** returns TRUE iff LP is proven to be dual feasible */
3109 SCIP_LPI* lpi /**< LP interface structure */
3110 )
3111{
3112 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3113
3114 assert(lpi != NULL);
3115 assert(lpi->spx != NULL);
3116
3117 return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL) || lpi->spx->basisStatus() == SPxBasis::DUAL;
3118}
3119
3120/** returns TRUE iff LP was solved to optimality */
3122 SCIP_LPI* lpi /**< LP interface structure */
3123 )
3124{
3125 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3126
3127 assert(lpi != NULL);
3128 assert(lpi->spx != NULL);
3129 assert((lpi->spx->basisStatus() == SPxBasis::OPTIMAL)
3131
3132 return (lpi->spx->status() == SPxSolver::OPTIMAL);
3133}
3134
3135/** returns TRUE iff current LP solution is stable
3136 *
3137 * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3138 * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3139 * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3140 * SCIPlpiIsStable() should return false.
3141 */
3143 SCIP_LPI* lpi /**< LP interface structure */
3144 )
3145{
3146 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3147
3148 assert(lpi != NULL);
3149 assert(lpi->spx != NULL);
3150
3151 if( lpi->spx->status() == SPxSolver::ERROR || lpi->spx->status() == SPxSolver::SINGULAR )
3152 return FALSE;
3153#if SOPLEX_APIVERSION >= 3
3154 if( lpi->spx->status() == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS )
3155 return FALSE;
3156#endif
3157 /* only if we have a regular basis and the condition limit is set, we compute the condition number of the basis;
3158 * everything above the specified threshold is then counted as instable
3159 */
3160 if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3161 {
3162 SCIP_RETCODE retcode;
3163 SCIP_Real kappa;
3164
3166 if( retcode != SCIP_OKAY )
3167 {
3168 SCIPABORT();
3169 }
3170 assert(kappa != SCIP_INVALID); /*lint !e777*/
3171
3172 if( kappa > lpi->conditionlimit )
3173 return FALSE;
3174 }
3175 /* if an objective limit is set and SoPlex claims that it is exceeded, we should check that this is indeed the case;
3176 * if not this points at numerical instability; note that this aligns with an assert in lp.c */
3177 if( SCIPlpiIsObjlimExc(lpi) )
3178 {
3179 SCIP_Real objlimit = lpi->spx->getObjLimit();
3180 SCIP_Real objvalue = lpi->spx->objValueReal();
3181
3182 if( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE )
3183 {
3184 objlimit *= -1.0;
3185 objvalue *= -1.0;
3186 }
3187 if( !SCIPlpiIsInfinity(lpi, objlimit) && LTrel(objvalue, objlimit, 2*lpi->spx->opttol()) )
3188 return FALSE;
3189 }
3190 return TRUE;
3191}
3192
3193/** returns TRUE iff the objective limit was reached */
3195 SCIP_LPI* lpi /**< LP interface structure */
3196 )
3197{
3198 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3199
3200 assert(lpi != NULL);
3201 assert(lpi->spx != NULL);
3202
3203 return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
3204}
3205
3206/** returns TRUE iff the iteration limit was reached */
3208 SCIP_LPI* lpi /**< LP interface structure */
3209 )
3210{
3211 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3212
3213 assert(lpi != NULL);
3214 assert(lpi->spx != NULL);
3215
3216 return (lpi->spx->status() == SPxSolver::ABORT_ITER);
3217}
3218
3219/** returns TRUE iff the time limit was reached */
3221 SCIP_LPI* lpi /**< LP interface structure */
3222 )
3223{
3224 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3225
3226 assert(lpi != NULL);
3227 assert(lpi->spx != NULL);
3228
3229 return (lpi->spx->status() == SPxSolver::ABORT_TIME);
3230}
3231
3232/** returns the internal solution status of the solver */
3234 SCIP_LPI* lpi /**< LP interface structure */
3235 )
3236{
3237 SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
3238
3239 assert(lpi != NULL);
3240 assert(lpi->spx != NULL);
3241
3242 return static_cast<int>(lpi->spx->status());
3243}
3244
3245/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3247 SCIP_LPI* lpi, /**< LP interface structure */
3248 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3249 )
3250{ /*lint --e{715}*/
3251 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3252
3253 assert(lpi != NULL);
3254 assert(lpi->spx != NULL);
3255 assert(success != NULL);
3256
3257#if SOPLEX_APIVERSION >= 4
3258 *success = lpi->spx->ignoreUnscaledViolations();
3259#else
3260 *success = FALSE;
3261#endif
3262
3263 return SCIP_OKAY;
3264}
3265
3266/** gets objective value of solution */
3268 SCIP_LPI* lpi, /**< LP interface structure */
3269 SCIP_Real* objval /**< stores the objective value */
3270 )
3271{
3272 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3273
3274 assert(lpi != NULL);
3275 assert(lpi->spx != NULL);
3276 assert(objval != NULL);
3277
3278 *objval = lpi->spx->objValueReal();
3279
3280 return SCIP_OKAY;
3281}
3282
3283/** gets primal and dual solution vectors for feasible LPs
3284 *
3285 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3286 * SCIPlpiIsOptimal() returns true.
3287 */
3289 SCIP_LPI* lpi, /**< LP interface structure */
3290 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3291 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3292 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3293 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3294 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3295 )
3296{
3297 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3298
3299 assert(lpi != NULL);
3300 assert(lpi->spx != NULL);
3301
3302 if( objval != NULL )
3303 *objval = lpi->spx->objValueReal();
3304
3305 try
3306 {
3307 if( primsol != NULL )
3308 {
3309#if SOPLEX_APIVERSION > 10
3310 (void)lpi->spx->getPrimalReal(primsol, lpi->spx->numColsReal());
3311#else
3312 Vector tmp(lpi->spx->numColsReal(), primsol);
3313 (void)lpi->spx->getPrimalReal(tmp);
3314#endif
3315 }
3316 if( dualsol != NULL )
3317 {
3318#if SOPLEX_APIVERSION > 10
3319 (void)lpi->spx->getDualReal(dualsol, lpi->spx->numRowsReal());
3320#else
3321 Vector tmp(lpi->spx->numRowsReal(), dualsol);
3322 (void)lpi->spx->getDualReal(tmp);
3323#endif
3324 }
3325 if( activity != NULL )
3326 {
3327#if SOPLEX_APIVERSION > 10
3328 (void)lpi->spx->getSlacksReal(activity, lpi->spx->numRowsReal()); /* in SoPlex, the activities are called "slacks" */
3329#else
3330 Vector tmp(lpi->spx->numRowsReal(), activity);
3331 (void)lpi->spx->getSlacksReal(tmp); /* in SoPlex, the activities are called "slacks" */
3332#endif
3333 }
3334 if( redcost != NULL )
3335 {
3336#if SOPLEX_APIVERSION > 10
3337 (void)lpi->spx->getRedCostReal(redcost, lpi->spx->numColsReal());
3338#else
3339 Vector tmp(lpi->spx->numColsReal(), redcost);
3340 (void)lpi->spx->getRedCostReal(tmp);
3341#endif
3342 }
3343 }
3344#ifndef NDEBUG
3345 catch( const SPxException& x )
3346 {
3347 std::string s = x.what();
3348 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3349#else
3350 catch( const SPxException& )
3351 {
3352#endif
3353 return SCIP_LPERROR;
3354 }
3355
3356 return SCIP_OKAY;
3357}
3358
3359/** gets primal ray for unbounded LPs */
3361 SCIP_LPI* lpi, /**< LP interface structure */
3362 SCIP_Real* ray /**< primal ray */
3363 )
3364{ /*lint --e{715}*/
3365 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3366
3367 assert(lpi != NULL);
3368 assert(lpi->spx != NULL);
3369 assert(lpi->spx->hasPrimalRay());
3370 assert(ray != NULL);
3371
3372 try
3373 {
3374#if SOPLEX_APIVERSION > 10
3375 (void)lpi->spx->getPrimalRayReal(ray, lpi->spx->numColsReal());
3376#else
3377 Vector tmp(lpi->spx->numColsReal(), ray);
3378 (void)lpi->spx->getPrimalRayReal(tmp);
3379#endif
3380 }
3381#ifndef NDEBUG
3382 catch( const SPxException& x )
3383 {
3384 std::string s = x.what();
3385 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3386#else
3387 catch( const SPxException& )
3388 {
3389#endif
3390 return SCIP_LPERROR;
3391 }
3392
3393 return SCIP_OKAY;
3394}
3395
3396/** gets dual farkas proof for infeasibility */
3398 SCIP_LPI* lpi, /**< LP interface structure */
3399 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3400 )
3401{
3402 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3403
3404 assert(lpi != NULL);
3405 assert(lpi->spx != NULL);
3406 assert(lpi->spx->hasDualFarkas());
3407 assert(dualfarkas != NULL);
3408
3409 try
3410 {
3411#if SOPLEX_APIVERSION > 10
3412 (void)lpi->spx->getDualFarkasReal(dualfarkas, lpi->spx->numRowsReal());
3413#else
3414 Vector tmp(lpi->spx->numRowsReal(), dualfarkas);
3415 (void)lpi->spx->getDualFarkasReal(tmp);
3416#endif
3417 }
3418#ifndef NDEBUG
3419 catch( const SPxException& x )
3420 {
3421 std::string s = x.what();
3422 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3423#else
3424 catch( const SPxException& )
3425 {
3426#endif
3427 return SCIP_LPERROR;
3428 }
3429
3430 return SCIP_OKAY;
3431}
3432
3433/** gets the number of LP iterations of the last solve call */
3435 SCIP_LPI* lpi, /**< LP interface structure */
3436 int* iterations /**< pointer to store the number of iterations of the last solve call */
3437 )
3438{
3439 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3440
3441 assert(lpi != NULL);
3442 assert(lpi->spx != NULL);
3443 assert(iterations != NULL);
3444
3445 *iterations = lpi->spx->numIterations();
3446
3447 return SCIP_OKAY;
3448}
3449
3450/** gets information about the quality of an LP solution
3451 *
3452 * Such information is usually only available, if also a (maybe not optimal) solution is available.
3453 * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
3454 */
3456 SCIP_LPI* lpi, /**< LP interface structure */
3457 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3458 SCIP_Real* quality /**< pointer to store quality number */
3459 )
3460{
3461 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3462
3463 assert(lpi != NULL);
3464 assert(quality != NULL);
3465
3466 bool success;
3467
3468 SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3469
3470 switch( qualityindicator )
3471 {
3473 success = lpi->spx->getEstimatedCondition(*quality);
3474 break;
3475
3477 success = lpi->spx->getExactCondition(*quality);
3478 break;
3479
3480 default:
3481 SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3482 return SCIP_INVALIDDATA;
3483 }
3484
3485 if( !success )
3486 {
3487 SCIPdebugMessage("problem computing condition number\n");
3488 *quality = SCIP_INVALID;
3489 }
3490
3491 return SCIP_OKAY;
3492}
3493
3494/**@} */
3495
3496
3497
3498
3499/*
3500 * LP Basis Methods
3501 */
3502
3503/**@name LP Basis Methods */
3504/**@{ */
3505
3506
3507/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
3509 SCIP_LPI* lpi, /**< LP interface structure */
3510 int* cstat, /**< array to store column basis status, or NULL */
3511 int* rstat /**< array to store row basis status, or NULL */
3512 )
3513{
3514 int i;
3515
3516 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
3517
3518 assert(lpi != NULL);
3519 assert(lpi->spx != NULL);
3520
3521 assert( lpi->spx->preStrongbranchingBasisFreed() );
3522
3523 if( rstat != NULL )
3524 {
3525 for( i = 0; i < lpi->spx->numRowsReal(); ++i )
3526 {
3527 switch( lpi->spx->basisRowStatus(i) )
3528 {
3529 case SPxSolver::BASIC:
3530 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3531 break;
3532 case SPxSolver::FIXED:
3533 case SPxSolver::ON_LOWER:
3534 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3535 break;
3536 case SPxSolver::ON_UPPER:
3537 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3538 break;
3539 case SPxSolver::ZERO:
3540 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3541 return SCIP_LPERROR;
3542 case SPxSolver::UNDEFINED:
3543 default:
3544 SCIPerrorMessage("invalid basis status\n");
3545 SCIPABORT();
3546 return SCIP_INVALIDDATA; /*lint !e527*/
3547 }
3548 }
3549 }
3550
3551 if( cstat != NULL )
3552 {
3553 for( i = 0; i < lpi->spx->numColsReal(); ++i )
3554 {
3555// SCIP_Real val = 0.0;
3556 switch( lpi->spx->basisColStatus(i) )
3557 {
3558 case SPxSolver::BASIC:
3559 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3560 break;
3561 case SPxSolver::FIXED:
3562 /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
3563 * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
3564 * this case there is no problem at all. If the basis is saved and/or used in some other
3565 * solver, it usually is very cheap to perform the pivots necessary to get an optimal
3566 * basis.
3567 * @todo implement getRedCostEst()
3568 * */
3569// SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
3570// if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
3571// cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3572// else
3573 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3574 break;
3575 case SPxSolver::ON_LOWER:
3576 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3577 break;
3578 case SPxSolver::ON_UPPER:
3579 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3580 break;
3581 case SPxSolver::ZERO:
3582 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3583 break;
3584 case SPxSolver::UNDEFINED:
3585 default:
3586 SCIPerrorMessage("invalid basis status\n");
3587 SCIPABORT();
3588 return SCIP_INVALIDDATA; /*lint !e527*/
3589 }
3590 }
3591 }
3592
3593 return SCIP_OKAY;
3594}
3595
3596/** sets current basis status for columns and rows */
3598 SCIP_LPI* lpi, /**< LP interface structure */
3599 const int* cstat, /**< array with column basis status */
3600 const int* rstat /**< array with row basis status */
3601 )
3602{
3603 int i;
3604 int ncols;
3605 int nrows;
3606
3607 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
3608
3609 assert(lpi != NULL);
3610 assert(lpi->spx != NULL);
3611
3612 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
3613 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
3614
3615 assert(cstat != NULL || ncols == 0);
3616 assert(rstat != NULL || nrows == 0);
3617
3618 assert( lpi->spx->preStrongbranchingBasisFreed() );
3619 invalidateSolution(lpi);
3620
3621 DataArray<SPxSolver::VarStatus>& _colstat = lpi->spx->colStat();
3622 DataArray<SPxSolver::VarStatus>& _rowstat = lpi->spx->rowStat();
3623
3624 _colstat.reSize(ncols);
3625 _rowstat.reSize(nrows);
3626
3627 for( i = 0; i < nrows; ++i )
3628 {
3629 switch( rstat[i] ) /*lint !e613*/
3630 {
3632 _rowstat[i] = SPxSolver::ON_LOWER;
3633 break;
3635 _rowstat[i] = SPxSolver::BASIC;
3636 break;
3638 _rowstat[i] = SPxSolver::ON_UPPER;
3639 break;
3640 case SCIP_BASESTAT_ZERO:
3641 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3642 return SCIP_LPERROR; /*lint !e429*/
3643 default:
3644 SCIPerrorMessage("invalid basis status\n");
3645 SCIPABORT();
3646 return SCIP_INVALIDDATA; /*lint !e527*/
3647 }
3648 }
3649
3650 for( i = 0; i < ncols; ++i )
3651 {
3652 switch( cstat[i] ) /*lint !e613*/
3653 {
3655 _colstat[i] = SPxSolver::ON_LOWER;
3656 break;
3658 _colstat[i] = SPxSolver::BASIC;
3659 break;
3661 _colstat[i] = SPxSolver::ON_UPPER;
3662 break;
3663 case SCIP_BASESTAT_ZERO:
3664 _colstat[i] = SPxSolver::ZERO;
3665 break;
3666 default:
3667 SCIPerrorMessage("invalid basis status\n");
3668 SCIPABORT();
3669 return SCIP_INVALIDDATA; /*lint !e527*/
3670 }
3671 }
3672
3673 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(_rowstat.get_ptr(), _colstat.get_ptr()) );
3674 lpi->spx->freePreStrongbranchingBasis();
3675
3676 return SCIP_OKAY;
3677}
3678
3679/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
3681 SCIP_LPI* lpi, /**< LP interface structure */
3682 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
3683 )
3684{
3685 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
3686
3687 assert(lpi != NULL);
3688 assert(lpi->spx != NULL);
3689 assert(bind != NULL);
3690
3691 assert(lpi->spx->preStrongbranchingBasisFreed());
3692
3693 lpi->spx->getBasisInd(bind);
3694
3695 return SCIP_OKAY;
3696}
3697
3698
3699/** get row of inverse basis matrix B^-1
3700 *
3701 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3702 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3703 * see also the explanation in lpi.h.
3704 */
3706 SCIP_LPI* lpi, /**< LP interface structure */
3707 int r, /**< row number */
3708 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
3709 int* inds, /**< array to store the non-zero indices, or NULL */
3710 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3711 * (-1: if we do not store sparsity information) */
3712 )
3713{
3714 SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
3715
3716 assert(lpi != NULL);
3717 assert(lpi->spx != NULL);
3718 assert(lpi->spx->preStrongbranchingBasisFreed());
3719 assert(coef != NULL);
3720
3721 assert(r >= 0);
3722 assert(r < lpi->spx->numRowsReal());
3723
3724 if( ! lpi->spx->getBasisInverseRowReal(r, coef, inds, ninds) )
3725 return SCIP_LPERROR;
3726
3727 return SCIP_OKAY;
3728}
3729
3730/** get column of inverse basis matrix B^-1
3731 *
3732 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3733 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3734 * see also the explanation in lpi.h.
3735 */
3737 SCIP_LPI* lpi, /**< LP interface structure */
3738 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
3739 * you have to call SCIPlpiGetBasisInd() to get the array which links the
3740 * B^-1 column numbers to the row and column numbers of the LP!
3741 * c must be between 0 and nrows-1, since the basis has the size
3742 * nrows * nrows */
3743 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
3744 int* inds, /**< array to store the non-zero indices, or NULL */
3745 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3746 * (-1: if we do not store sparsity information) */
3747 )
3748{
3749 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
3750
3751 assert( lpi != NULL );
3752 assert( lpi->spx != NULL );
3753 assert( lpi->spx->preStrongbranchingBasisFreed() );
3754 assert(coef != NULL);
3755
3756 if( ! lpi->spx->getBasisInverseColReal(c, coef, inds, ninds) )
3757 return SCIP_LPERROR;
3758
3759 return SCIP_OKAY;
3760}
3761
3762/** get row of inverse basis matrix times constraint matrix B^-1 * A
3763 *
3764 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3765 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3766 * see also the explanation in lpi.h.
3767 */
3769 SCIP_LPI* lpi, /**< LP interface structure */
3770 int r, /**< row number */
3771 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
3772 SCIP_Real* coef, /**< vector to return coefficients of the row */
3773 int* inds, /**< array to store the non-zero indices, or NULL */
3774 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3775 * (-1: if we do not store sparsity information) */
3776 )
3777{
3778 SCIP_Real* buf;
3779 SCIP_Real* binv;
3780 int nrows;
3781 int ncols;
3782 int c;
3783
3784 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
3785
3786 assert(lpi != NULL);
3787 assert(lpi->spx != NULL);
3788 assert( lpi->spx->preStrongbranchingBasisFreed() );
3789 assert(coef != NULL);
3790
3791 nrows = lpi->spx->numRowsReal();
3792 ncols = lpi->spx->numColsReal();
3793 buf = NULL;
3794
3795 /* get (or calculate) the row in B^-1 */
3796 if( binvrow == NULL )
3797 {
3798 SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
3799 SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
3800 binv = buf;
3801 }
3802 else
3803 binv = const_cast<SCIP_Real*>(binvrow);
3804
3805 assert(binv != NULL);
3806
3807 /* mark sparsity pattern as invalid */
3808 if( ninds != NULL )
3809 *ninds = -1;
3810
3811 // @todo exploit sparsity in binv by looping over nrows
3812 /* calculate the scalar product of the row in B^-1 and A */
3813 Vector binvvec(nrows, binv);
3814
3815#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3816 /* temporary unscaled column of A */
3817 DSVector acol;
3818#endif
3819
3820 for( c = 0; c < ncols; ++c )
3821 {
3822#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3823 lpi->spx->getColVectorReal(c, acol);
3824 coef[c] = binvvec * acol; /* scalar product */ /*lint !e1702*/
3825#else
3826 coef[c] = binvvec * lpi->spx->colVectorReal(c); /* scalar product */ /*lint !e1702*/
3827#endif
3828 }
3829
3830 /* free memory if it was temporarily allocated */
3832
3833 return SCIP_OKAY;
3834}
3835
3836/** get column of inverse basis matrix times constraint matrix B^-1 * A
3837 *
3838 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3839 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3840 * see also the explanation in lpi.h.
3841 */
3843 SCIP_LPI* lpi, /**< LP interface structure */
3844 int c, /**< column number */
3845 SCIP_Real* coef, /**< vector to return coefficients of the column */
3846 int* inds, /**< array to store the non-zero indices, or NULL */
3847 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3848 * (-1: if we do not store sparsity information) */
3849 )
3850{ /*lint --e{715}*/
3851 /* create a new uninitialized full vector */
3852 DVector col(lpi->spx->numRowsReal());
3853
3854#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3855 /* temporary sparse vector used for unscaling (memory is automatically enlarged) */
3856 DSVector colsparse;
3857#endif
3858
3859 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
3860
3861 assert( lpi != NULL );
3862 assert( lpi->spx != NULL );
3863 assert( lpi->spx->preStrongbranchingBasisFreed() );
3864 assert(coef != NULL);
3865
3866 /* extract column c of A */
3867 assert(c >= 0);
3868 assert(c < lpi->spx->numColsReal());
3869
3870 /* @todo implement this with sparse vectors */
3871 /* mark sparsity pattern as invalid */
3872 if( ninds != NULL )
3873 *ninds = -1;
3874
3875 /* col needs to be cleared because copying colVectorReal only regards nonzeros */
3876 col.clear();
3877
3878#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3879 lpi->spx->getColVectorReal(c, colsparse);
3880 /* the copy is necessary to transform the sparse column into a dense vector */
3881 col = colsparse;
3882#else
3883 col = lpi->spx->colVectorReal(c);
3884#endif
3885
3886 /* solve */
3887 if( ! lpi->spx->getBasisInverseTimesVecReal(col.get_ptr(), coef) )
3888 return SCIP_LPERROR;
3889
3890 return SCIP_OKAY;
3891}
3892
3893/**@} */
3894
3895
3896
3897
3898/*
3899 * LP State Methods
3900 */
3901
3902/**@name LP State Methods */
3903/**@{ */
3904
3905/** stores LPi state (like basis information) into lpistate object */
3907 SCIP_LPI* lpi, /**< LP interface structure */
3908 BMS_BLKMEM* blkmem, /**< block memory */
3909 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3910 )
3911{
3912 int ncols;
3913 int nrows;
3914
3915 SCIPdebugMessage("calling SCIPlpiGetState()\n");
3916
3917 assert(blkmem != NULL);
3918 assert(lpi != NULL);
3919 assert(lpi->spx != NULL);
3920 assert(lpistate != NULL);
3921
3922 assert( lpi->spx->preStrongbranchingBasisFreed() );
3923
3924 ncols = lpi->spx->numColsReal();
3925 nrows = lpi->spx->numRowsReal();
3926 assert(ncols >= 0);
3927 assert(nrows >= 0);
3928
3929 /* allocate lpistate data */
3930 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
3931
3932 /* allocate enough memory for storing uncompressed basis information */
3933 SCIP_CALL( ensureCstatMem(lpi, ncols) );
3934 SCIP_CALL( ensureRstatMem(lpi, nrows) );
3935
3936 /* get unpacked basis information */
3937 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
3938
3939 /* pack LPi state data */
3940 (*lpistate)->ncols = ncols;
3941 (*lpistate)->nrows = nrows;
3942 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
3943
3944 return SCIP_OKAY;
3945}
3946
3947/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
3948 * columns and rows since the state was stored with SCIPlpiGetState()
3949 */
3951 SCIP_LPI* lpi, /**< LP interface structure */
3952 BMS_BLKMEM* /*blkmem*/, /**< block memory */
3953 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
3954 )
3955{
3956 int lpncols;
3957 int lpnrows;
3958 int i;
3959
3960 SCIPdebugMessage("calling SCIPlpiSetState()\n");
3961
3962 assert(lpi != NULL);
3963 assert(lpi->spx != NULL);
3964 assert(lpistate != NULL);
3965 /* assert(blkmem != NULL); */
3966
3967 assert( lpi->spx->preStrongbranchingBasisFreed() );
3968
3969 lpncols = lpi->spx->numColsReal();
3970 lpnrows = lpi->spx->numRowsReal();
3971 assert(lpistate->ncols <= lpncols);
3972 assert(lpistate->nrows <= lpnrows);
3973
3974 /* allocate enough memory for storing uncompressed basis information */
3975 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
3976 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
3977
3978 /* unpack LPi state data */
3979 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
3980
3981 /* extend the basis to the current LP beyond the previously existing columns */
3982 for( i = lpistate->ncols; i < lpncols; ++i )
3983 {
3984 SCIP_Real bnd = lpi->spx->lowerReal(i);
3985 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3986 {
3987 /* if lower bound is +/- infinity -> try upper bound */
3988 bnd = lpi->spx->lowerReal(i);
3989 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3990 /* variable is free */
3991 lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3992 else
3993 /* use finite upper bound */
3994 lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3995 }
3996 else
3997 /* use finite lower bound */
3998 lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3999 }
4000 for( i = lpistate->nrows; i < lpnrows; ++i )
4001 lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4002
4003 /* load basis information */
4004 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4005
4006 return SCIP_OKAY;
4007}
4008
4009/** clears current LPi state (like basis information) of the solver */
4011 SCIP_LPI* lpi /**< LP interface structure */
4012 )
4013{ /*lint --e{715}*/
4014 SCIPdebugMessage("calling SCIPlpiClearState()\n");
4015
4016 assert(lpi != NULL);
4017 assert(lpi->spx != NULL);
4018
4019 try
4020 {
4021 lpi->spx->clearBasis();
4022 }
4023#ifndef NDEBUG
4024 catch( const SPxException& x )
4025 {
4026 std::string s = x.what();
4027 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4028#else
4029 catch( const SPxException& )
4030 {
4031#endif
4032 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
4033 return SCIP_LPERROR;
4034 }
4035
4036 return SCIP_OKAY;
4037}
4038
4039/** frees LPi state information */
4041 SCIP_LPI* lpi, /**< LP interface structure */
4042 BMS_BLKMEM* blkmem, /**< block memory */
4043 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4044 )
4045{ /*lint --e{715}*/
4046 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4047
4048 assert(lpi != NULL);
4049 assert(lpistate != NULL);
4050 assert(blkmem != NULL);
4051
4052 if ( *lpistate != NULL )
4053 lpistateFree(lpistate, blkmem);
4054
4055 return SCIP_OKAY;
4056}
4057
4058/** checks, whether the given LP state contains simplex basis information */
4060 SCIP_LPI* lpi, /**< LP interface structure */
4061 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4062 )
4063{ /*lint --e{715}*/
4064 assert(lpi != NULL);
4065 return TRUE;
4066}
4067
4068/** reads LP state (like basis information from a file */
4070 SCIP_LPI* lpi, /**< LP interface structure */
4071 const char* fname /**< file name */
4072 )
4073{
4074 SCIPdebugMessage("calling SCIPlpiReadState()\n");
4075 assert(lpi != NULL);
4076 assert(lpi->spx != NULL);
4077 assert(fname != NULL);
4078
4079 assert( lpi->spx->preStrongbranchingBasisFreed() );
4080
4081 bool success;
4082 SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4083
4084 return success ? SCIP_OKAY : SCIP_LPERROR;
4085}
4086
4087/** writes LPi state (i.e. basis information) to a file */
4089 SCIP_LPI* lpi, /**< LP interface structure */
4090 const char* fname /**< file name */
4091 )
4092{
4093 assert(lpi != NULL);
4094 assert(lpi->spx != NULL);
4095 assert(fname != NULL);
4096 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
4097
4098 assert( lpi->spx->preStrongbranchingBasisFreed() );
4099
4100 bool res;
4101 SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
4102
4103 if ( ! res )
4104 return SCIP_LPERROR;
4105
4106 return SCIP_OKAY;
4107}
4108
4109/**@} */
4110
4111
4112
4113
4114/*
4115 * LP Pricing Norms Methods
4116 */
4117
4118/**@name LP Pricing Norms Methods */
4119/**@{ */
4120
4121/** stores LPi pricing norms information
4122 * @todo should we store norm information?
4123 */
4125 SCIP_LPI* lpi, /**< LP interface structure */
4126 BMS_BLKMEM* blkmem, /**< block memory */
4127 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
4128 )
4129{ /*lint --e{715}*/
4130#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4131 int nrows;
4132 int ncols;
4133
4134 assert(blkmem != NULL);
4135 assert(lpi != NULL);
4136 assert(lpi->spx != NULL);
4137 assert(lpinorms != NULL);
4138
4139 lpi->spx->getNdualNorms(nrows, ncols);
4140
4141 if( nrows == 0 && ncols == 0)
4142 {
4143 (*lpinorms = NULL);
4144 return SCIP_OKAY;
4145 }
4146
4147 /* allocate lpinorms data */
4148 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
4149 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
4150 (*lpinorms)->nrows = 0;
4151 (*lpinorms)->ncols = 0;
4152
4153 SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
4154
4155 if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
4156 {
4157 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4158 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
4159 BMSfreeBlockMemory(blkmem, lpinorms);
4160 assert(*lpinorms == NULL);
4161 }
4162#ifndef NDEBUG
4163 else
4164 {
4165 assert(nrows == (*lpinorms)->nrows);
4166 assert(ncols == (*lpinorms)->ncols);
4167 }
4168#endif
4169#else
4170 (*lpinorms) = NULL;
4171#endif
4172
4173 return SCIP_OKAY;
4174}
4175
4176/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
4177 * columns and rows since the state was stored with SCIPlpiGetNorms()
4178 */
4180 SCIP_LPI* lpi, /**< LP interface structure */
4181 BMS_BLKMEM* blkmem, /**< block memory */
4182 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
4183 )
4184{ /*lint --e{715}*/
4185#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4186 assert(blkmem != NULL);
4187 assert(lpi != NULL);
4188 assert(lpi->spx != NULL);
4189
4190 /* if there was no pricing norms information available, the LPi norms were not stored */
4191 if( lpinorms == NULL )
4192 return SCIP_OKAY;
4193
4194 assert(lpinorms->nrows <= lpi->spx->numRowsReal());
4195 assert(lpinorms->ncols <= lpi->spx->numColsReal());
4196
4197 if( lpinorms->nrows == 0 )
4198 return SCIP_OKAY;
4199
4200 SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
4201 (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->numRowsReal(), lpi->spx->numColsReal());
4202
4203 (void) lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms);
4204#endif
4205
4206 return SCIP_OKAY;
4207}
4208
4209/** frees pricing norms information */
4211 SCIP_LPI* lpi, /**< LP interface structure */
4212 BMS_BLKMEM* blkmem, /**< block memory */
4213 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
4214 )
4215{ /*lint --e{715}*/
4216#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4217 assert(lpi != NULL);
4218 assert(lpinorms != NULL);
4219
4220 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4221
4222 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
4223 BMSfreeBlockMemory(blkmem, lpinorms);
4224 assert(*lpinorms == NULL);
4225#endif
4226
4227 return SCIP_OKAY;
4228}
4229
4230/**@} */
4231
4232
4233
4234
4235/*
4236 * Parameter Methods
4237 */
4238
4239/**@name Parameter Methods */
4240/**@{ */
4241
4242/** gets integer parameter of LP */
4244 SCIP_LPI* lpi, /**< LP interface structure */
4245 SCIP_LPPARAM type, /**< parameter number */
4246 int* ival /**< buffer to store the parameter value */
4247 )
4248{
4249 int scaleparam;
4250
4251 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
4252
4253 assert(lpi != NULL);
4254 assert(lpi->spx != NULL);
4255 assert(ival != NULL);
4256
4257 switch( type )
4258 {
4260 *ival = lpi->spx->getFromScratch();
4261 break;
4262 case SCIP_LPPAR_LPINFO:
4263 *ival = lpi->spx->getLpInfo();
4264 break;
4265 case SCIP_LPPAR_LPITLIM:
4266 *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
4267 if( *ival == -1 )
4268 *ival = INT_MAX;
4269 break;
4271 *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER);
4272 break;
4273 case SCIP_LPPAR_PRICING:
4274 *ival = (int) lpi->pricing;
4275 break;
4276 case SCIP_LPPAR_SCALING:
4277 scaleparam = lpi->spx->intParam(SoPlex::SCALER);
4278
4279 if( scaleparam == SoPlex::SCALER_OFF )
4280 *ival = 0;
4281 else if( scaleparam == SoPlex::SCALER_BIEQUI )
4282 *ival = 1;
4283#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4284 else
4285 {
4286 assert(scaleparam == SoPlex::SCALER_LEASTSQ);
4287 *ival = 2;
4288 }
4289#else
4290 else
4291 {
4292 assert(scaleparam == SoPlex::SCALER_GEO8);
4293 *ival = 2;
4294 }
4295#endif
4296 break;
4297#if SOPLEX_VERSION >= 201
4298 case SCIP_LPPAR_TIMING:
4299 *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
4300 break;
4301#endif
4302#if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
4304 *ival = (int) lpi->spx->randomSeed();
4305 break;
4306#endif
4307#if SOPLEX_APIVERSION >= 1
4309 *ival = (int) lpi->spx->intParam(SoPlex::FACTOR_UPDATE_MAX);
4310 break;
4311#endif
4312 default:
4313 return SCIP_PARAMETERUNKNOWN;
4314 } /*lint !e788*/
4315
4316 return SCIP_OKAY;
4317}
4318
4319/** sets integer parameter of LP */
4321 SCIP_LPI* lpi, /**< LP interface structure */
4322 SCIP_LPPARAM type, /**< parameter number */
4323 int ival /**< parameter value */
4324 )
4325{
4326 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
4327
4328 assert(lpi != NULL);
4329 assert(lpi->spx != NULL);
4330
4331 switch( type )
4332 {
4334 assert(ival == TRUE || ival == FALSE);
4335 lpi->spx->setFromScratch(bool(ival));
4336 break;
4337 case SCIP_LPPAR_LPINFO:
4338 assert(ival == TRUE || ival == FALSE);
4339 lpi->spx->setLpInfo(bool(ival));
4340 break;
4341 case SCIP_LPPAR_LPITLIM:
4342 assert( ival >= 0 );
4343 /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
4344 if( ival >= INT_MAX )
4345 ival = -1;
4346 (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
4347 break;
4349 assert(ival == TRUE || ival == FALSE);
4350#if SOPLEX_APIVERSION < 13
4351 assert(ival == TRUE || ival == FALSE);
4352#else
4353 assert(ival == 1 || ival == 0 || ival == 2);
4354#endif
4355 (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, ival);
4356 break;
4357 case SCIP_LPPAR_PRICING:
4358 lpi->pricing = (SCIP_PRICING)ival;
4359 switch( lpi->pricing )
4360 {
4362 case SCIP_PRICING_AUTO:
4363 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_AUTO);
4364 break;
4365 case SCIP_PRICING_FULL:
4366 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4367 break;
4369 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_PARMULT);
4370 break;
4371 case SCIP_PRICING_STEEP:
4372 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4373 break;
4375 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_QUICKSTEEP);
4376 break;
4377 case SCIP_PRICING_DEVEX:
4378 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_DEVEX);
4379 break;
4380 default:
4381 return SCIP_LPERROR;
4382 }
4383 break;
4384 case SCIP_LPPAR_SCALING:
4385 assert(ival >= 0 && ival <= 2);
4386 if( ival == 0 )
4387 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_OFF);
4388 else if( ival == 1 )
4389 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_BIEQUI);
4390 else
4391#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4392 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_LEASTSQ);
4393#else
4394 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_GEO8);
4395#endif
4396
4397 break;
4398#if SOPLEX_VERSION >= 201
4399 case SCIP_LPPAR_TIMING:
4400 assert(ival >= 0 && ival < 3);
4401 (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
4402 break;
4403#endif
4404#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
4406 lpi->spx->setRandomSeed((unsigned long)(long)ival);
4407 break;
4408#endif
4409#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION >= 221 && SOPLEX_SUBVERSION >= 3)
4411 assert(ival >= 0 && ival < 3);
4412 (void) lpi->spx->setIntParam(SoPlex::SOLUTION_POLISHING, ival);
4413 break;
4414#endif
4415#if SOPLEX_APIVERSION >= 1
4417 assert(ival >= 0);
4418 (void) lpi->spx->setIntParam(SoPlex::FACTOR_UPDATE_MAX, ival);
4419 break;
4420#endif
4421
4422 default:
4423 return SCIP_PARAMETERUNKNOWN;
4424 } /*lint !e788*/
4425
4426 return SCIP_OKAY;
4427}
4428
4429/** gets floating point parameter of LP */
4431 SCIP_LPI* lpi, /**< LP interface structure */
4432 SCIP_LPPARAM type, /**< parameter number */
4433 SCIP_Real* dval /**< buffer to store the parameter value */
4434 )
4435{
4436 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
4437
4438 assert(lpi != NULL);
4439 assert(lpi->spx != NULL);
4440 assert(dval != NULL);
4441
4442 switch( type )
4443 {
4444 case SCIP_LPPAR_FEASTOL:
4445 *dval = lpi->spx->feastol();
4446 break;
4448 *dval = lpi->spx->opttol();
4449 break;
4450 case SCIP_LPPAR_OBJLIM:
4451 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4452 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
4453 else
4454 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
4455 break;
4456 case SCIP_LPPAR_LPTILIM:
4457 *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
4458 break;
4460 *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
4461 if( *dval >= SCIPlpiInfinity(lpi) )
4462 *dval = -1.0;
4463 break;
4465 *dval = lpi->conditionlimit;
4466 break;
4468#if (SOPLEX_APIVERSION >= 9)
4469 *dval = lpi->spx->realParam(SoPlex::MIN_MARKOWITZ);
4470 break;
4471#endif
4472 default:
4473 return SCIP_PARAMETERUNKNOWN;
4474 } /*lint !e788*/
4475
4476 return SCIP_OKAY;
4477}
4478
4479/** sets floating point parameter of LP */
4481 SCIP_LPI* lpi, /**< LP interface structure */
4482 SCIP_LPPARAM type, /**< parameter number */
4483 SCIP_Real dval /**< parameter value */
4484 )
4485{
4486 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
4487
4488 assert(lpi != NULL);
4489 assert(lpi->spx != NULL);
4490
4491 switch( type )
4492 {
4493 case SCIP_LPPAR_FEASTOL:
4494 /* 0 < dval */
4495 assert( dval > 0.0 );
4496 lpi->spx->setFeastol(dval);
4497 break;
4499 /* 0 < dval */
4500 assert( dval > 0.0 );
4501 lpi->spx->setOpttol(dval);
4502 break;
4503 case SCIP_LPPAR_OBJLIM:
4504 /* no restrictions on dval */
4505 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4506 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
4507 else
4508 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
4509 break;
4510 case SCIP_LPPAR_LPTILIM:
4511 assert( dval > 0.0 );
4512 /* soplex requires 0 < dval < DEFAULT_INFINITY (= 1e100), -1 means unlimited */
4513 (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
4514 break;
4516 /* 0 <= dval <= inf */
4517 assert( dval >= 0.0 || dval == -1.0 );
4518 if( dval == -1 )
4519 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiInfinity(lpi));
4520 else
4521 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
4522 break;
4524 lpi->conditionlimit = dval;
4525 lpi->checkcondition = (dval >= 0.0);
4526 break;
4528#if (SOPLEX_APIVERSION >= 9)
4529 /* 1e-4 <= dval <= 0.999 */
4530 if( dval < 1e-4 )
4531 dval = 1e-4;
4532 else if( dval > 0.9999 )
4533 dval = 0.9999;
4534
4535 (void) lpi->spx->setRealParam(SoPlex::MIN_MARKOWITZ, dval);
4536 break;
4537#endif
4538 default:
4539 return SCIP_PARAMETERUNKNOWN;
4540 } /*lint !e788*/
4541
4542 return SCIP_OKAY;
4543}
4544
4545/** interrupts the currently ongoing lp solve or disables the interrupt */
4547 SCIP_LPI* lpi, /**< LP interface structure */
4548 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
4549 )
4550{
4551 assert(lpi != NULL);
4552 assert(lpi->spx != NULL);
4553
4554 lpi->spx->setInterrupt(interrupt);
4555
4556 return SCIP_OKAY;
4557}
4558
4559/**@} */
4560
4561
4562
4563
4564/*
4565 * Numerical Methods
4566 */
4567
4568/**@name Numerical Methods */
4569/**@{ */
4570
4571/** returns value treated as infinity in the LP solver */
4573 SCIP_LPI* lpi /**< LP interface structure */
4574 )
4575{
4576 assert(lpi != NULL);
4577 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
4578
4579 return lpi->spx->realParam(SoPlex::INFTY);
4580}
4581
4582/** checks if given value is treated as infinity in the LP solver */
4584 SCIP_LPI* lpi, /**< LP interface structure */
4585 SCIP_Real val
4586 )
4587{
4588 assert(lpi != NULL);
4589 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
4590
4591 return (val >= lpi->spx->realParam(SoPlex::INFTY));
4592}
4593
4594/**@} */
4595
4596
4597
4598
4599/*
4600 * File Interface Methods
4601 */
4602
4603/**@name File Interface Methods */
4604/**@{ */
4605
4606/** returns, whether the given file exists */
4607static
4609 const char* filename /**< file name */
4610 )
4611{
4612 FILE* f;
4613
4614 f = fopen(filename, "r");
4615 if( f == NULL )
4616 return FALSE;
4617
4618 fclose(f);
4619
4620 return TRUE;
4621}
4622
4623/** reads LP from a file */
4625 SCIP_LPI* lpi, /**< LP interface structure */
4626 const char* fname /**< file name */
4627 )
4628{
4629 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
4630
4631 assert(lpi != NULL);
4632 assert(lpi->spx != NULL);
4633 assert(fname != NULL);
4634
4635 assert( lpi->spx->preStrongbranchingBasisFreed() );
4636
4637 if( !fileExists(fname) )
4638 return SCIP_NOFILE;
4639
4640 try
4641 {
4642 assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL);
4643 if( !lpi->spx->readFile(fname) )
4644 return SCIP_READERROR;
4645 }
4646#ifndef NDEBUG
4647 catch( const SPxException& x )
4648 {
4649 std::string s = x.what();
4650 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4651#else
4652 catch( const SPxException& )
4653 {
4654#endif
4655 return SCIP_READERROR;
4656 }
4657
4658 return SCIP_OKAY;
4659}
4660
4661/** writes LP to a file */
4663 SCIP_LPI* lpi, /**< LP interface structure */
4664 const char* fname /**< file name */
4665 )
4666{
4667 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
4668
4669 assert(lpi != NULL);
4670 assert(lpi->spx != NULL);
4671 assert(fname != NULL);
4672
4673 try
4674 {
4675 (void) lpi->spx->writeFileReal(fname);
4676 }
4677#ifndef NDEBUG
4678 catch( const SPxException& x )
4679 {
4680 std::string s = x.what();
4681 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4682#else
4683 catch( const SPxException& )
4684 {
4685#endif
4686 return SCIP_WRITEERROR;
4687 }
4688
4689 return SCIP_OKAY;
4690}
4691
4692/**@} */
void SCIPdecodeDualBit(const SCIP_DUALPACKET *inp, int *out, int count)
Definition: bitencode.c:308
void SCIPencodeDualBit(const int *inp, SCIP_DUALPACKET *out, int count)
Definition: bitencode.c:238
packing single and dual bit values
unsigned int SCIP_DUALPACKET
Definition: bitencode.h:42
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_VAR ** x
Definition: circlepacking.c:63
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define EPSCEIL(x, eps)
Definition: def.h:206
#define SCIPABORT()
Definition: def.h:345
#define EPSFLOOR(x, eps)
Definition: def.h:205
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_spx2.cpp:1589
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
Definition: lpi_spx2.cpp:3950
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3842
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx2.cpp:4430
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:4572
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3194
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_spx2.cpp:1662
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_spx2.cpp:4583
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:1512
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:4010
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3054
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2980
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_spx2.cpp:3508
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4069
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_spx2.cpp:1381
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx2.cpp:3360
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_spx2.cpp:4243
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4662
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_spx2.cpp:1023
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3095
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_spx2.cpp:4480
SCIP_RETCODE 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)
Definition: lpi_spx2.cpp:2780
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_spx2.cpp:4179
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_spx2.cpp:1923
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_spx2.cpp:1044
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_spx2.cpp:2854
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_spx2.cpp:2268
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_spx2.cpp:1060
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx2.cpp:3397
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx2.cpp:3267
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_spx2.cpp:1800
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3233
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2477
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx2.cpp:2959
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx2.cpp:4210
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3207
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_spx2.cpp:1530
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3008
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx2.cpp:3246
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4088
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_spx2.cpp:1134
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_spx2.cpp:2810
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_spx2.cpp:2324
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3039
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4624
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx2.cpp:3455
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3108
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx2.cpp:4124
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3220
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_spx2.cpp:4059
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx2.cpp:4320
const char * SCIPlpiGetSolverName(void)
Definition: lpi_spx2.cpp:998
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_spx2.cpp:3597
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2995
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3705
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_spx2.cpp:1459
SCIP_RETCODE SCIPlpiGetCols(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lb, SCIP_Real *ub, int *nnonz, int *beg, int *ind, SCIP_Real *val)
Definition: lpi_spx2.cpp:1964
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3736
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx2.cpp:2176
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3768
SCIP_RETCODE SCIPlpiGetRows(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhs, SCIP_Real *rhs, int *nnonz, int *beg, int *ind, SCIP_Real *val)
Definition: lpi_spx2.cpp:2072
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2940
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_spx2.cpp:1007
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_spx2.cpp:2462
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3121
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx2.cpp:2202
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_spx2.cpp:1052
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2491
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_spx2.cpp:2296
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_spx2.cpp:2884
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_spx2.cpp:3288
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3069
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx2.cpp:1349
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_spx2.cpp:2245
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx2.cpp:4040
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3026
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2448
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_spx2.cpp:1245
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2434
SCIP_RETCODE SCIPlpiLoadColLP(SCIP_LPI *lpi, SCIP_OBJSEN objsen, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_spx2.cpp:1167
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3082
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx2.cpp:3434
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx2.cpp:3680
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx2.cpp:1080
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:1015
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_spx2.cpp:1682
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_spx2.cpp:2228
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3142
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_spx2.cpp:1906
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_spx2.cpp:4546
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_spx2.cpp:1327
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx2.cpp:1481
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_spx2.cpp:1726
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_spx2.cpp:1889
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx2.cpp:3906
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_spx2.cpp:1638
static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
Definition: heur_twoopt.c:936
interface methods for specific LP solvers
SCIP_DUALPACKET ROWPACKET
Definition: lpi_clp.cpp:128
SCIP_DUALPACKET COLPACKET
Definition: lpi_clp.cpp:126
static void setIntParam(SCIP_LPI *lpi, int const param, int const parval)
Definition: lpi_cpx.c:654
#define FEASTOL
Definition: lpi_qso.c:99
static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
Definition: lpi_spx2.cpp:876
#define NULL
Definition: lpi_spx2.cpp:142
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
Definition: lpi_spx2.cpp:892
static SCIP_Bool fileExists(const char *filename)
Definition: lpi_spx2.cpp:4608
#define SOPLEX_TRY(messagehdlr, x)
Definition: lpi_spx2.cpp:153
static int rowpacketNum(int nrows)
Definition: lpi_spx2.cpp:867
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2362
SCIP_DUALPACKET ROWPACKET
Definition: lpi_spx2.cpp:762
#define SOPLEX_VERBLEVEL
Definition: lpi_spx2.cpp:132
static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx2.cpp:807
static const char spxdesc[200]
Definition: lpi_spx2.cpp:981
#define COLS_PER_PACKET
Definition: lpi_spx2.cpp:761
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition: lpi_spx2.cpp:932
SCIP_DUALPACKET COLPACKET
Definition: lpi_spx2.cpp:760
static SCIP_RETCODE lpiStrongbranch(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_spx2.cpp:2507
static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx2.cpp:829
static int colpacketNum(int ncols)
Definition: lpi_spx2.cpp:858
#define CHECK_SOPLEX_PARAM(x)
Definition: lpi_spx2.cpp:79
#define SOPLEX_SUBVERSION
Definition: lpi_spx2.cpp:102
static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
Definition: lpi_spx2.cpp:908
#define SOPLEX_TRY_ABORT(x)
Definition: lpi_spx2.cpp:198
#define ROWS_PER_PACKET
Definition: lpi_spx2.cpp:763
static const char spxname[20]
Definition: lpi_spx2.cpp:979
static void invalidateSolution(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:959
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSallocMemoryCPP(size)
Definition: memory.h:121
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugMessage
Definition: pub_message.h:96
@ ERROR
Definition: reader_sm.c:68
#define UNKNOWN
Definition: sepa_mcf.c:4104
SCIP_Real * norms
Definition: lpi_qso.c:85
COLPACKET * packcstat
Definition: lpi_clp.cpp:136
ROWPACKET * packrstat
Definition: lpi_clp.cpp:137
SCIP_Bool solved
Definition: lpi_clp.cpp:114
SCIP_Real conditionlimit
Definition: lpi_cpx.c:174
int * cstat
Definition: lpi_clp.cpp:107
int rstatsize
Definition: lpi_clp.cpp:110
int * rstat
Definition: lpi_clp.cpp:108
SCIP_PRICING pricing
Definition: lpi_clp.cpp:112
int cstatsize
Definition: lpi_clp.cpp:109
SCIP_MESSAGEHDLR * messagehdlr
Definition: lpi_cpx.c:185
SPxSCIP * spx
Definition: lpi_spx1.cpp:1404
SCIP_Bool checkcondition
Definition: lpi_cpx.c:175
@ SCIP_PRICING_STEEPQSTART
Definition: type_lpi.h:83
@ SCIP_PRICING_AUTO
Definition: type_lpi.h:79
@ SCIP_PRICING_DEVEX
Definition: type_lpi.h:84
@ SCIP_PRICING_STEEP
Definition: type_lpi.h:82
@ SCIP_PRICING_FULL
Definition: type_lpi.h:80
@ SCIP_PRICING_LPIDEFAULT
Definition: type_lpi.h:78
@ SCIP_PRICING_PARTIAL
Definition: type_lpi.h:81
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:86
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:73
@ SCIP_LPSOLQUALITY_EXACTCONDITION
Definition: type_lpi.h:102
@ SCIP_LPSOLQUALITY_ESTIMCONDITION
Definition: type_lpi.h:101
@ SCIP_LPPAR_PRICING
Definition: type_lpi.h:54
@ SCIP_LPPAR_REFACTOR
Definition: type_lpi.h:71
@ SCIP_LPPAR_LPINFO
Definition: type_lpi.h:55
@ SCIP_LPPAR_POLISHING
Definition: type_lpi.h:70
@ SCIP_LPPAR_SCALING
Definition: type_lpi.h:52
@ SCIP_LPPAR_TIMING
Definition: type_lpi.h:68
@ SCIP_LPPAR_LPTILIM
Definition: type_lpi.h:61
@ SCIP_LPPAR_PRESOLVING
Definition: type_lpi.h:53
@ SCIP_LPPAR_CONDITIONLIMIT
Definition: type_lpi.h:67
@ SCIP_LPPAR_RANDOMSEED
Definition: type_lpi.h:69
@ SCIP_LPPAR_DUALFEASTOL
Definition: type_lpi.h:57
@ SCIP_LPPAR_FROMSCRATCH
Definition: type_lpi.h:50
@ SCIP_LPPAR_MARKOWITZ
Definition: type_lpi.h:62
@ SCIP_LPPAR_FEASTOL
Definition: type_lpi.h:56
@ SCIP_LPPAR_LPITLIM
Definition: type_lpi.h:60
@ SCIP_LPPAR_ROWREPSWITCH
Definition: type_lpi.h:63
@ SCIP_LPPAR_OBJLIM
Definition: type_lpi.h:59
@ SCIP_BASESTAT_BASIC
Definition: type_lpi.h:92
@ SCIP_BASESTAT_UPPER
Definition: type_lpi.h:93
@ SCIP_BASESTAT_LOWER
Definition: type_lpi.h:91
@ SCIP_BASESTAT_ZERO
Definition: type_lpi.h:94
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:104
@ SCIP_OBJSEN_MAXIMIZE
Definition: type_lpi.h:42
@ SCIP_OBJSEN_MINIMIZE
Definition: type_lpi.h:43
enum SCIP_ObjSen SCIP_OBJSEN
Definition: type_lpi.h:45
@ SCIP_LPERROR
Definition: type_retcode.h:49
@ SCIP_NOFILE
Definition: type_retcode.h:47
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PARAMETERUNKNOWN
Definition: type_retcode.h:55
@ SCIP_WRITEERROR
Definition: type_retcode.h:46
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63