Scippy

SCIP

Solving Constraint Integer Programs

lpi_spx1.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-2025 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_spx1.cpp
26 * @ingroup LPIS
27 * @brief LP interface for SoPlex version 1.4 and higher
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Ambros Gleixner
31 * @author Marc Pfetsch
32 *
33 * This is an implementation of SCIP's LP interface for SoPlex. While the ratio test is fixed to SoPlex's standard,
34 * different pricing methods can be chosen and an autopricing strategy (start with devex and switch to steepest edge
35 * after too many iterations) is implemented directly. Scaler and simplifier may be applied if solving from scratch.
36 *
37 * For debugging purposes, the SoPlex results can be double checked with CPLEX if SCIP_WITH_LPSCHECK is defined. This may
38 * yield false positives, since the LP is dumped to a file for transfering it to CPLEX, hence, precision may be lost.
39 */
40
41/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42
43#define AUTOPRICING_ITERSWITCH 10000/**< start with devex and switch to steepest edge after this many iterations */
44#define STRONGBRANCH_RESTOREBASIS /**< if defined then in SCIPlpiStrongbranch() we restore the basis after the
45 * down branch and after the up branch; if false only after the end of a
46 * strong branching phase, which however seems to mostly increase strong
47 * branching time and iterations */
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(m_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/* remember the original value of the SCIP_DEBUG define and undefine it */
79#ifdef SCIP_DEBUG
80#define ___DEBUG
81#undef SCIP_DEBUG
82#endif
83
84/* disable -Wclass-memaccess warnings due to dubious memcpy/realloc calls in SoPlex headers, e.g.,
85 * dataarray.h:314:16: warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct soplex::SPxParMultPR::SPxParMultPr_Tmp’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]
86 */
87#ifdef __GNUC__
88#if __GNUC__ >= 8
89#pragma GCC diagnostic ignored "-Wclass-memaccess"
90#endif
91#endif
92
93/* include SoPlex solver */
94#include "soplex.h"
95
96/* define subversion for versions <= 1.5.0.1 */
97#ifndef SOPLEX_SUBVERSION
98#define SOPLEX_SUBVERSION 0
99#endif
100/* define API version for versions <= 3.0.0 */
101#ifndef SOPLEX_APIVERSION
102#define SOPLEX_APIVERSION 0
103#endif
104
105/* check version */
106#if (SOPLEX_VERSION < 133)
107#error "This interface is not compatible with SoPlex versions prior to 1.4"
108#endif
109
110/* get githash of SoPlex */
111#if (SOPLEX_VERSION >= 160)
112#if (SOPLEX_APIVERSION <= 5)
113#include "spxgithash.h"
114#endif
115#endif
116
117#define WITH_BOUNDFLIPPING
118#if (SOPLEX_APIVERSION <= 5)
119/* include SoPlex components */
120#include "spxsolver.h"
121#include "slufactor.h"
122#include "spxsteeppr.h"
123#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 6) || SOPLEX_VERSION > 160)
124#include "spxsteepexpr.h"
125#endif
126#include "spxparmultpr.h"
127#include "spxdevexpr.h"
128#include "spxfastrt.h"
129#include "spxmainsm.h"
130#include "spxequilisc.h"
131
132#ifdef WITH_BOUNDFLIPPING
133#include "spxboundflippingrt.h"
134#endif
135#endif
136
137/* reset the SCIP_DEBUG define to its original SCIP value */
138#undef SCIP_DEBUG
139#ifdef ___DEBUG
140#define SCIP_DEBUG
141#undef ___DEBUG
142#endif
143
144/* define snprintf when using a too old MSVC version */
145#if defined(_MSC_VER) && _MSC_VER < 1900
146#ifndef snprintf
147#define snprintf _snprintf
148#endif
149#endif
150
151#define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
152
153#include "scip/pub_message.h"
154
155/********************************************************************/
156/*----------------------------- C++ --------------------------------*/
157/********************************************************************/
158
159/* in C++ we have to use "0" instead of "(void*)0" */
160#undef NULL
161#define NULL 0
162
163#include <cassert>
164using namespace soplex;
165
166
167/** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
168 * make no distinction between different exception types, e.g., between memory allocation and other
169 * exceptions.
170 */
171#ifndef NDEBUG
172#define SOPLEX_TRY(messagehdlr, x) do \
173 { \
174 try \
175 { \
176 (x); \
177 } \
178 catch( const SPxMemoryException& E ) \
179 { \
180 std::string s = E.what(); \
181 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
182 return SCIP_ERROR; \
183 } \
184 catch( const SPxException& E ) \
185 { \
186 std::string s = E.what(); \
187 SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
188 return SCIP_LPERROR; \
189 } \
190 } \
191 while( FALSE )
192
193#else
194#define SOPLEX_TRY(messagehdlr, x) do \
195 { \
196 try \
197 { \
198 (x); \
199 } \
200 catch( const SPxMemoryException& E ) \
201 { \
202 std::string s = E.what(); \
203 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
204 return SCIP_ERROR; \
205 } \
206 catch( const SPxException& ) \
207 { \
208 return SCIP_LPERROR; \
209 } \
210 } \
211 while( FALSE )
212#endif
213
214/* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
215 * arise. SCIP_ABORT() is not accessible here.
216 */
217#define SOPLEX_TRY_ABORT(x) do \
218 { \
219 try \
220 { \
221 (x); \
222 } \
223 catch( const SPxException& E ) \
224 { \
225 std::string s = E.what(); \
226 SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
227 abort(); \
228 } \
229 } \
230 while( FALSE )
231
232
233
234/** SCIP's SoPlex class */
235class SPxSCIP : public SPxSolver
236{
237 SPxLP::SPxSense m_sense; /**< optimization sense */
238 SLUFactor m_slu; /**< sparse LU factorization */
239 SPxSteepPR m_price_steep; /**< steepest edge pricer */
240#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 6) || SOPLEX_VERSION > 160)
241 SPxSteepExPR m_price_steep_ex; /**< steepest edge with exact weight initialization */
242#else
243 SPxSteepPR m_price_steep_ex; /**< fallback to quick start pricer */
244#endif
245 SPxParMultPR m_price_parmult; /**< partial multiple pricer */
246 SPxDevexPR m_price_devex; /**< devex pricer */
247#ifdef WITH_BOUNDFLIPPING
248 SPxBoundFlippingRT m_ratio; /**< Long step dual ratio tester */
249#else
250 SPxFastRT m_ratio; /**< Harris fast ratio tester */
251#endif
252 char* m_probname; /**< problem name */
253 bool m_fromscratch; /**< use old basis indicator */
254 bool m_presolving; /**< use lp presolving */
255 Real m_lpifeastol; /**< feastol set by SCIPlpiSetRealpar() */
256 Real m_lpiopttol; /**< opttol set by SCIPlpiSetRealpar() */
257 Real m_objLoLimit; /**< lower objective limit */
258 Real m_objUpLimit; /**< upper objective limit */
259 Status m_stat; /**< solving status */
260 bool m_lpinfo; /**< storing whether output is turned on */
261 bool m_autopricing; /**< is automatic pricing selected? */
262 int m_itlim; /**< iteration limit (-1 for unbounded) */
263 int m_itused; /**< number of iterations spent in phase one of auto pricing */
264 int m_scaling; /**< LP scaling (0: none, 1: normal, 2: aggressive) */
265 DataArray<SPxSolver::VarStatus> m_rowstat; /**< basis status of rows before starting strong branching (if available, 0 otherwise) */
266 DataArray<SPxSolver::VarStatus> m_colstat; /**< basis status of columns before starting strong branching (if available, 0 otherwise) */
267 NameSet* m_rownames; /**< row names */
268 NameSet* m_colnames; /**< column names */
269
270#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
271 SPxOut m_spxout;
272#endif
273
274#ifdef SCIP_WITH_LPSCHECK
275 int m_checknum;
276 bool m_doublecheck;
277 CPXENVptr m_cpxenv; /**< CPLEX memory environment */
278 CPXLPptr m_cpxlp; /**< CPLEX lp structure */
279#endif
280 SCIP_MESSAGEHDLR* m_messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
281
282public:
283 SPxSCIP(
284 SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
285 const char* probname = NULL /**< name of problem */
286 )
287 : SPxSolver(LEAVE, COLUMN),
288 m_probname(0),
289 m_fromscratch(false),
290 m_presolving(true),
291 m_objLoLimit(-soplex::infinity),
292 m_objUpLimit(soplex::infinity),
293 m_stat(NO_PROBLEM),
294 m_lpinfo(false),
295 m_autopricing(true),
296 m_itlim(-1),
297 m_itused(0),
298 m_scaling(1),
299 m_rowstat(0),
300 m_colstat(0),
301 m_rownames(0),
302 m_colnames(0),
303 m_messagehdlr(messagehdlr)
304 {
305#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
306 setOutstream(m_spxout);
307#endif
308 m_sense = sense();
309 setSense(SPxLP::MINIMIZE);
310#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION == 4)
311 setBasisSolver(&m_slu); /*lint !e1506*/
312#else
313 setSolver(&m_slu); /*lint !e1506*/
314#endif
315 setTester(&m_ratio); /*lint !e1506*/
316 setPricer(&m_price_steep); /*lint !e1506*/
317 /* no starter */
318
319 if ( probname != NULL )
320 SOPLEX_TRY_ABORT( setProbname(probname) );
321
322#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
323 m_lpifeastol = SPxSolver::feastol();
324 m_lpiopttol = SPxSolver::opttol();
325#else
326 m_lpifeastol = SPxSolver::delta();
327 m_lpiopttol = SPxSolver::delta();
328#endif
329
330#ifdef SCIP_WITH_LPSCHECK
331 int cpxstat;
332 m_cpxenv = CPXopenCPLEX(&cpxstat);
333 assert(m_cpxenv != NULL);
334 m_cpxlp = CPXcreateprob(m_cpxenv, &cpxstat, probname != NULL ? probname : "spxcheck");
335 (void) CPXsetintparam(m_cpxenv, CPX_PARAM_SCRIND, 0);
336 m_checknum = 0;
337 m_doublecheck = false;
338#endif
339 }
340
341 virtual ~SPxSCIP()
342 {
343 if( m_probname != NULL )
344 spx_free(m_probname); /*lint !e1551*/
345
346 freePreStrongbranchingBasis(); /*lint !e1551*/
347
348 if( m_rownames != NULL )
349 {
350 m_rownames->~NameSet(); /*lint !e1551*/
351 spx_free(m_rownames); /*lint !e1551*/
352 }
353 if( m_colnames != NULL )
354 {
355 m_colnames->~NameSet(); /*lint !e1551*/
356 spx_free(m_colnames); /*lint !e1551*/
357 }
358
359#ifdef SCIP_WITH_LPSCHECK
360 (void) CPXfreeprob(m_cpxenv, &m_cpxlp);
361 (void) CPXcloseCPLEX(&m_cpxenv);
362#endif
363 } /*lint !e1579*/
364
365 /**< return feastol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
366 Real feastol() const
367 {/*lint !e1511*/
368 return m_lpifeastol;
369 }
370
371 /**< set feastol and store value in case SoPlex only accepts a larger tolerance */
372 void setFeastol(
373 const Real d
374 )
375 {/*lint !e1511*/
376 m_lpifeastol = d;
377
378#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
379 SPxSolver::setFeastol(d);
380#else
381 SPxSolver::setDelta(d);
382#endif
383 }
384
385 /**< return opttol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
386 Real opttol() const
387 {/*lint !e1511*/
388 return m_lpiopttol;
389 }
390
391 /**< set opttol and store value in case SoPlex only accepts a larger tolerance */
392 void setOpttol(
393 const Real d
394 )
395 {/*lint !e1511*/
396 m_lpiopttol = d;
397
398#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
399 SPxSolver::setOpttol(d);
400#else
401 SPxSolver::setDelta(d);
402#endif
403 }
404
405 bool isPerturbed() const
406 {
407 /* the epsilon is 1e-16; we add a factor of ten to account for numerics */
408 return (shift() >= 10.0 * epsilon());
409 }
410
411 /** set iteration limit (-1 = unbounded) */
412 void setIterationLimit(
413 const int itlim
414 )
415 {
416 m_itlim = itlim;
417 }
418
419 void setAutoPricer()
420 {
421 setPricer(&m_price_devex);
422 m_autopricing = true;
423 }
424
425 void setFullPricer()
426 {
427 setPricer(&m_price_steep);
428 m_autopricing = false;
429 }
430
431 void setSteepPricer()
432 {
433 setPricer(&m_price_steep_ex);
434 m_autopricing = false;
435 }
436
437 void setSteepQStartPricer()
438 {
439 setPricer(&m_price_steep);
440 m_autopricing = false;
441 }
442
443 void setParmultPricer()
444 {
445 setPricer(&m_price_parmult);
446 m_autopricing = false;
447 }
448
449 void setDevexPricer()
450 {
451 setPricer(&m_price_devex);
452 m_autopricing = false;
453 }
454
455 /** get iteration limit (-1 = unbounded) */
456 int getIterationLimit() const
457 {
458 return m_itlim;
459 }
460
461 bool getFromScratch() const
462 {
463 return m_fromscratch;
464 }
465
466 void setFromScratch(bool fs)
467 {
468 m_fromscratch = fs;
469 }
470
471 int getScaling() const
472 {
473 return m_scaling;
474 }
475
476 void setScaling(int s)
477 {
478 m_scaling = s;
479 }
480
481 bool getPresolving() const
482 {
483 return m_presolving;
484 }
485
486 void setPresolving(bool p)
487 {
488 m_presolving = p;
489 }
490
491 bool getLpInfo() const
492 {
493 return m_lpinfo;
494 }
495
496 void setLpInfo(bool li)
497 {
498 m_lpinfo = li;
499 }
500
501 SPxLP::SPxSense getSense() const
502 {
503 assert(m_sense == sense());
504
505 return m_sense;
506 }
507
508 void setSense(const SPxLP::SPxSense sen)
509 {
510 assert(m_sense == sense());
511
512 if( m_sense != sen )
513 {
514 m_sense = sen;
515 changeSense(sen);
516
517 /* if objective limit was set for the new sense previously, we have to apply it now */
518 if( m_sense == SPxLP::MINIMIZE && getObjUpLimit() < soplex::infinity )
519 {
520 SCIPdebugMessage("setting termination value to <%g>\n", getObjUpLimit());
521 SPxSolver::setTerminationValue(getObjUpLimit());
522 }
523 else if( m_sense == SPxLP::MAXIMIZE && getObjLoLimit() > -soplex::infinity )
524 {
525 SCIPdebugMessage("setting termination value to <%g>\n", getObjLoLimit());
526 SPxSolver::setTerminationValue(getObjLoLimit());
527 }
528 }
529 }
530
531 void setProbname(const char* probname)
532 {
533 size_t len;
534
535 assert(probname != NULL);
536 if( m_probname != NULL )
537 spx_free(m_probname);
538
539 len = strlen(probname);
540 spx_alloc(m_probname, len + 1);
541 memcpy(m_probname, probname, len + 1);
542 }
543
544 Real getObjLoLimit() const
545 {
546 return m_objLoLimit;
547 }
548
549 void setObjLoLimit(Real limit)
550 {
551 if( getSense() == SPxLP::MAXIMIZE )
552 {
553 SCIPdebugMessage("setting termination value from <%g> to <%g>\n", m_objLoLimit, limit);
554 SPxSolver::setTerminationValue(limit);
555 }
556 m_objLoLimit = limit;
557 }
558
559 Real getObjUpLimit() const
560 {
561 return m_objUpLimit;
562 }
563
564 void setObjUpLimit(Real limit)
565 {
566 if( getSense() == SPxLP::MINIMIZE )
567 {
568 SCIPdebugMessage("setting termination value from <%g> to <%g>\n", m_objUpLimit, limit);
569 SPxSolver::setTerminationValue(limit);
570 }
571 m_objUpLimit = limit;
572 }
573
574 void setRep(SPxSolver::Representation p_rep)
575 {/*lint !e1511*/
576 if( p_rep != rep() )
577 {
578 SCIPdebugMessage("switching to %s representation of the basis\n", p_rep == SPxSolver::ROW ? "row" : "column");
579 SPxSolver::setRep(p_rep);
580 }
581 }
582
583#ifdef SCIP_WITH_LPSCHECK
584 bool getDoubleCheck()
585 {
586 m_checknum++;
587 return m_doublecheck && m_checknum + 1 >= CHECK_START;
588 }
589
590 void setDoubleCheck(bool dc)
591 {
592 m_doublecheck = dc;
593 }
594
595 const char* spxStatusString(const SPxSolver::Status stat)
596 {
597 switch( stat )
598 {
599 case SPxSolver::ABORT_TIME:
600 return "ABORT_TIME";
601 case SPxSolver::ABORT_ITER:
602 return "ABORT_ITER";
603 case SPxSolver::ABORT_VALUE:
604 return "ABORT_VALUE";
605 case SPxSolver::SINGULAR:
606 return "SINGULAR";
607 case SPxSolver::REGULAR:
608 return "REGULAR";
610 return "UNKNOWN";
611 case SPxSolver::OPTIMAL:
612 return "OPTIMAL";
613 case SPxSolver::UNBOUNDED:
614 return "UNBOUNDED";
615 case SPxSolver::INFEASIBLE:
616 return "INFEASIBLE";
617 default:
618 return "UNKNOWN";
619 } /*lint !e788*/
620
621 return "UNKNOWN";
622 }
623
624 const char* cpxStatusString(const int stat)
625 {
626 switch( stat )
627 {
628 case CPX_STAT_ABORT_TIME_LIM:
629 return "ABORT_TIME";
630 case CPX_STAT_ABORT_IT_LIM:
631 return "ABORT_ITER";
632 case CPX_STAT_ABORT_OBJ_LIM:
633 return "ABORT_VALUE";
634 case CPX_STAT_OPTIMAL:
635 return "OPTIMAL";
636 case CPX_STAT_OPTIMAL_INFEAS:
637 return "CPX_STAT_OPTIMAL_INFEAS: OPT SOL INFEASIBLE AFTER UNSCALING";
638 case CPX_STAT_UNBOUNDED:
639 return "UNBOUNDED";
640 case CPX_STAT_INFEASIBLE:
641 return "INFEASIBLE";
642 case CPX_STAT_INForUNBD:
643 return "INFEASIBLE or UNBOUNDED";
644 case CPX_STAT_NUM_BEST:
645 return "CPX_STAT_NUM_BEST: SOL AVAILABLE BUT NOT PROVEN OPTIMAL DUE TO NUM TROUBLE";
646 default:
647 return "UNKNOWN";
648 } /*lint !e788*/
649
650 return "UNKNOWN";
651 }
652#endif
653
654#ifndef NDEBUG
655 bool checkConsistentBounds() const
656 {
657 for( int i = 0; i < nCols(); ++i )
658 {
659 if( lower(i) > upper(i) + Param::epsilon() )
660 {
661 SCIPerrorMessage("inconsistent bounds on column %d: lower=%.17g, upper=%.17g\n",
662 i, lower(i), upper(i));
663 return false;
664 }
665 }
666
667 return true;
668 }
669
670 bool checkConsistentSides() const
671 {
672 for( int i = 0; i < nRows(); ++i )
673 {
674 if( lhs(i) > rhs(i) + Param::epsilon() )
675 {
676 SCIPerrorMessage("inconsistent sides on row %d: lhs=%.17g, rhs=%.17g\n",
677 i, lhs(i), rhs(i));
678 return false;
679 }
680 }
681
682 return true;
683 }
684#endif
685
686 void trySolve(bool printwarning = true)
687 {
688 Real timespent;
689 Real timelimit;
690 try
691 {
692 m_stat = SPxSolver::solve();
693 }
694 catch( const SPxException& x )
695 {
696 std::string s = x.what();
697 if( printwarning )
698 {
699 SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
700 }
701 m_stat = SPxSolver::status();
702
703 /* since it is not clear if the status in SoPlex are set correctly
704 * we want to make sure that if an error is thrown the status is
705 * not OPTIMAL anymore.
706 */
707 assert( m_stat != SPxSolver::OPTIMAL );
708 }
709
710 /* save iteration count */
711 m_itused += SPxSolver::iterations();
712 assert(m_itlim < 0 || m_itused <= m_itlim);
713
714 /* update time limit */
715 timespent = SPxSolver::time();
716 if( timespent > 0 )
717 {
718 /* get current time limit */
719 timelimit = SPxSolver::terminationTime();
720 if( timelimit > timespent )
721 timelimit -= timespent;
722 else
723 timelimit = 0;
724 /* set new time limit */
725 assert(timelimit >= 0);
726 SPxSolver::setTerminationTime(timelimit);
727 }
728 }
729
730 void doSolve(bool printwarning = true)
731 {
732 /* store and set verbosity */
733#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
734 SPxOut::Verbosity verbosity;
735 verbosity = m_spxout.getVerbosity();
736 m_spxout.setVerbosity(getLpInfo() ? (SPxOut::Verbosity) SOPLEX_VERBLEVEL : (SPxOut::Verbosity) 0);
737#else
738 int verbosity;
739 verbosity = Param::verbose();
740 Param::setVerbose(getLpInfo() ? SOPLEX_VERBLEVEL : 0);
741#endif
742
743 assert(checkConsistentBounds());
744 assert(checkConsistentSides());
745
746#ifdef SCIP_WITH_LPSCHECK
747 /* dump LP with current basis and settings saved in SoPlex */
748 if( getDoubleCheck() )
749 writeState("spxcheck", NULL, NULL);
750#endif
751
752 /* in auto pricing, do the first iterations with devex, then switch to steepest edge */
753 setTerminationIter(m_autopricing && (m_itlim < 0 || m_itlim - m_itused > AUTOPRICING_ITERSWITCH) ? AUTOPRICING_ITERSWITCH : m_itlim - m_itused);
754
755 trySolve(printwarning);
756
757 if( m_autopricing && m_stat == SPxSolver::ABORT_ITER && (m_itlim < 0 || m_itlim - m_itused > 0) )
758 {
759 setTerminationIter(m_itlim - m_itused);
760 setPricer(&m_price_steep_ex);
761
762 trySolve(printwarning);
763
764 setPricer(&m_price_devex);
765 }
766
767 /* for safety reset iteration limit */
768 setTerminationIter(m_itlim);
769
770 if( m_stat == OPTIMAL )
771 {
772 Real objval = value();
773
774 if( (objval > m_objUpLimit) || (objval < m_objLoLimit) )
775 m_stat = ABORT_VALUE;
776 }
777
778#ifdef SCIP_WITH_LPSCHECK
779 /* if SoPlex gave a definite answer, we double check if it is consistent with CPLEX's answer */
780 if( getDoubleCheck() && (m_stat == SPxSolver::OPTIMAL || m_stat == SPxSolver::UNBOUNDED || m_stat == SPxSolver::INFEASIBLE || m_stat == SPxSolver::ABORT_VALUE) )
781 {
782 SCIP_Real cpxobj;
783 int cpxstat;
784
785 /* read LP with basis */
786 CPX_CALL( CPXreadcopyprob(m_cpxenv, m_cpxlp, "spxcheck.mps", NULL) );
787 CPX_CALL( CPXreadcopybase(m_cpxenv, m_cpxlp, "spxcheck.bas") );
788
789 /* set tolerances */
790 CPX_CALL( CPXsetdblparam(m_cpxenv, CPX_PARAM_EPOPT, MAX(opttol(), 1e-9)) );
791 CPX_CALL( CPXsetdblparam(m_cpxenv, CPX_PARAM_EPRHS, MAX(feastol(), 1e-9)) );
792
793 /* solve LP */
794 CPX_CALL( CPXlpopt(m_cpxenv, m_cpxlp) );
795
796 /* get solution status and objective value */
797 CPX_CALL( CPXsolution(m_cpxenv, m_cpxlp, &cpxstat, &cpxobj, NULL, NULL, NULL, NULL) );
798 if( getSense() == SPxLP::MAXIMIZE )
799 cpxobj *= -1.0;
800
801 /* check for inconsistent statuses */
802 if( cpxstat == CPX_STAT_OPTIMAL_INFEAS )
803 {
804 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s)\n",
805 m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat));
806 if( EXIT_AT_CPXERROR )
807 exit(1);
808 }
809 else if( (m_stat == SPxSolver::OPTIMAL && cpxstat != CPX_STAT_OPTIMAL)
810 || (m_stat == SPxSolver::UNBOUNDED && cpxstat != CPX_STAT_UNBOUNDED)
811 || (m_stat == SPxSolver::INFEASIBLE && cpxstat != CPX_STAT_INFEASIBLE) )
812 {
813 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
814 m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat), m_checknum);
815 if( EXIT_AT_WRONG_RESULT )
816 exit(1);
817 }
818 else if( m_stat == SPxSolver::ABORT_VALUE )
819 {
820 switch( cpxstat )
821 {
822 case CPX_STAT_OPTIMAL:
823 if( (getSense() == SPxSolver::MINIMIZE && LTrel(cpxobj, getObjUpLimit(), 2*opttol()))
824 || (getSense() == SPxSolver::MAXIMIZE && GTrel(cpxobj, getObjLoLimit(), 2*opttol())) )
825 {
826 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
827 m_probname, m_stat, spxStatusString(m_stat), cpxobj, getSense() == SPxSolver::MINIMIZE ? "<" : ">",
828 getSense() == SPxSolver::MINIMIZE ? getObjUpLimit() : getObjLoLimit(), cpxStatusString(cpxstat), m_checknum);
829 if( EXIT_AT_WRONG_RESULT )
830 exit(1);
831 }
832 else if( (getSense() == SPxSolver::MINIMIZE && cpxobj < getObjUpLimit())
833 || (getSense() == SPxSolver::MAXIMIZE && cpxobj > getObjLoLimit()) )
834 {
835 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
836 m_probname, m_stat, spxStatusString(m_stat), cpxobj, getSense() == SPxSolver::MINIMIZE ? "<" : ">",
837 getSense() == SPxSolver::MINIMIZE ? getObjUpLimit() : getObjLoLimit(), cpxStatusString(cpxstat), m_checknum);
838 }
839 break;
840 case CPX_STAT_OPTIMAL_INFEAS:
841 case CPX_STAT_NUM_BEST:
842 if( (getSense() == SPxSolver::MINIMIZE && cpxobj < getObjUpLimit())
843 || (getSense() == SPxSolver::MAXIMIZE && cpxobj > getObjLoLimit()) )
844 {
845 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
846 m_probname, m_stat, spxStatusString(m_stat), cpxobj, getSense() == SPxSolver::MINIMIZE ? "<" : ">",
847 getSense() == SPxSolver::MINIMIZE ? getObjUpLimit() : getObjLoLimit(), cpxStatusString(cpxstat), m_checknum);
848 }
849 break;
850 case CPX_STAT_INFEASIBLE:
851 break;
852 case CPX_STAT_UNBOUNDED:
853 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
854 m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat), m_checknum);
855 if( EXIT_AT_WRONG_RESULT )
856 exit(1);
857 break;
858 case CPX_STAT_INForUNBD:
859 default:
860 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
861 m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat), m_checknum);
862 break;
863 } /*lint !e788*/
864 }
865 /* check for same objective values */
866 else if( m_stat == SPxSolver::OPTIMAL )
867 {
868 if( (getSense() == SPxSolver::MINIMIZE && LTrel(value(), cpxobj, 2*opttol()))
869 || (getSense() == SPxSolver::MAXIMIZE && GTrel(value(), cpxobj, 2*opttol())) )
870 {
871 /* SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f too good (checknum=%d)\n", value(),
872 m_probname, getSense() == SPxSolver::MINIMIZE ? "<" : ">", cpxobj, m_checknum); */
873 }
874 else if( (getSense() == SPxSolver::MINIMIZE && GTrel(value(), cpxobj, 2*opttol()))
875 || (getSense() == SPxSolver::MAXIMIZE && LTrel(value(), cpxobj, 2*opttol())) )
876 {
877 SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f suboptimal (checknum=%d)\n", value(),
878 m_probname, getSense() == SPxSolver::MINIMIZE ? ">" : "<", cpxobj, m_checknum);
879 if( EXIT_AT_WRONG_RESULT )
880 exit(1);
881 }
882 }
883 }
884
885 ENDCHECK:
886#endif
887
888 /* restore verbosity */
889#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
890 m_spxout.setVerbosity(verbosity);
891#else
892 Param::setVerbose(verbosity);
893#endif
894
895 }
896
897 virtual Status solve()
898 {
899 assert(m_sense == sense());
900 SPxEquiliSC* scaler = NULL;
901 SPxMainSM* simplifier = NULL;
902 SPxLP origlp;
903 SPxSimplifier::Result result = SPxSimplifier::OKAY;
904
905 /* delete starting basis if solving from scratch */
906 if ( getFromScratch() )
907 {
908 try
909 {
910 SPxSolver::reLoad();
911 }
912 catch( const SPxException& x )
913 {
914 std::string s = x.what();
915 SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
916 m_stat = SPxSolver::status();
917 assert( m_stat != SPxSolver::OPTIMAL );
918 return m_stat;
919 }
920 }
921 assert(!getFromScratch() || getBasisStatus() == SPxBasis::NO_PROBLEM);
922
923 /* use scaler and simplifier if no basis is loaded, i.e., if solving for the first time or from scratch */
924 if( SPxSolver::getBasisStatus() == SPxBasis::NO_PROBLEM && (getScaling() > 0) && nCols() > 0 && nRows() > 0 )
925 {
926 spx_alloc(scaler, 1);
927 scaler = new (scaler) SPxEquiliSC();
928 assert(scaler != NULL);
929#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
930 scaler->setOutstream(m_spxout);
931#endif
932 }
933
934 if( SPxSolver::getBasisStatus() == SPxBasis::NO_PROBLEM && getPresolving() && nCols() > 0 && nRows() > 0 )
935 {
936 spx_alloc(simplifier, 1);
937 simplifier = new (simplifier) SPxMainSM();
938 assert(simplifier != NULL);
939 }
940
941 /* store original lp */
942 if( scaler != NULL || simplifier != NULL )
943 origlp = SPxLP(*this);
944
945 m_itused = 0;
946
947 SOLVEAGAIN:
948 /* perform scaling and presolving */
949 if( scaler != NULL )
950 {
951 SCIPdebugMessage("scaling LP\n");
952 scaler->scale(*this);
953 }
954
955 if( simplifier != NULL )
956 {
957 /* store and set verbosity */
958#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
959 SPxOut::Verbosity verbosity;
960 verbosity = m_spxout.getVerbosity();
961 m_spxout.setVerbosity(getLpInfo() ? (SPxOut::Verbosity) SOPLEX_VERBLEVEL : (SPxOut::Verbosity) 0);
962#else
963 int verbosity;
964 verbosity = Param::verbose();
965 Param::setVerbose(getLpInfo() ? SOPLEX_VERBLEVEL : 0);
966#endif
967 SCIPdebugMessage("simplifying LP\n");
968#ifdef WITH_BOUNDFLIPPING
969 result = simplifier->simplify(*this, epsilon(), feastol(), opttol(), true);
970#else
971#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
972 result = simplifier->simplify(*this, epsilon(), feastol(), opttol());
973#else
974 result = simplifier->simplify(*this, epsilon(), delta());
975#endif
976#endif
977 SCIPdebugMessage("simplifier ended with status %u (0: OKAY, 1: INFEASIBLE, 2: DUAL_INFEASIBLE, 3: UNBOUNDED, 4: VANISHED)\n", result);
978
979 /* unsimplification is not designed for these cases, thus reload original/scaled lp */
980 if( result == SPxSimplifier::INFEASIBLE || result == SPxSimplifier::DUAL_INFEASIBLE )
981 {
982 SCIPdebugMessage("simplifier detected primal or dual infeasibility - reloading and solving unsimplified LP\n");
983
984 simplifier->~SPxMainSM();
985 spx_free(simplifier);
986
987 SPxSolver::loadLP(origlp);
988 m_sense = sense();
989
990 goto SOLVEAGAIN;
991 }
992 /* reset verbosity */
993#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
994 m_spxout.setVerbosity(verbosity);
995#else
996 Param::setVerbose(verbosity);
997#endif
998 }
999
1000 /* solve */
1001 if( result != SPxSimplifier::VANISHED )
1002 {
1003 /* we have to deactivate the objective limit, since we do not know the transformed value */
1004 Real objlolimit = getObjLoLimit();
1005 Real objuplimit = getObjUpLimit();
1006
1007 if( simplifier != NULL || scaler != NULL )
1008 {
1009 setObjLoLimit(-soplex::infinity);
1010 setObjUpLimit(soplex::infinity);
1011 }
1012
1013#ifndef NDEBUG
1014 doSolve();
1015#else
1016 doSolve(false);
1017#endif
1018
1019 if( simplifier != NULL || scaler != NULL )
1020 {
1021 setObjLoLimit(objlolimit);
1022 setObjUpLimit(objuplimit);
1023 }
1024 }
1025
1026 /* unsimplification only stable for optimal basis */
1027 if( m_stat != SPxSolver::OPTIMAL && simplifier != NULL )
1028 {
1029 SCIPdebugMessage("presolved LP not optimal - reloading and solving original LP\n");
1030
1031 simplifier->~SPxMainSM();
1032 spx_free(simplifier);
1033
1034 SPxSolver::loadLP(origlp);
1035 m_sense = sense();
1036
1037 goto SOLVEAGAIN;
1038 }
1039
1040 /* if scaling or presolving was applied, restore original lp */
1041 if( scaler != NULL || simplifier != NULL )
1042 {
1043 SPxSolver::VarStatus* cstat = NULL;
1044 SPxSolver::VarStatus* rstat = NULL;
1045
1046 /* get basis if at least regular */
1047 if( (simplifier == NULL || result != SPxSimplifier::VANISHED) && SPxSolver::getBasisStatus() >= SPxBasis::REGULAR )
1048 {
1049 SCIPdebugMessage("get basis of presolved LP\n");
1050 spx_alloc(rstat, nRows());
1051 spx_alloc(cstat, nCols());
1052 (void) SPxSolver::getBasis(rstat, cstat);
1053 }
1054
1055 /* unsimplify */
1056 if( simplifier != NULL && SPxSolver::getBasisStatus() >= SPxBasis::REGULAR )
1057 {
1058 assert((result == SPxSimplifier::VANISHED) == (cstat == NULL));
1059 assert((result == SPxSimplifier::VANISHED) == (rstat == NULL));
1060
1061 /* dimension of presolved lp */
1062 int ncols = result == SPxSimplifier::VANISHED ? 0 : nCols();
1063 int nrows = result == SPxSimplifier::VANISHED ? 0 : nRows();
1064
1065 /* get solution of presolved lp */
1066 DVector primals(ncols);
1067 DVector duals(nrows);
1068 DVector slacks(nrows);
1069 DVector redcosts(ncols);
1070 if( result != SPxSimplifier::VANISHED )
1071 {
1072 (void) SPxSolver::getPrimal(primals);
1073 (void) SPxSolver::getDual(duals);
1074 (void) SPxSolver::getSlacks(slacks);
1075 (void) SPxSolver::getRedCost(redcosts);
1076 }
1077
1078 /* perform unsimplification */
1079 SCIPdebugMessage("unsimplify\n");
1080 try
1081 {
1082 simplifier->unsimplify(primals, duals, slacks, redcosts, rstat, cstat);
1083 }
1084 catch( const SPxException& x )
1085 {
1086 std::string s = x.what();
1087 SCIPmessagePrintWarning(m_messagehdlr, "SoPlex unsimplification unsuccessful; solving again without LP presolving (SoPlex says %s)\n",
1088 s.c_str());
1089 }
1090
1091 if( cstat != NULL )
1092 spx_free(cstat);
1093 if( rstat != NULL )
1094 spx_free(rstat);
1095
1096 if( simplifier->isUnsimplified() )
1097 {
1098 /* get basis for original lp */
1099 rstat = NULL;
1100 cstat = NULL;
1101 spx_alloc(rstat, origlp.nRows());
1102 spx_alloc(cstat, origlp.nCols());
1103 simplifier->getBasis(rstat, cstat);
1104 }
1105 }
1106
1107 /* reload original lp */
1108 SCIPdebugMessage("reload original LP\n");
1109 SPxSolver::loadLP(origlp);
1110 m_sense = sense();
1111
1112 /* set basis from preprocessed lp and reoptimize */
1113 if( rstat != NULL && cstat != NULL )
1114 {
1115 SCIPdebugMessage("load unsimplified basis into original LP\n");
1116 SPxSolver::setBasis(rstat, cstat);
1117 }
1118
1119 SCIPdebugMessage("solve original LP\n");
1120#ifndef NDEBUG
1121 doSolve();
1122#else
1123 doSolve(false);
1124#endif
1125
1126 /* free allocated memory */
1127 if( cstat != NULL )
1128 spx_free(cstat);
1129 if( rstat != NULL )
1130 spx_free(rstat);
1131 if( scaler != NULL )
1132 {
1133 scaler->~SPxEquiliSC();
1134 spx_free(scaler);
1135 }
1136 if( simplifier != NULL )
1137 {
1138 simplifier->~SPxMainSM();
1139 spx_free(simplifier);
1140 }
1141 }
1142
1143 if( m_stat == OPTIMAL )
1144 {
1145 Real objval = value();
1146
1147 if( (objval > m_objUpLimit) || (objval < m_objLoLimit) )
1148 m_stat = ABORT_VALUE;
1149 }
1150
1151 return m_stat;
1152 }
1153
1154 /** save the current basis */
1155 void savePreStrongbranchingBasis()
1156 {
1157 m_rowstat.reSize(nRows());
1158 m_colstat.reSize(nCols());
1159
1160 try
1161 {
1162 m_stat = getBasis(m_rowstat.get_ptr(), m_colstat.get_ptr());
1163 }
1164#ifndef NDEBUG
1165 catch( const SPxException& x )
1166 {
1167 std::string s = x.what();
1168 SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1169
1170 /* since it is not clear if the status in SoPlex are set correctly
1171 * we want to make sure that if an error is thrown the status is
1172 * not OPTIMAL anymore.
1173 */
1174 assert(m_stat != SPxSolver::OPTIMAL);
1175 }
1176#else
1177 catch( const SPxException& )
1178 { }
1179#endif
1180
1181 }
1182
1183 /** restore basis */
1184 void restorePreStrongbranchingBasis()
1185 {
1186 assert(m_rowstat.size() == nRows());
1187 assert(m_colstat.size() == nCols());
1188
1189 try
1190 {
1191 setBasis(m_rowstat.get_const_ptr(), m_colstat.get_const_ptr());
1192 }
1193#ifndef NDEBUG
1194 catch( const SPxException& x )
1195 {
1196 std::string s = x.what();
1197 SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1198#else
1199 catch( const SPxException& )
1200 {
1201#endif
1202 m_stat = SPxSolver::status();
1203
1204 /* since it is not clear if the status in SoPlex are set correctly
1205 * we want to make sure that if an error is thrown the status is
1206 * not OPTIMAL anymore.
1207 */
1208 assert(m_stat != SPxSolver::OPTIMAL);
1209 }
1210 }
1211
1212 /** if basis is in store, delete it without restoring it */
1213 void freePreStrongbranchingBasis()
1214 {
1215 m_rowstat.clear();
1216 m_colstat.clear();
1217 }
1218
1219 /** is pre-strong-branching basis freed? */
1220 bool preStrongbranchingBasisFreed() const
1221 {
1222 return ((m_rowstat.size() == 0 ) && (m_colstat.size() == 0));
1223 }
1224
1225 /** provides access for temporary storage of basis status of rows */
1226 DataArray<SPxSolver::VarStatus>& rowStat()
1227 {
1228 return m_rowstat;
1229 }
1230
1231 /** provides access for temporary storage of basis status or columns */
1232 DataArray<SPxSolver::VarStatus>& colStat()
1233 {
1234 return m_colstat;
1235 }
1236
1237 Status getStatus() const
1238 {
1239 return m_stat;
1240 }
1241
1242 Status updateStatus()
1243 {
1244 m_stat = SPxSolver::status();
1245 return m_stat;
1246 }
1247
1248 bool isInitialized() const
1249 {/*lint !e1511*/
1250 return SPxSolver::isInitialized();
1251 }
1252
1253 int iterations() const
1254 {/*lint !e1511*/
1255 return m_itused;
1256 }
1257
1258 virtual void clear()
1259 {
1260 SPxSolver::clear();
1261 freePreStrongbranchingBasis();
1262 m_stat = NO_PROBLEM;
1263 m_sense = sense();
1264 }
1265
1266 bool readLP(const char* fname)
1267 {
1268 clear();
1269
1270 if ( m_rownames != 0 )
1271 m_rownames->~NameSet();
1272 else
1273 spx_alloc(m_colnames, 1);
1274
1275 if ( m_colnames != 0 )
1276 m_colnames->~NameSet();
1277 else
1278 spx_alloc(m_rownames, 1);
1279
1280 m_rownames = new (m_rownames) NameSet();
1281 m_colnames = new (m_colnames) NameSet();
1282
1283 if( SPxSolver::readFile(fname, m_rownames, m_colnames) )
1284 {
1285 m_stat = NO_PROBLEM;
1286 m_sense = sense();
1287 return true;
1288 }
1289
1290 return false;
1291 }
1292
1293 /** copy column names into namestorage with access via colnames */
1294 void getColNames(
1295 int firstcol, /**< first column to get name from LP */
1296 int lastcol, /**< last column to get name from LP */
1297 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) */
1298 char* namestorage, /**< storage for col names */
1299 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
1300 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) */
1301 )
1302 {
1303 assert(m_colnames != NULL);
1304 assert(firstcol >= 0);
1305 assert(firstcol <= lastcol + 1);
1306
1307 // compute size
1308 if( namestoragesize == 0 )
1309 {
1310 // the following may overestimate the space requirements
1311 *storageleft = -m_colnames->memSize();
1312 }
1313 else
1314 {
1315 NameSet* names = m_colnames;
1316 assert(names != 0);
1317 int sizeleft = namestoragesize;
1318 char* s = namestorage;
1319 for( int j = firstcol; j <= lastcol; ++j )
1320 {
1321 const char* t = (*names)[j];
1322 colnames[j-firstcol] = s;
1323 while( *t != '\0' && sizeleft >= 0 )
1324 {
1325 *(s++) = *(t++);
1326 --sizeleft;
1327 }
1328 *(s++) = '\0';
1329 }
1330 if( sizeleft == 0 )
1331 {
1332 *storageleft = namestoragesize - m_colnames->memSize();
1333 assert(*storageleft <= 0);
1334 }
1335 else
1336 *storageleft = sizeleft;
1337 }
1338 }
1339
1340 /** copy row names into namestorage with access via row */
1341 void getRowNames(
1342 int firstrow, /**< first row to get name from LP */
1343 int lastrow, /**< last row to get name from LP */
1344 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) */
1345 char* namestorage, /**< storage for row names */
1346 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1347 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) */
1348 )
1349 {
1350 assert(m_rownames != NULL);
1351 assert(firstrow >= 0);
1352 assert(firstrow <= lastrow + 1);
1353
1354 // compute size
1355 if( namestoragesize == 0 )
1356 {
1357 // the following may overestimate the space requirements
1358 *storageleft = -m_rownames->memSize();
1359 }
1360 else
1361 {
1362 NameSet* names = m_rownames;
1363 assert(names != 0);
1364 int sizeleft = namestoragesize;
1365 char* s = namestorage;
1366 for( int i = firstrow; i <= lastrow; ++i )
1367 {
1368 const char* t = (*names)[i];
1369 rownames[i-firstrow] = s;
1370 while( *t != '\0' && sizeleft >= 0 )
1371 {
1372 *(s++) = *(t++);
1373 --sizeleft;
1374 }
1375 *(s++) = '\0';
1376 }
1377 if( sizeleft == 0 )
1378 {
1379 *storageleft = m_rownames->memSize() - namestoragesize;
1380 assert(*storageleft <= 0);
1381 }
1382 else
1383 *storageleft = sizeleft;
1384 }
1385 }
1386}; /*lint !e1748*/
1387
1388
1389
1390
1391/********************************************************************/
1392/*----------------------------- C --------------------------------*/
1393/********************************************************************/
1394
1395#include "lpi/lpi.h"
1396#include "scip/bitencode.h"
1397
1398typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
1399#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
1400typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
1401#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
1402
1403
1404
1405/** LP interface */
1406struct SCIP_LPi
1407{
1408 SPxSCIP* spx; /**< our SPxSolver implementation */
1409 int* cstat; /**< array for storing column basis status */
1410 int* rstat; /**< array for storing row basis status */
1411 int cstatsize; /**< size of cstat array */
1412 int rstatsize; /**< size of rstat array */
1413 SCIP_PRICING pricing; /**< current pricing strategy */
1414 SCIP_Bool solved; /**< was the current LP solved? */
1415 SLUFactor* factorization; /**< factorization possibly needed for basis inverse */
1416 SCIP_Real rowrepswitch; /**< use row representation if number of rows divided by number of columns exceeds this value */
1417 SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
1418 SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
1419 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
1420};
1421
1422/** LPi state stores basis information */
1423struct SCIP_LPiState
1424{
1425 int ncols; /**< number of LP columns */
1426 int nrows; /**< number of LP rows */
1427 COLPACKET* packcstat; /**< column basis status in compressed form */
1428 ROWPACKET* packrstat; /**< row basis status in compressed form */
1429};
1430
1431/** LPi norms to store dual steepest edge */
1432struct SCIP_LPiNorms
1433{
1434 int nrows; /**< number of stored norms corresponding to rows */
1435 int ncols; /**< number of stored norms corresponding to cols */
1436 SCIP_Real* norms; /**< norms to be (re)stored */
1437};
1438
1439
1440/*
1441 * dynamic memory arrays
1442 */
1443
1444/** resizes cstat array to have at least num entries */
1445static
1447 SCIP_LPI* lpi, /**< LP interface structure */
1448 int num /**< minimal number of entries in array */
1449 )
1450{
1451 assert(lpi != NULL);
1452
1453 if( num > lpi->cstatsize )
1454 {
1455 int newsize;
1456
1457 newsize = MAX(2*lpi->cstatsize, num);
1458 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
1459 lpi->cstatsize = newsize;
1460 }
1461 assert(num <= lpi->cstatsize);
1462
1463 return SCIP_OKAY;
1464}
1465
1466/** resizes rstat array to have at least num entries */
1467static
1469 SCIP_LPI* lpi, /**< LP interface structure */
1470 int num /**< minimal number of entries in array */
1471 )
1472{
1473 assert(lpi != NULL);
1474
1475 if( num > lpi->rstatsize )
1476 {
1477 int newsize;
1478
1479 newsize = MAX(2*lpi->rstatsize, num);
1480 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
1481 lpi->rstatsize = newsize;
1482 }
1483 assert(num <= lpi->rstatsize);
1484
1485 return SCIP_OKAY;
1486}
1487
1488
1489
1490
1491/*
1492 * LPi state methods
1493 */
1494
1495/** returns the number of packets needed to store column packet information */
1496static
1498 int ncols /**< number of columns to store */
1499 )
1500{
1501 return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
1502}
1503
1504/** returns the number of packets needed to store row packet information */
1505static
1507 int nrows /**< number of rows to store */
1508 )
1509{
1510 return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
1511}
1512
1513/** store row and column basis status in a packed LPi state object */
1514static
1516 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
1517 const int* cstat, /**< basis status of columns in unpacked format */
1518 const int* rstat /**< basis status of rows in unpacked format */
1519 )
1520{
1521 assert(lpistate != NULL);
1522 assert(lpistate->packcstat != NULL);
1523 assert(lpistate->packrstat != NULL);
1524
1525 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
1526 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
1527}
1528
1529/** unpacks row and column basis status from a packed LPi state object */
1530static
1532 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
1533 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
1534 int* rstat /**< buffer for storing basis status of rows in unpacked format */
1535 )
1536{
1537 assert(lpistate != NULL);
1538 assert(lpistate->packcstat != NULL);
1539 assert(lpistate->packrstat != NULL);
1540
1541 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
1542 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
1543}
1544
1545/** creates LPi state information object */
1546static
1548 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
1549 BMS_BLKMEM* blkmem, /**< block memory */
1550 int ncols, /**< number of columns to store */
1551 int nrows /**< number of rows to store */
1552 )
1553{
1554 assert(lpistate != NULL);
1555 assert(blkmem != NULL);
1556 assert(ncols >= 0);
1557 assert(nrows >= 0);
1558
1559 int nColPackets = colpacketNum(ncols);
1560 int nRowPackets = rowpacketNum(nrows);
1561
1562 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
1563 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
1564 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
1565
1566 return SCIP_OKAY;
1567}
1568
1569/** frees LPi state information */
1570static
1572 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
1573 BMS_BLKMEM* blkmem /**< block memory */
1574 )
1575{
1576 assert(blkmem != NULL);
1577 assert(lpistate != NULL);
1578 assert(*lpistate != NULL);
1579
1580 int nColPackets = colpacketNum((*lpistate)->ncols);
1581 int nRowPackets = rowpacketNum((*lpistate)->nrows);
1582
1583 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
1584 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
1585 BMSfreeBlockMemory(blkmem, lpistate);
1586}
1587
1588
1589
1590
1591/*
1592 * local methods
1593 */
1594
1595/** converts SCIP's objective sense into SoPlex's objective sense */
1596static
1597SPxLP::SPxSense spxObjsen(
1598 SCIP_OBJSEN objsen /**< SCIP's objective sense value */
1599 )
1600{
1601 switch( objsen )
1602 {
1604 return SPxLP::MAXIMIZE;
1606 return SPxLP::MINIMIZE;
1607 default:
1608 SCIPerrorMessage("invalid objective sense\n");
1609 SCIPABORT();
1610 return SPxLP::MINIMIZE; /*lint !e527 */
1611 }
1612}
1613
1614/** marks the current LP to be unsolved */
1615static
1617{
1618 assert(lpi != NULL);
1619 lpi->solved = FALSE;
1620 if ( lpi->factorization != 0 )
1621 {
1622 delete lpi->factorization;
1623 lpi->factorization = 0;
1624 }
1625}
1626
1627
1628
1629/*
1630 * LP Interface Methods
1631 */
1632
1633
1634/*
1635 * Miscellaneous Methods
1636 */
1637
1638char* initSpxDesc( );
1639
1640#if (SOPLEX_SUBVERSION > 0)
1641 const static char spxname[20]= {'S', 'o', 'p', 'l', 'e', 'x', '1', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '.', SOPLEX_SUBVERSION + '0', '\0'};
1642#else
1643 const static char spxname[20] = {'S', 'o', 'p', 'l', 'e', 'x', '1', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '\0'};
1644#endif
1645
1646static char* spxdesc = initSpxDesc();
1647
1649{
1650 spxdesc = new char[200];
1651 (void)snprintf(spxdesc, 200, "%s [GitHash: %s]", "Linear Programming Solver developed at Zuse Institute Berlin (soplex.zib.de)"
1652#ifdef SCIP_WITH_LPSCHECK
1653 " - including CPLEX double check"
1654#endif
1655 , getGitHash());
1656 return spxdesc;
1657}
1658
1659/**@name Miscellaneous Methods */
1660/**@{ */
1661
1662/** gets name and version of LP solver */
1664 void
1665 )
1666{
1667 SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
1668 return spxname;
1669}
1670
1671/** gets description of LP solver (developer, webpage, ...) */
1673 void
1674 )
1675{
1676 return spxdesc;
1677}
1678
1679/** gets pointer for LP solver - use only with great care */
1681 SCIP_LPI* lpi /**< pointer to an LP interface structure */
1682 )
1683{
1684 return (void*) lpi->spx;
1685}
1686
1687/** pass integrality information about variables to the solver */
1689 SCIP_LPI* lpi, /**< pointer to an LP interface structure */
1690 int ncols, /**< length of integrality array */
1691 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
1692 )
1693{
1694#if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1695 assert(ncols == lpi->spx->nCols() || (ncols == 0 && intInfo == NULL));
1696 lpi->spx->setIntegralityInformation(ncols, intInfo);
1697 return SCIP_OKAY;
1698#else
1699 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1700 return SCIP_LPERROR;
1701#endif
1702}
1703
1704/** informs about availability of a primal simplex solving method */
1706 void
1707 )
1708{
1709 return TRUE;
1710}
1711
1712/** informs about availability of a dual simplex solving method */
1714 void
1715 )
1716{
1717 return TRUE;
1718}
1719
1720/** informs about availability of a barrier solving method */
1722 void
1723 )
1724{
1725 return FALSE;
1726}
1727
1728/**@} */
1729
1730
1731
1732
1733/*
1734 * LPI Creation and Destruction Methods
1735 */
1736
1737/**@name LPI Creation and Destruction Methods */
1738/**@{ */
1739
1740/** creates an LP problem object */
1742 SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1743 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1744 const char* name, /**< problem name */
1745 SCIP_OBJSEN objsen /**< objective sense */
1746 )
1747{
1748 assert(lpi != NULL);
1749 assert(name != NULL);
1750
1751 /* create SoPlex object */
1752 SCIP_ALLOC( BMSallocMemory(lpi) );
1753
1754 /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1755 (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1756 SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1757 (*lpi)->cstat = NULL;
1758 (*lpi)->rstat = NULL;
1759 (*lpi)->cstatsize = 0;
1760 (*lpi)->rstatsize = 0;
1761 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1762 (*lpi)->factorization = 0;
1763 (*lpi)->rowrepswitch = SCIPlpiInfinity(*lpi);
1764 (*lpi)->conditionlimit = -1.0;
1765 (*lpi)->checkcondition = FALSE;
1766 (*lpi)->messagehdlr = messagehdlr;
1767
1768 invalidateSolution(*lpi);
1769
1770 /* set objective sense */
1771 SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
1772
1773 /* set default pricing */
1774 SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1775
1776 return SCIP_OKAY;
1777}
1778
1779/** deletes an LP problem object */
1781 SCIP_LPI** lpi /**< pointer to an LP interface structure */
1782 )
1783{
1784 assert(lpi != NULL);
1785 assert(*lpi != NULL);
1786 assert((*lpi)->spx != NULL);
1787
1788 /* free LP using destructor and free memory via blockmemshell */
1789 (*lpi)->spx->~SPxSCIP();
1790 BMSfreeMemory(&((*lpi)->spx));
1791
1792 /* free memory */
1793 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1794 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1795 BMSfreeMemory(lpi);
1796
1797 return SCIP_OKAY;
1798}
1799
1800/**@} */
1801
1802
1803
1804
1805/*
1806 * Modification Methods
1807 */
1808
1809/**@name Modification Methods */
1810/**@{ */
1811
1812/** copies LP data with column matrix into LP solver */
1814 SCIP_LPI* lpi, /**< LP interface structure */
1815 SCIP_OBJSEN objsen, /**< objective sense */
1816 int ncols, /**< number of columns */
1817 const SCIP_Real* obj, /**< objective function values of columns */
1818 const SCIP_Real* lb, /**< lower bounds of columns */
1819 const SCIP_Real* ub, /**< upper bounds of columns */
1820 char** colnames, /**< column names, or NULL */
1821 int nrows, /**< number of rows */
1822 const SCIP_Real* lhs, /**< left hand sides of rows */
1823 const SCIP_Real* rhs, /**< right hand sides of rows */
1824 char** /*rownames*/, /**< row names, or NULL */
1825 int nnonz, /**< number of nonzero elements in the constraint matrix */
1826 const int* beg, /**< start index of each column in ind- and val-array */
1827 const int* ind, /**< row indices of constraint matrix entries */
1828 const SCIP_Real* val /**< values of constraint matrix entries */
1829 )
1830{
1831#ifndef NDEBUG
1832 {
1833 int j;
1834 for( j = 0; j < nnonz; j++ )
1835 assert( val[j] != 0 );
1836 }
1837#endif
1838
1839 SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1840
1841 assert(lpi != NULL);
1842 assert(lpi->spx != NULL);
1843 assert(lhs != NULL);
1844 assert(rhs != NULL);
1845 assert(obj != NULL);
1846 assert(lb != NULL);
1847 assert(ub != NULL);
1848 assert(beg != NULL);
1849 assert(ind != NULL);
1850 assert(val != NULL);
1851
1852 invalidateSolution(lpi);
1853 assert( lpi->spx->preStrongbranchingBasisFreed() );
1854
1855 try
1856 {
1857 SPxSCIP* spx = lpi->spx;
1858 LPRowSet rows(nrows);
1859 DSVector emptyVector(0);
1860 int i;
1861
1862 spx->clear();
1863
1864 /* set objective sense */
1865 spx->setSense(spxObjsen(objsen));
1866
1867 /* create empty rows with given sides */
1868 for( i = 0; i < nrows; ++i )
1869 rows.add(lhs[i], emptyVector, rhs[i]);
1870 spx->addRows(rows);
1871
1872 /* create column vectors with coefficients and bounds */
1873 SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1874 }
1875#ifndef NDEBUG
1876 catch( const SPxException& x )
1877 {
1878 std::string s = x.what();
1879 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1880#else
1881 catch( const SPxException& )
1882 {
1883#endif
1884 return SCIP_LPERROR;
1885 }
1886
1887 return SCIP_OKAY;
1888}
1889
1890/** adds columns to the LP */
1892 SCIP_LPI* lpi, /**< LP interface structure */
1893 int ncols, /**< number of columns to be added */
1894 const SCIP_Real* obj, /**< objective function values of new columns */
1895 const SCIP_Real* lb, /**< lower bounds of new columns */
1896 const SCIP_Real* ub, /**< upper bounds of new columns */
1897 char** /*colnames*/, /**< column names, or NULL */
1898 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1899 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1900 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1901 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1902 )
1903{
1904 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1905
1906 assert(lpi != NULL);
1907 assert(lpi->spx != NULL);
1908 assert(obj != NULL);
1909 assert(lb != NULL);
1910 assert(ub != NULL);
1911 assert(nnonz == 0 || beg != NULL);
1912 assert(nnonz == 0 || ind != NULL);
1913 assert(nnonz == 0 || val != NULL);
1914 assert(nnonz >= 0);
1915 assert(ncols >= 0);
1916
1917 invalidateSolution(lpi);
1918
1919 assert( lpi->spx->preStrongbranchingBasisFreed() );
1920
1921#ifndef NDEBUG
1922 if ( nnonz > 0 )
1923 {
1924 /* perform check that no new rows are added - this is likely to be a mistake */
1925 int nrows = lpi->spx->nRows();
1926 for (int j = 0; j < nnonz; ++j)
1927 {
1928 assert( 0 <= ind[j] && ind[j] < nrows );
1929 assert( val[j] != 0.0 );
1930 }
1931 }
1932#endif
1933
1934 SPxSCIP* spx = lpi->spx;
1935 try
1936 {
1937 LPColSet cols(ncols);
1938 DSVector colVector(ncols);
1939 int start;
1940 int last;
1941 int i;
1942
1943 /* create column vectors with coefficients and bounds */
1944 for( i = 0; i < ncols; ++i )
1945 {
1946 colVector.clear();
1947 if( nnonz > 0 )
1948 {
1949 start = beg[i];
1950 last = (i == ncols-1 ? nnonz : beg[i+1]);
1951 colVector.add( last-start, &ind[start], &val[start] );
1952 }
1953 cols.add(obj[i], lb[i], colVector, ub[i]);
1954 }
1955 spx->addCols(cols);
1956 }
1957#ifndef NDEBUG
1958 catch( const SPxException& x )
1959 {
1960 std::string s = x.what();
1961 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1962#else
1963 catch( const SPxException& )
1964 {
1965#endif
1966 return SCIP_LPERROR;
1967 }
1968
1969 return SCIP_OKAY;
1970}
1971
1972/** deletes all columns in the given range from LP */
1974 SCIP_LPI* lpi, /**< LP interface structure */
1975 int firstcol, /**< first column to be deleted */
1976 int lastcol /**< last column to be deleted */
1977 )
1978{
1979 assert(lpi != NULL);
1980 assert(lpi->spx != NULL);
1981 assert(firstcol >= 0);
1982 assert(lastcol < lpi->spx->nCols());
1983 assert(firstcol <= lastcol + 1);
1984
1985 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1986
1987 // handle empty range
1988 if( firstcol > lastcol )
1989 return SCIP_OKAY;
1990
1991 invalidateSolution(lpi);
1992
1993 assert( lpi->spx->preStrongbranchingBasisFreed() );
1994
1995 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRange(firstcol, lastcol) );
1996
1997 return SCIP_OKAY;
1998}
1999
2000/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
2002 SCIP_LPI* lpi, /**< LP interface structure */
2003 int* dstat /**< deletion status of columns
2004 * input: 1 if column should be deleted, 0 if not
2005 * output: new position of column, -1 if column was deleted */
2006 )
2007{
2008 int ncols;
2009 int i;
2010
2011 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
2012
2013 assert(lpi != NULL);
2014 assert(lpi->spx != NULL);
2015 assert(dstat != NULL);
2016
2017 invalidateSolution(lpi);
2018
2019 assert( lpi->spx->preStrongbranchingBasisFreed() );
2020
2021 ncols = lpi->spx->nCols();
2022
2023 /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
2024 for( i = 0; i < ncols; ++i )
2025 dstat[i] *= -1;
2026
2027 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeCols(dstat) );
2028
2029 return SCIP_OKAY;
2030}
2031
2032/** adds rows to the LP */
2034 SCIP_LPI* lpi, /**< LP interface structure */
2035 int nrows, /**< number of rows to be added */
2036 const SCIP_Real* lhs, /**< left hand sides of new rows */
2037 const SCIP_Real* rhs, /**< right hand sides of new rows */
2038 char** /*rownames*/, /**< row names, or NULL */
2039 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
2040 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
2041 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
2042 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
2043 )
2044{
2045 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
2046
2047 assert(lpi != NULL);
2048 assert(lpi->spx != NULL);
2049 assert(lhs != NULL);
2050 assert(rhs != NULL);
2051 assert(nnonz == 0 || beg != NULL);
2052 assert(nnonz == 0 || ind != NULL);
2053 assert(nnonz == 0 || val != NULL);
2054
2055 invalidateSolution(lpi);
2056
2057 assert( lpi->spx->preStrongbranchingBasisFreed() );
2058
2059#ifndef NDEBUG
2060 if ( nnonz > 0 )
2061 {
2062 /* perform check that no new columns are added - this is likely to be a mistake */
2063 int ncols = lpi->spx->nCols();
2064 for (int j = 0; j < nnonz; ++j)
2065 {
2066 assert( 0 <= ind[j] && ind[j] < ncols );
2067 assert( val[j] != 0.0 );
2068 }
2069 }
2070#endif
2071
2072 try
2073 {
2074 SPxSCIP* spx = lpi->spx;
2075 LPRowSet rows(nrows);
2076 DSVector rowVector;
2077 int start;
2078 int last;
2079 int i;
2080
2081 /* create row vectors with given sides */
2082 for( i = 0; i < nrows; ++i )
2083 {
2084 rowVector.clear();
2085 if( nnonz > 0 )
2086 {
2087 start = beg[i];
2088 last = (i == nrows-1 ? nnonz : beg[i+1]);
2089 rowVector.add( last-start, &ind[start], &val[start] );
2090 }
2091 rows.add(lhs[i], rowVector, rhs[i]);
2092 }
2093 spx->addRows(rows);
2094 }
2095#ifndef NDEBUG
2096 catch( const SPxException& x )
2097 {
2098 std::string s = x.what();
2099 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2100#else
2101 catch( const SPxException& )
2102 {
2103#endif
2104 return SCIP_LPERROR;
2105 }
2106
2107 return SCIP_OKAY;
2108}
2109
2110/** deletes all rows in the given range from LP */
2112 SCIP_LPI* lpi, /**< LP interface structure */
2113 int firstrow, /**< first row to be deleted */
2114 int lastrow /**< last row to be deleted */
2115 )
2116{
2117 assert(lpi != NULL);
2118 assert(lpi->spx != NULL);
2119 assert(firstrow >= 0);
2120 assert(lastrow < lpi->spx->nRows());
2121 assert(firstrow <= lastrow + 1);
2122
2123 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
2124
2125 // handle empty range
2126 if( firstrow > lastrow )
2127 return SCIP_OKAY;
2128
2129 invalidateSolution(lpi);
2130
2131 assert( lpi->spx->preStrongbranchingBasisFreed() );
2132
2133 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRange(firstrow, lastrow) );
2134
2135 return SCIP_OKAY;
2136}
2137
2138/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
2140 SCIP_LPI* lpi, /**< LP interface structure */
2141 int* dstat /**< deletion status of rows
2142 * input: 1 if row should be deleted, 0 if not
2143 * output: new position of row, -1 if row was deleted */
2144 )
2145{
2146 int nrows;
2147 int i;
2148
2149 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
2150
2151 assert(lpi != NULL);
2152 assert(lpi->spx != NULL);
2153
2154 invalidateSolution(lpi);
2155
2156 assert( lpi->spx->preStrongbranchingBasisFreed() );
2157
2158 nrows = lpi->spx->nRows();
2159
2160 /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
2161 for( i = 0; i < nrows; ++i )
2162 dstat[i] *= -1;
2163
2164 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRows(dstat) );
2165
2166 return SCIP_OKAY;
2167}
2168
2169/** clears the whole LP */
2171 SCIP_LPI* lpi /**< LP interface structure */
2172 )
2173{
2174 SCIPdebugMessage("calling SCIPlpiClear()\n");
2175
2176 assert(lpi != NULL);
2177 assert(lpi->spx != NULL);
2178
2179 invalidateSolution(lpi);
2180
2181 assert( lpi->spx->preStrongbranchingBasisFreed() );
2182 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clear() );
2183
2184 return SCIP_OKAY;
2185}
2186
2187/** changes lower and upper bounds of columns */
2189 SCIP_LPI* lpi, /**< LP interface structure */
2190 int ncols, /**< number of columns to change bounds for */
2191 const int* ind, /**< column indices or NULL if ncols is zero */
2192 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
2193 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
2194 )
2195{
2196 int i;
2197
2198 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
2199
2200 assert(lpi != NULL);
2201 assert(lpi->spx != NULL);
2202 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
2203 if( ncols <= 0 )
2204 return SCIP_OKAY;
2205
2206 invalidateSolution(lpi);
2207
2208 assert( lpi->spx->preStrongbranchingBasisFreed() );
2209
2210 try
2211 {
2212 for( i = 0; i < ncols; ++i )
2213 {
2214 assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2215
2216 if ( SCIPlpiIsInfinity(lpi, lb[i]) )
2217 {
2218 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
2219 return SCIP_LPERROR;
2220 }
2221 if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
2222 {
2223 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
2224 return SCIP_LPERROR;
2225 }
2226
2227 lpi->spx->changeBounds(ind[i], lb[i], ub[i]);
2228 assert(lpi->spx->lower(ind[i]) <= lpi->spx->upper(ind[i]) + Param::epsilon());
2229 }
2230 }
2231#ifndef NDEBUG
2232 catch( const SPxException& x )
2233 {
2234 std::string s = x.what();
2235 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2236#else
2237 catch( const SPxException& )
2238 {
2239#endif
2240 return SCIP_LPERROR;
2241 }
2242
2243 return SCIP_OKAY;
2244}
2245
2246/** changes left and right hand sides of rows */
2248 SCIP_LPI* lpi, /**< LP interface structure */
2249 int nrows, /**< number of rows to change sides for */
2250 const int* ind, /**< row indices */
2251 const SCIP_Real* lhs, /**< new values for left hand sides */
2252 const SCIP_Real* rhs /**< new values for right hand sides */
2253 )
2254{
2255 int i;
2256
2257 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
2258
2259 assert(lpi != NULL);
2260 assert(lpi->spx != NULL);
2261 assert(ind != NULL);
2262 assert(lhs != NULL);
2263 assert(rhs != NULL);
2264 if( nrows <= 0 )
2265 return SCIP_OKAY;
2266
2267 invalidateSolution(lpi);
2268
2269 assert( lpi->spx->preStrongbranchingBasisFreed() );
2270
2271 try
2272 {
2273 for( i = 0; i < nrows; ++i )
2274 {
2275 assert(0 <= ind[i] && ind[i] < lpi->spx->nRows());
2276 lpi->spx->changeRange(ind[i], lhs[i], rhs[i]);
2277 assert(lpi->spx->lhs(ind[i]) <= lpi->spx->rhs(ind[i]) + Param::epsilon());
2278 }
2279 }
2280#ifndef NDEBUG
2281 catch( const SPxException& x )
2282 {
2283 std::string s = x.what();
2284 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2285#else
2286 catch( const SPxException& )
2287 {
2288#endif
2289 return SCIP_LPERROR;
2290 }
2291
2292 return SCIP_OKAY;
2293}
2294
2295/** changes a single coefficient */
2297 SCIP_LPI* lpi, /**< LP interface structure */
2298 int row, /**< row number of coefficient to change */
2299 int col, /**< column number of coefficient to change */
2300 SCIP_Real newval /**< new value of coefficient */
2301 )
2302{
2303 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
2304
2305 assert(lpi != NULL);
2306 assert(lpi->spx != NULL);
2307 assert(0 <= row && row < lpi->spx->nRows());
2308 assert(0 <= col && col < lpi->spx->nCols());
2309
2310 invalidateSolution(lpi);
2311
2312 assert( lpi->spx->preStrongbranchingBasisFreed() );
2313
2314 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElement(row, col, newval) );
2315
2316 return SCIP_OKAY;
2317}
2318
2319/** changes the objective sense */
2321 SCIP_LPI* lpi, /**< LP interface structure */
2322 SCIP_OBJSEN objsen /**< new objective sense */
2323 )
2324{
2325 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
2326
2327 assert(lpi != NULL);
2328 assert(lpi->spx != NULL);
2329
2330 invalidateSolution(lpi);
2331
2332 assert( lpi->spx->preStrongbranchingBasisFreed() );
2333
2334 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setSense(spxObjsen(objsen)) );
2335
2336 return SCIP_OKAY;
2337}
2338
2339/** changes objective values of columns in the LP */
2341 SCIP_LPI* lpi, /**< LP interface structure */
2342 int ncols, /**< number of columns to change objective value for */
2343 const int* ind, /**< column indices to change objective value for */
2344 const SCIP_Real* obj /**< new objective values for columns */
2345 )
2346{
2347 int i;
2348
2349 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
2350
2351 assert(lpi != NULL);
2352 assert(lpi->spx != NULL);
2353 assert(ind != NULL);
2354 assert(obj != NULL);
2355
2356 invalidateSolution(lpi);
2357
2358 assert( lpi->spx->preStrongbranchingBasisFreed() );
2359
2360 try
2361 {
2362 for( i = 0; i < ncols; ++i )
2363 {
2364 assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2365 lpi->spx->changeObj(ind[i], obj[i]);
2366 }
2367 }
2368#ifndef NDEBUG
2369 catch( const SPxException& x )
2370 {
2371 std::string s = x.what();
2372 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2373#else
2374 catch( const SPxException& )
2375 {
2376#endif
2377 return SCIP_LPERROR;
2378 }
2379
2380 return SCIP_OKAY;
2381}
2382
2383/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
2385 SCIP_LPI* lpi, /**< LP interface structure */
2386 int row, /**< row number to scale */
2387 SCIP_Real scaleval /**< scaling multiplier */
2388 )
2389{
2390 SCIP_Real lhs;
2391 SCIP_Real rhs;
2392
2393 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
2394
2395 assert(lpi != NULL);
2396 assert(lpi->spx != NULL);
2397 assert(scaleval != 0.0);
2398
2399 try
2400 {
2401 invalidateSolution(lpi);
2402
2403 assert( lpi->spx->preStrongbranchingBasisFreed() );
2404
2405 /* get the row vector and the row's sides */
2406 SVector rowvec = lpi->spx->rowVector(row);
2407 lhs = lpi->spx->lhs(row);
2408 rhs = lpi->spx->rhs(row);
2409
2410 /* scale the row vector */
2411 rowvec *= scaleval;
2412
2413 /* adjust the sides */
2414 if( lhs > -soplex::infinity )
2415 lhs *= scaleval;
2416 else if( scaleval < 0.0 )
2417 lhs = soplex::infinity;
2418 if( rhs < soplex::infinity )
2419 rhs *= scaleval;
2420 else if( scaleval < 0.0 )
2421 rhs = -soplex::infinity;
2422 if( scaleval < 0.0 )
2423 {
2424 SCIP_Real oldlhs = lhs;
2425 lhs = rhs;
2426 rhs = oldlhs;
2427 }
2428
2429 /* create the new row */
2430 LPRow lprow(lhs, rowvec, rhs);
2431
2432 /* change the row in the LP */
2433 lpi->spx->changeRow(row, lprow);
2434 assert(lpi->spx->lhs(row) <= lpi->spx->rhs(row));
2435 }
2436#ifndef NDEBUG
2437 catch( const SPxException& x )
2438 {
2439 std::string s = x.what();
2440 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2441#else
2442 catch( const SPxException& )
2443 {
2444#endif
2445 return SCIP_LPERROR;
2446 }
2447
2448 return SCIP_OKAY;
2449}
2450
2451/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
2452 * are divided by the scalar; for negative scalars, the column's bounds are switched
2453 */
2455 SCIP_LPI* lpi, /**< LP interface structure */
2456 int col, /**< column number to scale */
2457 SCIP_Real scaleval /**< scaling multiplier */
2458 )
2459{
2460 SCIP_Real obj;
2461 SCIP_Real lb;
2462 SCIP_Real ub;
2463
2464 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
2465
2466 assert(lpi != NULL);
2467 assert(lpi->spx != NULL);
2468 assert(scaleval != 0.0);
2469
2470 try
2471 {
2472 invalidateSolution(lpi);
2473
2474 assert( lpi->spx->preStrongbranchingBasisFreed() );
2475
2476 /* get the col vector and the col's bounds and objective value */
2477 SVector colvec = lpi->spx->colVector(col);
2478 obj = lpi->spx->obj(col);
2479 lb = lpi->spx->lower(col);
2480 ub = lpi->spx->upper(col);
2481
2482 /* scale the col vector */
2483 colvec *= scaleval;
2484
2485 /* scale the objective value */
2486 obj *= scaleval;
2487
2488 /* adjust the bounds */
2489 if( lb > -soplex::infinity )
2490 lb /= scaleval;
2491 else if( scaleval < 0.0 )
2492 lb = soplex::infinity;
2493 if( ub < soplex::infinity )
2494 ub /= scaleval;
2495 else if( scaleval < 0.0 )
2496 ub = -soplex::infinity;
2497 if( scaleval < 0.0 )
2498 {
2499 SCIP_Real oldlb = lb;
2500 lb = ub;
2501 ub = oldlb;
2502 }
2503
2504 /* create the new col (in LPCol's constructor, the upper bound is given first!) */
2505 LPCol lpcol(obj, colvec, ub, lb);
2506
2507 /* change the col in the LP */
2508 lpi->spx->changeCol(col, lpcol);
2509 assert(lpi->spx->lower(col) <= lpi->spx->upper(col));
2510 }
2511#ifndef NDEBUG
2512 catch( const SPxException& x )
2513 {
2514 std::string s = x.what();
2515 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2516#else
2517 catch( const SPxException& )
2518 {
2519#endif
2520 return SCIP_LPERROR;
2521 }
2522
2523 return SCIP_OKAY;
2524}
2525
2526/**@} */
2527
2528
2529
2530
2531/*
2532 * Data Accessing Methods
2533 */
2534
2535/**@name Data Accessing Methods */
2536/**@{ */
2537
2538/** gets the number of rows in the LP */
2540 SCIP_LPI* lpi, /**< LP interface structure */
2541 int* nrows /**< pointer to store the number of rows */
2542 )
2543{
2544 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
2545
2546 assert(lpi != NULL);
2547 assert(lpi->spx != NULL);
2548 assert(nrows != NULL);
2549
2550 *nrows = lpi->spx->nRows();
2551
2552 return SCIP_OKAY;
2553}
2554
2555/** gets the number of columns in the LP */
2557 SCIP_LPI* lpi, /**< LP interface structure */
2558 int* ncols /**< pointer to store the number of cols */
2559 )
2560{
2561 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
2562
2563 assert(lpi != NULL);
2564 assert(lpi->spx != NULL);
2565 assert(ncols != NULL);
2566
2567 *ncols = lpi->spx->nCols();
2568
2569 return SCIP_OKAY;
2570}
2571
2572/** gets the number of nonzero elements in the LP constraint matrix */
2574 SCIP_LPI* lpi, /**< LP interface structure */
2575 int* nnonz /**< pointer to store the number of nonzeros */
2576 )
2577{
2578 int i;
2579
2580 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
2581
2582 assert(lpi != NULL);
2583 assert(lpi->spx != NULL);
2584 assert(nnonz != NULL);
2585
2586 /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
2587 *nnonz = 0;
2588 if( lpi->spx->nRows() < lpi->spx->nCols() )
2589 {
2590 for( i = 0; i < lpi->spx->nRows(); ++i )
2591 (*nnonz) += lpi->spx->rowVector(i).size();
2592 }
2593 else
2594 {
2595 for( i = 0; i < lpi->spx->nCols(); ++i )
2596 (*nnonz) += lpi->spx->colVector(i).size();
2597 }
2598
2599 return SCIP_OKAY;
2600}
2601
2602/** gets columns from LP problem object; the arrays have to be large enough to store all values
2603 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
2604 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2605 */
2607 SCIP_LPI* lpi, /**< LP interface structure */
2608 int firstcol, /**< first column to get from LP */
2609 int lastcol, /**< last column to get from LP */
2610 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
2611 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
2612 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2613 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
2614 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
2615 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2616 )
2617{
2618 int i;
2619 int j;
2620
2621 assert(lpi != NULL);
2622 assert(lpi->spx != NULL);
2623 assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
2624 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2625 assert(firstcol >= 0);
2626 assert(lastcol < lpi->spx->nCols());
2627 assert(firstcol <= lastcol + 1);
2628
2629 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
2630
2631 if( lb != NULL )
2632 {
2633 const Vector& lbvec = lpi->spx->lower();
2634 const Vector& ubvec = lpi->spx->upper();
2635 for( i = firstcol; i <= lastcol; ++i )
2636 {
2637 lb[i-firstcol] = lbvec[i];
2638 ub[i-firstcol] = ubvec[i];
2639 }
2640 }
2641
2642 if( nnonz != NULL )
2643 {
2644 *nnonz = 0;
2645 for( i = firstcol; i <= lastcol; ++i )
2646 {
2647 beg[i-firstcol] = *nnonz;
2648 const SVector& cvec = lpi->spx->colVector(i);
2649 for( j = 0; j < cvec.size(); ++j )
2650 {
2651 ind[*nnonz] = cvec.index(j);
2652 val[*nnonz] = cvec.value(j);
2653 (*nnonz)++;
2654 }
2655 }
2656 }
2657
2658 return SCIP_OKAY;
2659}
2660
2661/** gets rows from LP problem object; the arrays have to be large enough to store all values.
2662 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2663 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2664 */
2666 SCIP_LPI* lpi, /**< LP interface structure */
2667 int firstrow, /**< first row to get from LP */
2668 int lastrow, /**< last row to get from LP */
2669 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2670 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2671 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2672 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2673 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2674 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2675 )
2676{
2677 int i;
2678 int j;
2679
2680 assert(lpi != NULL);
2681 assert(lpi->spx != NULL);
2682 assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2683 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2684 assert(firstrow >= 0);
2685 assert(lastrow < lpi->spx->nRows());
2686 assert(firstrow <= lastrow + 1);
2687
2688 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2689
2690 if( lhs != NULL )
2691 {
2692 const Vector& lhsvec = lpi->spx->lhs();
2693 const Vector& rhsvec = lpi->spx->rhs();
2694 for( i = firstrow; i <= lastrow; ++i )
2695 {
2696 lhs[i-firstrow] = lhsvec[i];
2697 rhs[i-firstrow] = rhsvec[i];
2698 }
2699 }
2700
2701 if( nnonz != NULL )
2702 {
2703 *nnonz = 0;
2704 for( i = firstrow; i <= lastrow; ++i )
2705 {
2706 beg[i-firstrow] = *nnonz;
2707 const SVector& rvec = lpi->spx->rowVector(i);
2708 for( j = 0; j < rvec.size(); ++j )
2709 {
2710 ind[*nnonz] = rvec.index(j);
2711 val[*nnonz] = rvec.value(j);
2712 (*nnonz)++;
2713 }
2714 }
2715 }
2716
2717 return SCIP_OKAY;
2718}
2719
2720/** gets column names */
2722 SCIP_LPI* lpi, /**< LP interface structure */
2723 int firstcol, /**< first column to get name from LP */
2724 int lastcol, /**< last column to get name from LP */
2725 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2726 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2727 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2728 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2729 )
2730{
2731 assert(lpi != NULL);
2732 assert(lpi->spx != NULL);
2733 assert(colnames != NULL || namestoragesize == 0);
2734 assert(namestorage != NULL || namestoragesize == 0);
2735 assert(namestoragesize >= 0);
2736 assert(storageleft != NULL);
2737 assert(firstcol >= 0);
2738 assert(lastcol < lpi->spx->nCols());
2739 assert(firstcol <= lastcol + 1);
2740
2741 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2742
2743 lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2744
2745 return SCIP_OKAY;
2746}
2747
2748/** gets row names */
2750 SCIP_LPI* lpi, /**< LP interface structure */
2751 int firstrow, /**< first row to get name from LP */
2752 int lastrow, /**< last row to get name from LP */
2753 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2754 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2755 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2756 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2757 )
2758{
2759 assert(lpi != NULL);
2760 assert(lpi->spx != NULL);
2761 assert(rownames != NULL || namestoragesize == 0);
2762 assert(namestorage != NULL || namestoragesize == 0);
2763 assert(namestoragesize >= 0);
2764 assert(storageleft != NULL);
2765 assert(firstrow >= 0);
2766 assert(lastrow < lpi->spx->nRows());
2767 assert(firstrow <= lastrow + 1);
2768
2769 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2770
2771 lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2772
2773 return SCIP_OKAY;
2774}
2775
2776/** gets objective sense of the LP */
2778 SCIP_LPI* lpi, /**< LP interface structure */
2779 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2780 )
2781{
2782 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2783
2784 assert(lpi != NULL);
2785 assert(lpi->spx != NULL);
2786 assert(objsen != NULL);
2787
2788 *objsen = (lpi->spx->getSense() == SPxLP::MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2789
2790 return SCIP_OKAY;
2791}
2792
2793/** gets objective coefficients from LP problem object */
2795 SCIP_LPI* lpi, /**< LP interface structure */
2796 int firstcol, /**< first column to get objective coefficient for */
2797 int lastcol, /**< last column to get objective coefficient for */
2798 SCIP_Real* vals /**< array to store objective coefficients */
2799 )
2800{
2801 int i;
2802
2803 assert(lpi != NULL);
2804 assert(lpi->spx != NULL);
2805 assert(vals != NULL);
2806 assert(firstcol >= 0);
2807 assert(lastcol < lpi->spx->nCols());
2808 assert(firstcol <= lastcol + 1);
2809
2810 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2811
2812 for( i = firstcol; i <= lastcol; ++i )
2813 vals[i-firstcol] = lpi->spx->obj(i);
2814
2815 return SCIP_OKAY;
2816}
2817
2818/** gets current bounds from LP problem object */
2820 SCIP_LPI* lpi, /**< LP interface structure */
2821 int firstcol, /**< first column to get objective value for */
2822 int lastcol, /**< last column to get objective value for */
2823 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2824 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2825 )
2826{
2827 int i;
2828
2829 assert(lpi != NULL);
2830 assert(lpi->spx != NULL);
2831 assert(firstcol >= 0);
2832 assert(lastcol < lpi->spx->nCols());
2833 assert(firstcol <= lastcol + 1);
2834
2835 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2836
2837 for( i = firstcol; i <= lastcol; ++i )
2838 {
2839 if( lbs != NULL )
2840 lbs[i-firstcol] = lpi->spx->lower(i);
2841 if( ubs != NULL )
2842 ubs[i-firstcol] = lpi->spx->upper(i);
2843 }
2844
2845 return SCIP_OKAY;
2846}
2847
2848/** gets current row sides from LP problem object */
2850 SCIP_LPI* lpi, /**< LP interface structure */
2851 int firstrow, /**< first row to get sides for */
2852 int lastrow, /**< last row to get sides for */
2853 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2854 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2855 )
2856{
2857 int i;
2858
2859 assert(lpi != NULL);
2860 assert(lpi->spx != NULL);
2861 assert(firstrow >= 0);
2862 assert(lastrow < lpi->spx->nRows());
2863 assert(firstrow <= lastrow + 1);
2864
2865 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2866
2867 for( i = firstrow; i <= lastrow; ++i )
2868 {
2869 if( lhss != NULL )
2870 lhss[i-firstrow] = lpi->spx->lhs(i);
2871 if( rhss != NULL )
2872 rhss[i-firstrow] = lpi->spx->rhs(i);
2873 }
2874
2875 return SCIP_OKAY;
2876}
2877
2878/** gets a single coefficient */
2880 SCIP_LPI* lpi, /**< LP interface structure */
2881 int row, /**< row number of coefficient */
2882 int col, /**< column number of coefficient */
2883 SCIP_Real* val /**< pointer to store the value of the coefficient */
2884 )
2885{
2886 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2887
2888 assert(lpi != NULL);
2889 assert(lpi->spx != NULL);
2890 assert(0 <= col && col < lpi->spx->nCols());
2891 assert(0 <= row && row < lpi->spx->nRows());
2892 assert(val != NULL);
2893
2894 *val = lpi->spx->colVector(col)[row];
2895
2896 return SCIP_OKAY;
2897}
2898
2899/**@} */
2900
2901
2902
2903
2904/*
2905 * Solving Methods
2906 */
2907
2908/**@name Solving Methods */
2909/**@{ */
2910
2911/** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2912static
2914 SCIP_LPI* lpi, /**< LP interface structure */
2915 SPxSolver::Representation rep, /**< basis representation */
2916 SPxSolver::Type type /**< algorithm type */
2917 )
2918{
2919 assert( lpi != NULL );
2920 assert( lpi->spx != NULL );
2921 assert( rep == SPxSolver::ROW || rep == SPxSolver::COLUMN );
2922 assert( type == SPxSolver::ENTER || type == SPxSolver::LEAVE );
2923
2924 SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows, rep=%s\n", lpi->spx->nCols(), lpi->spx->nRows(),
2925 rep == SPxSolver::COLUMN ? "column" : "row");
2926
2927 invalidateSolution(lpi);
2928
2929 assert( lpi->spx->preStrongbranchingBasisFreed() );
2930
2931 /* set basis representation and algorithm type */
2932 lpi->spx->setRep(rep);
2933 lpi->spx->setType(type);
2934
2935#ifdef SCIP_WITH_LPSCHECK
2936 lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2937#endif
2938
2939 SPxSolver::Status status = lpi->spx->solve();
2940 SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->getStatus(), lpi->spx->basis().status());
2941 lpi->solved = TRUE;
2942
2943 switch( status )
2944 {
2945 case SPxSolver::ABORT_TIME:
2946 case SPxSolver::ABORT_ITER:
2947 case SPxSolver::ABORT_VALUE:
2948 case SPxSolver::SINGULAR:
2949 case SPxSolver::REGULAR:
2950 case SPxSolver::UNKNOWN:
2951 case SPxSolver::OPTIMAL:
2952 case SPxSolver::UNBOUNDED:
2953 case SPxSolver::INFEASIBLE:
2954 return SCIP_OKAY;
2955 default:
2956 return SCIP_LPERROR;
2957 } /*lint !e788*/
2958}
2959
2960/** calls primal simplex to solve the LP */
2962 SCIP_LPI* lpi /**< LP interface structure */
2963 )
2964{
2965 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2966
2967 SCIP_RETCODE retcode;
2968 SCIP_Bool rowrep;
2969
2970 assert(lpi != NULL);
2971 assert(lpi->spx != NULL);
2972
2973 /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2974 factor 1.1 for switching back to column representation */
2975 if( lpi->rowrepswitch >= 0 )
2976 {
2977 rowrep = lpi->spx->rep() == SPxSolver::ROW;
2978
2979 if( !rowrep )
2980 rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2981 else
2982 rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2983 }
2984 else
2985 rowrep = FALSE;
2986
2987 /* SoPlex doesn't distinct between the primal and dual simplex; however
2988 * we can force SoPlex to start with the desired method:
2989 * If the representation is COLUMN:
2990 * - ENTER = PRIMAL
2991 * - LEAVE = DUAL
2992 *
2993 * If the representation is ROW:
2994 * - ENTER = DUAL
2995 * - LEAVE = PRIMAL
2996 */
2997 retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::LEAVE) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::ENTER);
2998 assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
2999 assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
3000
3001 return retcode;
3002}
3003
3004/** calls dual simplex to solve the LP */
3006 SCIP_LPI* lpi /**< LP interface structure */
3007 )
3008{
3009 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
3010
3011 SCIP_RETCODE retcode;
3012 SCIP_Bool rowrep;
3013
3014 assert(lpi != NULL);
3015 assert(lpi->spx != NULL);
3016
3017 /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
3018 factor 1.1 for switching back to column representation */
3019 if( lpi->rowrepswitch >= 0 )
3020 {
3021 rowrep = lpi->spx->rep() == SPxSolver::ROW;
3022
3023 if( !rowrep )
3024 rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
3025 else
3026 rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
3027 }
3028 else
3029 rowrep = FALSE;
3030
3031 /* SoPlex doesn't distinct between the primal and dual simplex; however
3032 * we can force SoPlex to start with the desired method:
3033 * If the representation is COLUMN:
3034 * - ENTER = PRIMAL
3035 * - LEAVE = DUAL
3036 *
3037 * If the representation is ROW:
3038 * - ENTER = DUAL
3039 * - LEAVE = PRIMAL
3040 */
3041 retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::ENTER) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::LEAVE);
3042 assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
3043 assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
3044
3045 return retcode;
3046}
3047
3048/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
3050 SCIP_LPI* lpi, /**< LP interface structure */
3051 SCIP_Bool crossover /**< perform crossover */
3052 )
3053{ /*lint --e{715}*/
3054 assert(lpi != NULL);
3055 assert(lpi->spx != NULL);
3056
3057 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
3058
3059 /* SoPlex does not support barrier (yet) */
3060 SCIPerrorMessage("SCIPlpiSolveBarrier() not supported by SoPlex\n");
3061 return SCIP_INVALIDCALL;
3062}
3063
3064/** start strong branching - call before any strongbranching */
3066 SCIP_LPI* lpi /**< LP interface structure */
3067 )
3068{
3069 assert(lpi != NULL);
3070 assert(lpi->spx != NULL);
3071
3072 assert( lpi->spx->preStrongbranchingBasisFreed() );
3073 lpi->spx->savePreStrongbranchingBasis();
3074
3075 return SCIP_OKAY;
3076}
3077
3078/** end strong branching - call after any strongbranching */
3080 SCIP_LPI* lpi /**< LP interface structure */
3081 )
3082{
3083 assert(lpi != NULL);
3084 assert(lpi->spx != NULL);
3085
3086 assert( ! lpi->spx->preStrongbranchingBasisFreed() );
3087 lpi->spx->restorePreStrongbranchingBasis();
3088 lpi->spx->freePreStrongbranchingBasis();
3089
3090 return SCIP_OKAY;
3091}
3092
3093/** performs strong branching iterations on one arbitrary candidate */
3094static
3096 SCIP_LPI* lpi, /**< LP interface structure */
3097 int col, /**< column to apply strong branching on */
3098 SCIP_Real psol, /**< current primal solution value of column */
3099 int itlim, /**< iteration limit for strong branchings */
3100 SCIP_Real* down, /**< stores dual bound after branching column down */
3101 SCIP_Real* up, /**< stores dual bound after branching column up */
3102 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3103 * otherwise, it can only be used as an estimate value */
3104 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3105 * otherwise, it can only be used as an estimate value */
3106 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3107 )
3108{
3109 SPxSCIP* spx;
3110 SPxSolver::Status status;
3111 SCIP_Real oldlb;
3112 SCIP_Real oldub;
3113 SCIP_Real newlb;
3114 SCIP_Real newub;
3115 bool fromparentbasis;
3116 bool error;
3117 int oldItlim;
3118
3119 SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
3120
3121 assert(lpi != NULL);
3122 assert(lpi->spx != NULL);
3123 /* assert(down != NULL);
3124 * assert(up != NULL); temporary hack for cloud branching */
3125 assert(downvalid != NULL);
3126 assert(upvalid != NULL);
3127
3128 spx = lpi->spx;
3129 status = SPxSolver::UNKNOWN;
3130 fromparentbasis = false;
3131 error = false;
3132 oldItlim = spx->getIterationLimit();
3133
3134 /* get current bounds of column */
3135 oldlb = spx->lower(col);
3136 oldub = spx->upper(col);
3137
3138 *downvalid = FALSE;
3139 *upvalid = FALSE;
3140
3141 if( iter != NULL )
3142 *iter = 0;
3143
3144 /* set the algorithm type to use dual simplex */
3145 lpi->spx->setType( lpi->spx->rep() == SPxSolver::ROW ? SPxSolver::ENTER : SPxSolver::LEAVE);
3146
3147 /* down branch */
3148 newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
3149 if( newub >= oldlb - 0.5 && down != NULL )
3150 {
3151 SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
3152
3153 spx->changeUpper(col, newub);
3154 assert(spx->lower(col) <= spx->upper(col));
3155
3156 spx->setIterationLimit(itlim);
3157 do
3158 {
3159#ifdef SCIP_WITH_LPSCHECK
3160 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3161#endif
3162 status = spx->solve();
3163 SCIPdebugMessage(" --> Terminate with status %d\n", status);
3164 switch( status )
3165 {
3166 case SPxSolver::OPTIMAL:
3167 *down = spx->value();
3168 *downvalid = TRUE;
3169 SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3170 break;
3171 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3172 case SPxSolver::ABORT_ITER:
3173 case SPxSolver::ABORT_CYCLING:
3174 *down = spx->value();
3175 break;
3176 case SPxSolver::ABORT_VALUE:
3177 case SPxSolver::INFEASIBLE:
3178 *down = spx->terminationValue();
3179 *downvalid = TRUE;
3180 break;
3181 default:
3182 error = true;
3183 break;
3184 } /*lint !e788*/
3185 if( iter != NULL )
3186 (*iter) += spx->iterations();
3187
3188#ifdef STRONGBRANCH_RESTOREBASIS
3189 /* we restore the pre-strong-branching basis by default (and don't solve again) */
3190 assert( ! spx->preStrongbranchingBasisFreed() );
3191 spx->restorePreStrongbranchingBasis();
3192 fromparentbasis = false;
3193#else
3194 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3195 * pre-strong-branching basis and try again with reduced iteration limit */
3196 if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3197 {
3198 SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n", itlim - spx->iterations());
3199 spx->setIterationLimit(itlim - spx->iterations());
3200 spx->restorePreStrongbranchingBasis();
3201 fromparentbasis = true;
3202 error = false;
3203 }
3204 /* otherwise don't solve again */
3205 else
3206 fromparentbasis = false;
3207#endif
3208 }
3209 while( fromparentbasis );
3210
3211 spx->changeUpper(col, oldub);
3212 assert(spx->lower(col) <= spx->upper(col));
3213 }
3214 else if( down != NULL )
3215 {
3216 *down = spx->terminationValue();
3217 *downvalid = TRUE;
3218 }
3219 else
3220 *downvalid = TRUE;
3221
3222 /* up branch */
3223 if( !error )
3224 {
3225 newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
3226 if( newlb <= oldub + 0.5 && up != NULL )
3227 {
3228 SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
3229
3230 spx->changeLower(col, newlb);
3231 assert(spx->lower(col) <= spx->upper(col));
3232
3233 spx->setIterationLimit(itlim);
3234 do
3235 {
3236#ifdef SCIP_WITH_LPSCHECK
3237 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3238#endif
3239 status = spx->solve();
3240 SCIPdebugMessage(" --> Terminate with status %d\n", status);
3241 switch( status )
3242 {
3243 case SPxSolver::OPTIMAL:
3244 *up = spx->value();
3245 *upvalid = TRUE;
3246 SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3247 break;
3248 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3249 case SPxSolver::ABORT_ITER:
3250 case SPxSolver::ABORT_CYCLING:
3251 *up = spx->value();
3252 break;
3253 case SPxSolver::ABORT_VALUE:
3254 case SPxSolver::INFEASIBLE:
3255 *up = spx->terminationValue();
3256 *upvalid = TRUE;
3257 break;
3258 default:
3259 error = true;
3260 break;
3261 } /*lint !e788*/
3262 if( iter != NULL )
3263 (*iter) += spx->iterations();
3264
3265#ifdef STRONGBRANCH_RESTOREBASIS
3266 /* we restore the pre-strong-branching basis by default (and don't solve again) */
3267 assert( ! spx->preStrongbranchingBasisFreed() );
3268 spx->restorePreStrongbranchingBasis();
3269 fromparentbasis = false;
3270#else
3271 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3272 * pre-strong-branching basis and try again with reduced iteration limit */
3273 if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3274 {
3275 SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->iterations());
3276 spx->restorePreStrongbranchingBasis();
3277 spx->setIterationLimit(itlim - spx->iterations());
3278 error = false;
3279 fromparentbasis = true;
3280 }
3281 /* otherwise don't solve again */
3282 else
3283 fromparentbasis = false;
3284#endif
3285 }
3286 while( fromparentbasis );
3287
3288 spx->changeLower(col, oldlb);
3289 assert(spx->lower(col) <= spx->upper(col));
3290 }
3291 else if( up != NULL )
3292 {
3293 *up = spx->terminationValue();
3294 *upvalid = TRUE;
3295 }
3296 else
3297 *upvalid = TRUE;
3298 }
3299
3300 /* reset old iteration limit */
3301 spx->setIterationLimit(oldItlim);
3302
3303 if( error )
3304 {
3305 SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status));
3306 return SCIP_LPERROR;
3307 }
3308
3309 return SCIP_OKAY;
3310}
3311
3312/** performs strong branching iterations on one @b fractional candidate */
3314 SCIP_LPI* lpi, /**< LP interface structure */
3315 int col, /**< column to apply strong branching on */
3316 SCIP_Real psol, /**< fractional current primal solution value of column */
3317 int itlim, /**< iteration limit for strong branchings */
3318 SCIP_Real* down, /**< stores dual bound after branching column down */
3319 SCIP_Real* up, /**< stores dual bound after branching column up */
3320 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3321 * otherwise, it can only be used as an estimate value */
3322 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3323 * otherwise, it can only be used as an estimate value */
3324 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3325 )
3326{
3327 SCIP_RETCODE retcode;
3328
3329 /* pass call on to lpiStrongbranch() */
3330 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3331
3332 /* pass SCIP_LPERROR to SCIP without a back trace */
3333 if( retcode == SCIP_LPERROR )
3334 return SCIP_LPERROR;
3335
3336 /* evaluate retcode */
3337 SCIP_CALL( retcode );
3338
3339 return SCIP_OKAY;
3340}
3341
3342/** performs strong branching iterations on given @b fractional candidates */
3344 SCIP_LPI* lpi, /**< LP interface structure */
3345 int* cols, /**< columns to apply strong branching on */
3346 int ncols, /**< number of columns */
3347 SCIP_Real* psols, /**< fractional current primal solution values of columns */
3348 int itlim, /**< iteration limit for strong branchings */
3349 SCIP_Real* down, /**< stores dual bounds after branching columns down */
3350 SCIP_Real* up, /**< stores dual bounds after branching columns up */
3351 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3352 * otherwise, they can only be used as an estimate values */
3353 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3354 * otherwise, they can only be used as an estimate values */
3355 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3356 )
3357{
3358 SCIP_RETCODE retcode;
3359
3360 assert( cols != NULL );
3361 assert( psols != NULL );
3362 assert( down != NULL );
3363 assert( up != NULL );
3364 assert( downvalid != NULL );
3365 assert( upvalid != NULL );
3366 assert( down != NULL );
3367
3368 if ( iter != NULL )
3369 *iter = 0;
3370
3371 for (int j = 0; j < ncols; ++j)
3372 {
3373 /* pass call on to lpiStrongbranch() */
3374 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3375
3376 /* pass SCIP_LPERROR to SCIP without a back trace */
3377 if( retcode == SCIP_LPERROR )
3378 return SCIP_LPERROR;
3379
3380 /* evaluate retcode */
3381 SCIP_CALL( retcode );
3382 }
3383 return SCIP_OKAY;
3384}
3385
3386/** performs strong branching iterations on one candidate with @b integral value */
3388 SCIP_LPI* lpi, /**< LP interface structure */
3389 int col, /**< column to apply strong branching on */
3390 SCIP_Real psol, /**< current integral primal solution value of column */
3391 int itlim, /**< iteration limit for strong branchings */
3392 SCIP_Real* down, /**< stores dual bound after branching column down */
3393 SCIP_Real* up, /**< stores dual bound after branching column up */
3394 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3395 * otherwise, it can only be used as an estimate value */
3396 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3397 * otherwise, it can only be used as an estimate value */
3398 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3399 )
3400{
3401 SCIP_RETCODE retcode;
3402
3403 /* pass call on to lpiStrongbranch() */
3404 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3405
3406 /* pass SCIP_LPERROR to SCIP without a back trace */
3407 if( retcode == SCIP_LPERROR )
3408 return SCIP_LPERROR;
3409
3410 /* evaluate retcode */
3411 SCIP_CALL( retcode );
3412
3413 return SCIP_OKAY;
3414}
3415
3416/** performs strong branching iterations on given candidates with @b integral values */
3418 SCIP_LPI* lpi, /**< LP interface structure */
3419 int* cols, /**< columns to apply strong branching on */
3420 int ncols, /**< number of columns */
3421 SCIP_Real* psols, /**< current integral primal solution values of columns */
3422 int itlim, /**< iteration limit for strong branchings */
3423 SCIP_Real* down, /**< stores dual bounds after branching columns down */
3424 SCIP_Real* up, /**< stores dual bounds after branching columns up */
3425 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3426 * otherwise, they can only be used as an estimate values */
3427 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3428 * otherwise, they can only be used as an estimate values */
3429 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3430 )
3431{
3432 SCIP_RETCODE retcode;
3433
3434 assert( cols != NULL );
3435 assert( psols != NULL );
3436 assert( down != NULL );
3437 assert( up != NULL );
3438 assert( downvalid != NULL );
3439 assert( upvalid != NULL );
3440 assert( down != NULL );
3441
3442 if ( iter != NULL )
3443 *iter = 0;
3444
3445 for (int j = 0; j < ncols; ++j)
3446 {
3447 /* pass call on to lpiStrongbranch() */
3448 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3449
3450 /* pass SCIP_LPERROR to SCIP without a back trace */
3451 if( retcode == SCIP_LPERROR )
3452 return SCIP_LPERROR;
3453
3454 /* evaluate retcode */
3455 SCIP_CALL( retcode );
3456 }
3457
3458 return SCIP_OKAY;
3459}
3460/**@} */
3461
3462
3463
3464
3465/*
3466 * Solution Information Methods
3467 */
3468
3469/**@name Solution Information Methods */
3470/**@{ */
3471
3472/** returns whether a solve method was called after the last modification of the LP */
3474 SCIP_LPI* lpi /**< LP interface structure */
3475 )
3476{
3477 assert(lpi != NULL);
3478
3479 return lpi->solved;
3480}
3481
3482/** gets information about primal and dual feasibility of the current LP solution
3483 *
3484 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
3485 * returns true. If the LP is changed, this information might be invalidated.
3486 *
3487 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
3488 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
3489 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
3490 * the problem might actually be feasible).
3491 */
3493 SCIP_LPI* lpi, /**< LP interface structure */
3494 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
3495 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
3496 )
3497{
3498 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
3499
3500 assert(lpi != NULL);
3501 assert(primalfeasible != NULL);
3502 assert(dualfeasible != NULL);
3503
3504 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
3505 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
3506
3507 return SCIP_OKAY;
3508}
3509
3510/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
3511 * this does not necessarily mean, that the solver knows and can return the primal ray
3512 */
3514 SCIP_LPI* lpi /**< LP interface structure */
3515 )
3516{
3517 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
3518
3519 assert(lpi != NULL);
3520 assert(lpi->spx != NULL);
3521
3522 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3523}
3524
3525/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
3526 * and the solver knows and can return the primal ray
3527 */
3529 SCIP_LPI* lpi /**< LP interface structure */
3530 )
3531{
3532 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
3533
3534 assert(lpi != NULL);
3535 assert(lpi->spx != NULL);
3536
3537#if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3538 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3539#else
3540 return FALSE;
3541#endif
3542}
3543
3544/** returns TRUE iff LP is proven to be primal unbounded */
3546 SCIP_LPI* lpi /**< LP interface structure */
3547 )
3548{
3549 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
3550
3551 assert(lpi != NULL);
3552 assert(lpi->spx != NULL);
3553
3554 assert(lpi->spx->getStatus() != SPxSolver::UNBOUNDED || lpi->spx->basis().status() == SPxBasis::UNBOUNDED);
3555
3556 /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
3557 * feasible point; hence we have to check the perturbation
3558 */
3559 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED && !lpi->spx->isPerturbed());
3560}
3561
3562/** returns TRUE iff LP is proven to be primal infeasible */
3564 SCIP_LPI* lpi /**< LP interface structure */
3565 )
3566{
3567 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3568
3569 assert(lpi != NULL);
3570 assert(lpi->spx != NULL);
3571
3572 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3573}
3574
3575/** returns TRUE iff LP is proven to be primal feasible */
3577 SCIP_LPI* lpi /**< LP interface structure */
3578 )
3579{
3580 SPxBasis::SPxStatus basestatus;
3581
3582 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3583
3584 assert(lpi != NULL);
3585 assert(lpi->spx != NULL);
3586
3587 basestatus = lpi->spx->basis().status();
3588
3589 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3590 * still return true as long as perturbation plus violation is within tolerances
3591 */
3592 assert(basestatus == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3593
3594 return basestatus == SPxBasis::OPTIMAL ||
3595 ((basestatus == SPxBasis::PRIMAL || basestatus == SPxBasis::UNBOUNDED) && !lpi->spx->isPerturbed());
3596}
3597
3598/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3599 * this does not necessarily mean, that the solver knows and can return the dual ray
3600 */
3602 SCIP_LPI* lpi /**< LP interface structure */
3603 )
3604{
3605 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3606
3607 assert(lpi != NULL);
3608 assert(lpi->spx != NULL);
3609
3610 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3611}
3612
3613/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3614 * and the solver knows and can return the dual ray
3615 */
3617 SCIP_LPI* lpi /**< LP interface structure */
3618 )
3619{
3620 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3621
3622 assert(lpi != NULL);
3623 assert(lpi->spx != NULL);
3624
3625 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3626}
3627
3628/** returns TRUE iff LP is dual unbounded */
3630 SCIP_LPI* lpi /**< LP interface structure */
3631 )
3632{
3633 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3634
3635 assert(lpi != NULL);
3636 assert(lpi->spx != NULL);
3637
3638 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE && lpi->spx->basis().status() == SPxBasis::DUAL
3639 && !lpi->spx->isPerturbed());
3640}
3641
3642/** returns TRUE iff LP is dual infeasible */
3644 SCIP_LPI* lpi /**< LP interface structure */
3645 )
3646{
3647 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3648
3649 assert(lpi != NULL);
3650 assert(lpi->spx != NULL);
3651
3652 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3653}
3654
3655/** returns TRUE iff LP is proven to be dual feasible */
3657 SCIP_LPI* lpi /**< LP interface structure */
3658 )
3659{
3660 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3661
3662 assert(lpi != NULL);
3663 assert(lpi->spx != NULL);
3664
3665 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3666 * still return true as long as perturbation plus violation is within tolerances
3667 */
3668 assert(lpi->spx->basis().status() == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3669
3670 return (lpi->spx->basis().status() == SPxBasis::OPTIMAL) ||
3671 (lpi->spx->basis().status() == SPxBasis::DUAL && !lpi->spx->isPerturbed());
3672}
3673
3674/** returns TRUE iff LP was solved to optimality */
3676 SCIP_LPI* lpi /**< LP interface structure */
3677 )
3678{
3679 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3680
3681 assert(lpi != NULL);
3682 assert(lpi->spx != NULL);
3683 assert((lpi->spx->basis().status() == SPxBasis::OPTIMAL)
3685
3686 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3687 * still return true as long as perturbation plus violation is within tolerances
3688 */
3689 return (lpi->spx->basis().status() == SPxBasis::OPTIMAL);
3690}
3691
3692/** returns TRUE iff current LP solution is stable
3693 *
3694 * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3695 * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3696 * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3697 * SCIPlpiIsStable() should return false.
3698 */
3700 SCIP_LPI* lpi /**< LP interface structure */
3701 )
3702{
3703 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3704
3705 assert(lpi != NULL);
3706 assert(lpi->spx != NULL);
3707
3708#if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3709 /* If the condition number of the basis should be checked, everything above the specified threshold is counted
3710 * as instable.
3711 */
3712 if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3713 {
3714#ifndef NDEBUG
3715 SCIP_RETCODE retcode;
3716#endif
3717 SCIP_Real kappa;
3718
3719#ifndef NDEBUG
3720 retcode =
3721#endif
3723 assert(kappa != SCIP_INVALID); /*lint !e777*/
3724 assert(retcode == SCIP_OKAY);
3725
3726 if( kappa > lpi->conditionlimit )
3727 return FALSE;
3728 }
3729#endif
3730
3731 return (lpi->spx->getStatus() != SPxSolver::ERROR && lpi->spx->getStatus() != SPxSolver::SINGULAR);
3732}
3733
3734/** returns TRUE iff the objective limit was reached */
3736 SCIP_LPI* lpi /**< LP interface structure */
3737 )
3738{
3739 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3740
3741 assert(lpi != NULL);
3742 assert(lpi->spx != NULL);
3743
3744 return (lpi->spx->getStatus() == SPxSolver::ABORT_VALUE);
3745}
3746
3747/** returns TRUE iff the iteration limit was reached */
3749 SCIP_LPI* lpi /**< LP interface structure */
3750 )
3751{
3752 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3753
3754 assert(lpi != NULL);
3755 assert(lpi->spx != NULL);
3756
3757 return (lpi->spx->getStatus() == SPxSolver::ABORT_ITER);
3758}
3759
3760/** returns TRUE iff the time limit was reached */
3762 SCIP_LPI* lpi /**< LP interface structure */
3763 )
3764{
3765 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3766
3767 assert(lpi != NULL);
3768 assert(lpi->spx != NULL);
3769
3770 return (lpi->spx->getStatus() == SPxSolver::ABORT_TIME);
3771}
3772
3773/** returns the internal solution status of the solver */
3775 SCIP_LPI* lpi /**< LP interface structure */
3776 )
3777{
3778 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3779
3780 assert(lpi != NULL);
3781 assert(lpi->spx != NULL);
3782
3783 return static_cast<int>(lpi->spx->getStatus());
3784}
3785
3786/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3788 SCIP_LPI* lpi, /**< LP interface structure */
3789 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3790 )
3791{ /*lint --e{715}*/
3792 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3793
3794 assert(lpi != NULL);
3795 assert(lpi->spx != NULL);
3796 assert(success != NULL);
3797
3798 /* instable situations cannot be ignored */
3799 *success = FALSE;
3800
3801 return SCIP_OKAY;
3802}
3803
3804/** gets objective value of solution */
3806 SCIP_LPI* lpi, /**< LP interface structure */
3807 SCIP_Real* objval /**< stores the objective value */
3808 )
3809{
3810 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3811
3812 assert(lpi != NULL);
3813 assert(lpi->spx != NULL);
3814 assert(objval != NULL);
3815
3816 *objval = lpi->spx->value();
3817
3818 return SCIP_OKAY;
3819}
3820
3821/** gets primal and dual solution vectors for feasible LPs
3822 *
3823 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3824 * SCIPlpiIsOptimal() returns true.
3825 */
3827 SCIP_LPI* lpi, /**< LP interface structure */
3828 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3829 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3830 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3831 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3832 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3833 )
3834{
3835 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3836
3837 assert(lpi != NULL);
3838 assert(lpi->spx != NULL);
3839
3840 if( objval != NULL )
3841 *objval = lpi->spx->value();
3842
3843 try
3844 {
3845 if( primsol != NULL )
3846 {
3847 Vector tmp(lpi->spx->nCols(), primsol);
3848 (void)lpi->spx->getPrimal(tmp);
3849 }
3850 if( dualsol != NULL )
3851 {
3852 Vector tmp(lpi->spx->nRows(), dualsol);
3853 (void)lpi->spx->getDual(tmp);
3854 }
3855 if( activity != NULL )
3856 {
3857 Vector tmp(lpi->spx->nRows(), activity);
3858 (void)lpi->spx->getSlacks(tmp); /* in SoPlex, the activities are called "slacks" */
3859 }
3860 if( redcost != NULL )
3861 {
3862 Vector tmp(lpi->spx->nCols(), redcost);
3863 (void)lpi->spx->getRedCost(tmp);
3864 }
3865 }
3866#ifndef NDEBUG
3867 catch( const SPxException& x )
3868 {
3869 std::string s = x.what();
3870 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3871#else
3872 catch( const SPxException& )
3873 {
3874#endif
3875 return SCIP_LPERROR;
3876 }
3877
3878 return SCIP_OKAY;
3879}
3880
3881/** gets primal ray for unbounded LPs */
3883 SCIP_LPI* lpi, /**< LP interface structure */
3884 SCIP_Real* ray /**< primal ray */
3885 )
3886{ /*lint --e{715}*/
3887 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3888
3889 assert(lpi != NULL);
3890 assert(lpi->spx != NULL);
3891 assert(ray != NULL);
3892
3893#if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3894 try
3895 {
3896 Vector tmp(lpi->spx->nCols(), ray);
3897 (void)lpi->spx->getPrimalray(tmp);
3898 }
3899#ifndef NDEBUG
3900 catch( const SPxException& x )
3901 {
3902 std::string s = x.what();
3903 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3904#else
3905 catch( const SPxException& )
3906 {
3907#endif
3908 return SCIP_LPERROR;
3909 }
3910
3911 return SCIP_OKAY;
3912#else
3913 SCIPerrorMessage("SCIPlpiGetPrimalRay() not supported by SoPlex versions <= 1.5.0\n");
3914 return SCIP_LPERROR;
3915#endif
3916}
3917
3918/** gets dual farkas proof for infeasibility */
3920 SCIP_LPI* lpi, /**< LP interface structure */
3921 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3922 )
3923{
3924 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3925
3926 assert(lpi != NULL);
3927 assert(lpi->spx != NULL);
3928 assert(dualfarkas != NULL);
3929
3930 try
3931 {
3932 Vector tmp(lpi->spx->nRows(), dualfarkas);
3933 (void)lpi->spx->getDualfarkas(tmp);
3934 }
3935#ifndef NDEBUG
3936 catch( const SPxException& x )
3937 {
3938 std::string s = x.what();
3939 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3940#else
3941 catch( const SPxException& )
3942 {
3943#endif
3944 return SCIP_LPERROR;
3945 }
3946
3947 return SCIP_OKAY;
3948}
3949
3950/** gets the number of LP iterations of the last solve call */
3952 SCIP_LPI* lpi, /**< LP interface structure */
3953 int* iterations /**< pointer to store the number of iterations of the last solve call */
3954 )
3955{
3956 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3957
3958 assert(lpi != NULL);
3959 assert(lpi->spx != NULL);
3960 assert(iterations != NULL);
3961
3962 *iterations = lpi->spx->iterations();
3963
3964 return SCIP_OKAY;
3965}
3966
3967/** gets information about the quality of an LP solution
3968 *
3969 * Such information is usually only available, if also a (maybe not optimal) solution is available.
3970 * The LPI should return SCIP_INVALID for @p quality, if the requested quality is not available.
3971 */
3973 SCIP_LPI* lpi, /**< LP interface structure */
3974 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3975 SCIP_Real* quality /**< pointer to store quality number */
3976 )
3977{
3978 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3979
3980 assert(lpi != NULL);
3981 assert(quality != NULL);
3982
3983#if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3984 int maxiter;
3985 Real tolerance;
3986
3987 SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3988
3989 switch( qualityindicator )
3990 {
3992 maxiter = 20;
3993 tolerance = 1e-6;
3994 break;
3995
3997 maxiter = 10000;
3998 tolerance = 1e-9;
3999 break;
4000
4001 default:
4002 SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
4003 return SCIP_INVALIDDATA;
4004 }
4005
4006 *quality = lpi->spx->basis().condition(maxiter, tolerance);
4007#else
4008 *quality = SCIP_INVALID;
4009#endif
4010 return SCIP_OKAY;
4011}
4012
4013/**@} */
4014
4015
4016
4017
4018/*
4019 * LP Basis Methods
4020 */
4021
4022/**@name LP Basis Methods */
4023/**@{ */
4024
4025/** Return reduced cost of column @c col if this is readily available, otherwise return 0.0 */
4026static
4027SCIP_RETCODE getRedCostEst(SPxSCIP* spx, int col, SCIP_Real* val)
4028{
4029 assert( spx != NULL );
4030 assert( val != NULL );
4031
4032 *val = 0.0;
4033
4034 /* Return if the vectors are not set up. The vectors are not set up if for instance we preformed
4035 * strong branching before. */
4036 if (! spx->isInitialized() )
4037 return SCIP_OKAY;
4038
4039 assert( 0 <= col && col < spx->nCols() );
4040
4041 if( spx->rep() == SPxSolver::COLUMN )
4042 {
4043 /* in column case the reduced costs are available: */
4044 if (spx->getSense() == SPxLP::MINIMIZE)
4045 *val = spx->pVec()[col] - spx->maxObj()[col];
4046 else
4047 *val = spx->maxObj()[col] - spx->pVec()[col];
4048 }
4049 else
4050 {
4051 assert( spx->rep() == SPxSolver::ROW );
4052
4053 /* In row case for computing the reduced costs one needs to pass through the basis. We skip this expensive part. */
4054#ifdef SCIP_DISABLED_CODE
4055 /* Here is the code necessary to compute the reduced costs for row representation: */
4056 SCIP_Real sign = 1.0;
4057 if ( spx->getSense() == SPxLP::MINIMIZE )
4058 sign = -1.0;
4059
4060 if ( spx->isColBasic(col) )
4061 {
4062 /* It seems necessary to search through the basis in order to find the correct position */
4063 for (int i = spx->dim() - 1; i >= 0; --i)
4064 {
4065 SPxId id = spx->basis().baseId(i);
4066 if ( id.isSPxColId() && col == spx->number(SPxColId(id)) )
4067 {
4068 *val = sign * spx->fVec()[i];
4069 break;
4070 }
4071 }
4072 }
4073#endif
4074 }
4075
4076 return SCIP_OKAY;
4077}
4078
4079
4080
4081/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
4083 SCIP_LPI* lpi, /**< LP interface structure */
4084 int* cstat, /**< array to store column basis status, or NULL */
4085 int* rstat /**< array to store row basis status, or NULL */
4086 )
4087{
4088 int i;
4089
4090 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
4091
4092 assert(lpi != NULL);
4093 assert(lpi->spx != NULL);
4094
4095 assert( lpi->spx->preStrongbranchingBasisFreed() );
4096
4097 if( rstat != NULL )
4098 {
4099 for( i = 0; i < lpi->spx->nRows(); ++i )
4100 {
4101 switch( lpi->spx->getBasisRowStatus(i) )
4102 {
4103 case SPxSolver::BASIC:
4104 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4105 break;
4106 case SPxSolver::FIXED:
4107 case SPxSolver::ON_LOWER:
4108 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4109 break;
4110 case SPxSolver::ON_UPPER:
4111 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4112 break;
4113 case SPxSolver::ZERO:
4114 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4115 return SCIP_LPERROR;
4116 case SPxSolver::UNDEFINED:
4117 default:
4118 SCIPerrorMessage("invalid basis status\n");
4119 SCIPABORT();
4120 return SCIP_INVALIDDATA; /*lint !e527*/
4121 }
4122 }
4123 }
4124
4125 if( cstat != NULL )
4126 {
4127 for( i = 0; i < lpi->spx->nCols(); ++i )
4128 {
4129 SCIP_Real val = 0.0;
4130 switch( lpi->spx->getBasisColStatus(i) )
4131 {
4132 case SPxSolver::BASIC:
4133 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4134 break;
4135 case SPxSolver::FIXED:
4136 /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
4137 * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
4138 * this case there is no problem at all. If the basis is saved and/or used in some other
4139 * solver, it usually is very cheap to perform the pivots necessary to get an optimal
4140 * basis. */
4141 SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
4142 if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
4143 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4144 else
4145 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4146 break;
4147 case SPxSolver::ON_LOWER:
4148 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4149 break;
4150 case SPxSolver::ON_UPPER:
4151 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4152 break;
4153 case SPxSolver::ZERO:
4154 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
4155 break;
4156 case SPxSolver::UNDEFINED:
4157 default:
4158 SCIPerrorMessage("invalid basis status\n");
4159 SCIPABORT();
4160 return SCIP_INVALIDDATA; /*lint !e527*/
4161 }
4162 }
4163 }
4164
4165 return SCIP_OKAY;
4166}
4167
4168/** sets current basis status for columns and rows */
4170 SCIP_LPI* lpi, /**< LP interface structure */
4171 const int* cstat, /**< array with column basis status */
4172 const int* rstat /**< array with row basis status */
4173 )
4174{
4175 int i;
4176 int ncols;
4177 int nrows;
4178
4179 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
4180
4181 assert(lpi != NULL);
4182 assert(lpi->spx != NULL);
4183
4184 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
4185 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
4186
4187 assert(cstat != NULL || ncols == 0);
4188 assert(rstat != NULL || nrows == 0);
4189
4190 assert( lpi->spx->preStrongbranchingBasisFreed() );
4191 invalidateSolution(lpi);
4192
4193 DataArray<SPxSolver::VarStatus>& m_colstat = lpi->spx->colStat();
4194 DataArray<SPxSolver::VarStatus>& m_rowstat = lpi->spx->rowStat();
4195
4196 m_colstat.reSize(ncols);
4197 m_rowstat.reSize(nrows);
4198
4199 for( i = 0; i < nrows; ++i )
4200 {
4201 assert( rstat != 0 ); /* for lint */
4202 switch( rstat[i] )
4203 {
4205 m_rowstat[i] = SPxSolver::ON_LOWER;
4206 break;
4208 m_rowstat[i] = SPxSolver::BASIC;
4209 break;
4211 m_rowstat[i] = SPxSolver::ON_UPPER;
4212 break;
4213 case SCIP_BASESTAT_ZERO:
4214 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4215 return SCIP_LPERROR; /*lint !e429*/
4216 default:
4217 SCIPerrorMessage("invalid basis status\n");
4218 SCIPABORT();
4219 return SCIP_INVALIDDATA; /*lint !e527*/
4220 }
4221 }
4222
4223 for( i = 0; i < ncols; ++i )
4224 {
4225 assert( cstat != 0 ); /* for lint */
4226 switch( cstat[i] )
4227 {
4229 m_colstat[i] = SPxSolver::ON_LOWER;
4230 break;
4232 m_colstat[i] = SPxSolver::BASIC;
4233 break;
4235 m_colstat[i] = SPxSolver::ON_UPPER;
4236 break;
4237 case SCIP_BASESTAT_ZERO:
4238 m_colstat[i] = SPxSolver::ZERO;
4239 break;
4240 default:
4241 SCIPerrorMessage("invalid basis status\n");
4242 SCIPABORT();
4243 return SCIP_INVALIDDATA; /*lint !e527*/
4244 }
4245 }
4246
4247 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(m_rowstat.get_const_ptr(), m_colstat.get_const_ptr()) );
4248 (void) lpi->spx->updateStatus();
4249
4250 lpi->spx->freePreStrongbranchingBasis();
4251
4252 return SCIP_OKAY;
4253}
4254
4255/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
4257 SCIP_LPI* lpi, /**< LP interface structure */
4258 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
4259 )
4260{
4261 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
4262
4263 SPxSolver* spx;
4264
4265 assert(lpi != NULL);
4266 assert(lpi->spx != NULL);
4267 assert(bind != NULL);
4268
4269 assert( lpi->spx->preStrongbranchingBasisFreed() );
4270
4271 /* the LPi defines the basis as column basis, i.e., as the set of (indices of) non-fixed columns and rows; if SoPlex
4272 * uses row representation, this is just the complement of the basis
4273 */
4274 spx = lpi->spx;
4275
4276 /* for column representation, return the basis */
4277 if( spx->rep() == SPxSolver::COLUMN )
4278 {
4279 for( int i = 0; i < spx->nRows(); ++i )
4280 {
4281 SPxId id = spx->basis().baseId(i);
4282
4283 bind[i] = (id.isSPxColId() ? spx->number(id) : - 1 - spx->number(id));
4284 }
4285 }
4286 /* for row representation, return the complement of the basis; for this, we need to loop through all rows and columns */
4287 else
4288 {
4289 int k = 0;
4290 int nrows = spx->nRows();
4291 int ncols = spx->nCols();
4292
4293 assert( spx->rep() == SPxSolver::ROW );
4294
4295 for( int i = 0; i < nrows; ++i )
4296 {
4297 if( !spx->isRowBasic(i) )
4298 {
4299 bind[k++] = -1 - i;
4300 if( k >= nrows )
4301 break;
4302 }
4303 }
4304
4305 for( int j = 0; j < ncols && k < nrows; ++j )
4306 {
4307 if( !spx->isColBasic(j) )
4308 bind[k++] = j;
4309 }
4310
4311 assert(k == nrows);
4312 }
4313
4314 return SCIP_OKAY;
4315}
4316
4317#ifdef OLD_BINV
4318/* prepare a factorization of the basis matrix in column representation */
4319static
4320SCIP_RETCODE prepareFactorization(
4321 SCIP_LPI* lpi
4322 )
4323{
4324 SCIPdebugMessage("Preparing factorization for computation of basis inverse.\n");
4325
4326 try
4327 {
4328 /* if the factorization has not been set up, we compute a new factorization */
4329 if ( lpi->factorization == 0 )
4330 {
4331 SPxSolver* spx = lpi->spx;
4332
4333 /* matrix to store columns */
4334 DataArray <const SVector*> matrix(spx->nRows());
4335
4336 int k = 0;
4337 for (int i = 0; i < spx->nRows(); ++i)
4338 {
4339 if ( ! spx->isRowBasic(i) )
4340 matrix[k++] = new UnitVector(i);
4341 }
4342 for (int j = 0; j < spx->nCols(); ++j)
4343 {
4344 if ( ! spx->isColBasic(j) )
4345 matrix[k++] = &spx->colVector(j);
4346 }
4347 assert( k == spx->nRows() );
4348 assert( k == matrix.size() );
4349
4350 /* compute factorization */
4351 lpi->factorization = new SLUFactor;
4352#ifndef NDEBUG
4353 SLinSolver::Status status = lpi->factorization->load(matrix.get_ptr(), k);
4354#else
4355 (void) lpi->factorization->load(matrix.get_ptr(), k);
4356#endif
4357 assert( status == SLinSolver::OK );
4358 assert( k == lpi->factorization->dim() );
4359
4360 /* delete matrix columns corresponding to unit vectors */
4361 k = 0;
4362 for (int i = 0; i < spx->nRows(); ++i)
4363 {
4364 if ( ! spx->isRowBasic(i) )
4365 delete matrix[k++];
4366 }
4367 }
4368 }
4369#ifndef NDEBUG
4370 catch( const SPxException& x )
4371 {
4372 std::string s = x.what();
4373 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4374#else
4375 catch( const SPxException& )
4376 {
4377#endif
4378 return SCIP_LPERROR;
4379 }
4380
4381 return SCIP_OKAY;
4382}
4383#endif
4384
4385/** get row of inverse basis matrix B^-1
4386 *
4387 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4388 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4389 * see also the explanation in lpi.h.
4390 */
4392 SCIP_LPI* lpi, /**< LP interface structure */
4393 int r, /**< row number */
4394 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
4395 int* inds, /**< array to store the non-zero indices, or NULL */
4396 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4397 * (-1: if we do not store sparsity information) */
4398 )
4399{
4400 SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
4401
4402 assert( lpi != NULL );
4403 assert( lpi->spx != NULL );
4404 assert( lpi->spx->preStrongbranchingBasisFreed() );
4405 assert(coef != NULL);
4406
4407 int nCols = lpi->spx->nCols();
4408 int nRows = lpi->spx->nRows();
4409
4410 assert(r >= 0);
4411 assert(r < nRows);
4412
4413 try
4414 {
4415 SPxSolver* spx = lpi->spx;
4416
4417 /* in the column case use the existing factorization */
4418 if ( spx->rep() == SPxSolver::COLUMN )
4419 {
4420 SSVector x(nRows);
4421 spx->basis().coSolve(x, spx->unitVector(r));
4422
4423 /* copy sparse data to dense result vector based on coef array */
4424 if( ninds != NULL && inds != NULL )
4425 {
4426 int idx;
4427 /* during solving SoPlex may have destroyed the sparsity structure so we need to restore it */
4428 x.setup();
4429 *ninds = x.size();
4430 for( int i = 0; i < *ninds; ++i )
4431 {
4432 idx = x.index(i);
4433 coef[idx] = x[idx];
4434 /* set sparsity pattern of coef array */
4435 inds[i] = idx;
4436 }
4437 }
4438 else
4439 {
4440 /* @todo check whether we only need to copy nonzeros to coef - is coef cleared? */
4441 Vector y(nRows, coef);
4442 y = x;
4443 if( ninds != NULL )
4444 *ninds = -1;
4445 }
4446 }
4447 else
4448 {
4449 assert(spx->rep() == SPxSolver::ROW);
4450
4451#ifdef OLD_BINV
4452 DVector e(nRows);
4453
4454 /* prepare unit vector */
4455 e.clear();
4456 e[r] = 1.0;
4457
4458 /* factorization is deleted in invalidateSolution() */
4459 SCIP_CALL( prepareFactorization(lpi) );
4460 assert( lpi->factorization != 0 );
4461 assert( lpi->factorization->dim() == nRows );
4462
4463 /* solve system "x = e_r^T * B^-1" to get r'th row of B^-1 */
4464 lpi->factorization->solveLeft(x, e);
4465#else
4466 Vector x(nRows, coef); /* row of B^-1 has nrows entries - note that x is based on coef */
4467 /**@todo should rhs be a reference? */
4468 DSVector rhs(nCols);
4469 SSVector y(nCols);
4470 int* bind;
4471 int idx;
4472
4473 bind = NULL;
4474
4475 /**@todo should bind be stored globally in lpi? */
4476 /* get ordering of column basis matrix */
4477 SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4478 SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4479
4480 /* get vector corresponding to requested index r */
4481 idx = bind[r];
4482
4483 /* r corresponds to a row vector */
4484 if( idx < 0 )
4485 {
4486 idx = -idx-1;
4487
4488 /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4489 assert(idx >= 0);
4490 assert(idx < nRows);
4491 assert(!spx->isRowBasic(idx));
4492
4493 /* get row vector */
4494 rhs = spx->rowVector(idx);
4495 rhs *= -1.0;
4496 }
4497 /* r corresponds to a column vector */
4498 else
4499 {
4500 /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4501 assert(idx < nCols);
4502 assert(!spx->isColBasic(idx));
4503
4504 /* get unit vector */
4505 rhs = spx->unitVector(idx);
4506 }
4507
4508 /* solve system "y B = rhs", where B is the row basis matrix */
4509 spx->basis().solve(y, rhs);
4510
4511 /* initialize result vector x as zero */
4512 BMSclearMemoryArray(coef, nRows);
4513
4514 /* add nonzero entries */
4515 for( int i = 0; i < nCols; ++i )
4516 {
4517 SPxId id = spx->basis().baseId(i);
4518
4519 if( id.isSPxRowId() )
4520 {
4521 assert(spx->number(id) >= 0);
4522 assert(spx->number(id) < nRows);
4523 assert(bind[r] >= 0 || spx->number(id) != idx);
4524
4525 x[spx->number(id)] = y[i];
4526 }
4527 }
4528
4529 /* if r corresponds to a row vector, we have to add a 1 at position r */
4530 if( bind[r] < 0 )
4531 {
4532 assert(x[idx] == 0.0);
4533 x[idx] = 1.0;
4534 }
4535
4536 /* @todo implement returning of sparsity information like in column wise case */
4537 if( ninds != NULL )
4538 *ninds = -1;
4539
4540 /* free memory */
4541 BMSfreeMemoryArray(&bind);
4542#endif
4543 }
4544 }
4545#ifndef NDEBUG
4546 catch( const SPxException& x )
4547 {
4548 std::string s = x.what();
4549 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4550#else
4551 catch( const SPxException& )
4552 {
4553#endif
4554 return SCIP_LPERROR;
4555 }
4556
4557 return SCIP_OKAY;
4558}
4559
4560/** get solution of basis matrix B * coef = rhs */
4561static
4563 SCIP_LPI* lpi, /**< LP interface structure */
4564 SCIP_Real* rhs, /**< right-hand side vector */
4565 SCIP_Real* coef /**< vector to return coefficients */
4566 )
4567{
4568 SCIPdebugMessage("calling SCIPlpiGetBInvVec()\n");
4569
4570 assert(lpi != NULL);
4571 assert(lpi->spx != NULL);
4572 assert(lpi->spx->preStrongbranchingBasisFreed());
4573 assert(rhs != NULL);
4574 assert(coef != NULL);
4575
4576 int nCols = lpi->spx->nCols();
4577 int nRows = lpi->spx->nRows();
4578
4579 try
4580 {
4581 SPxSolver* spx = lpi->spx;
4582 Vector v(nRows, rhs);
4583 Vector x(nRows, coef);
4584
4585 /* in the column case use the existing factorization */
4586 if( spx->rep() == SPxSolver::COLUMN )
4587 {
4588 /* solve system "x = B^-1 * A_c" to get c'th column of B^-1 * A */
4589 spx->basis().solve(x, v);
4590 }
4591 else
4592 {
4593 assert(spx->rep() == SPxSolver::ROW);
4594
4595#ifdef OLD_BINV
4596 /* factorization is deleted in invalidateSolution() */
4597 SCIP_CALL( prepareFactorization(lpi) );
4598 assert(lpi->factorization != 0);
4599 assert(lpi->factorization->dim() == spx->nRows());
4600
4601 /* solve system B * x = v */
4602 lpi->factorization->solveRight(x, v);
4603#else
4604 DSVector rowrhs(nCols);
4605 SSVector y(nCols);
4606 int* bind;
4607
4608 bind = NULL;
4609
4610 /**@todo should bind be stored globally in lpi? */
4611 /* get ordering of column basis matrix */
4612 SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4613 SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4614
4615 /* fill right-hand side for row-based system */
4616 for( int i = 0; i < nCols; ++i )
4617 {
4618 SPxId id = spx->basis().baseId(i);
4619
4620 if( id.isSPxRowId() )
4621 {
4622 assert(spx->number(id) >= 0);
4623 assert(spx->number(id) < nRows);
4624
4625 rowrhs.add(i, v[spx->number(id)]);
4626 }
4627 else
4628 {
4629 assert(rowrhs[i] == 0.0);
4630 }
4631 }
4632
4633 /* solve system "B y = rowrhs", where B is the row basis matrix */
4634 spx->basis().coSolve(y, rowrhs);
4635
4636 /* fill result w.r.t. order given by bind */
4637 for( int i = 0; i < nRows; ++i )
4638 {
4639 int idx;
4640
4641 idx = bind[i];
4642
4643 if( idx < 0 )
4644 {
4645 idx = -idx-1;
4646
4647 /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4648 assert(idx >= 0);
4649 assert(idx < nRows);
4650 assert(!spx->isRowBasic(idx));
4651
4652 x[i] = v[idx] - (spx->rowVector(idx) * Vector(nCols, y.get_ptr())); /*lint !e1702*/
4653 }
4654 else
4655 {
4656 /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4657 assert(idx >= 0);
4658 assert(idx < nCols);
4659 assert(!spx->isColBasic(idx));
4660
4661 x[i] = y[idx];
4662 }
4663 }
4664
4665 /* free memory */
4666 BMSfreeMemoryArray(&bind);
4667#endif
4668 }
4669 }
4670#ifndef NDEBUG
4671 catch( const SPxException& x )
4672 {
4673 std::string s = x.what();
4674 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4675#else
4676 catch( const SPxException& )
4677 {
4678#endif
4679 return SCIP_LPERROR;
4680 }
4681
4682 return SCIP_OKAY;
4683}
4684
4685/** get column of inverse basis matrix B^-1
4686 *
4687 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4688 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4689 * see also the explanation in lpi.h.
4690 */
4692 SCIP_LPI* lpi, /**< LP interface structure */
4693 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
4694 * you have to call SCIPlpiGetBasisInd() to get the array which links the
4695 * B^-1 column numbers to the row and column numbers of the LP!
4696 * c must be between 0 and nrows-1, since the basis has the size
4697 * nrows * nrows */
4698 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
4699 int* inds, /**< array to store the non-zero indices, or NULL */
4700 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4701 * (-1: if we do not store sparsity information) */
4702 )
4703{ /*lint --e{715}*/
4704 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
4705
4706 assert( lpi != NULL );
4707 assert( lpi->spx != NULL );
4708 assert( lpi->spx->preStrongbranchingBasisFreed() );
4709 assert(coef != NULL);
4710
4711 /* mark sparsity pattern as invalid */
4712 if( ninds != NULL )
4713 *ninds = -1;
4714
4715 /* prepare unit vector */
4716 DVector e(lpi->spx->nRows());
4717
4718 e.clear();
4719
4720 assert(c >= 0);
4721 assert(c < lpi->spx->nRows());
4722 e[c] = 1.0;
4723
4724 /* solve */
4725 SCIP_CALL( lpiGetBInvVec(lpi, e.get_ptr(), coef) );
4726
4727 return SCIP_OKAY;
4728}
4729
4730/** get row of inverse basis matrix times constraint matrix B^-1 * A
4731 *
4732 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4733 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4734 * see also the explanation in lpi.h.
4735 */
4737 SCIP_LPI* lpi, /**< LP interface structure */
4738 int r, /**< row number */
4739 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
4740 SCIP_Real* coef, /**< vector to return coefficients of the row */
4741 int* inds, /**< array to store the non-zero indices, or NULL */
4742 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4743 * (-1: if we do not store sparsity information) */
4744 )
4745{
4746 SCIP_Real* buf;
4747 SCIP_Real* binv;
4748 int nrows;
4749 int ncols;
4750 int c;
4751
4752 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
4753
4754 assert(lpi != NULL);
4755 assert(lpi->spx != NULL);
4756 assert( lpi->spx->preStrongbranchingBasisFreed() );
4757 assert(coef != NULL);
4758
4759 nrows = lpi->spx->nRows();
4760 ncols = lpi->spx->nCols();
4761 buf = NULL;
4762
4763 /* get (or calculate) the row in B^-1 */
4764 if( binvrow == NULL )
4765 {
4766 SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
4767 SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
4768 binv = buf;
4769 }
4770 else
4771 binv = const_cast<SCIP_Real*>(binvrow);
4772
4773 assert(binv != NULL);
4774
4775 /* mark sparsity pattern as invalid */
4776 if( ninds != NULL )
4777 *ninds = -1;
4778
4779 /* calculate the scalar product of the row in B^-1 and A */
4780 soplex::Vector binvvec(nrows, binv);
4781 for( c = 0; c < ncols; ++c )
4782 coef[c] = binvvec * lpi->spx->colVector(c); /* scalar product */ /*lint !e1702*/
4783
4784 /* free memory if it was temporarily allocated */
4786
4787 return SCIP_OKAY;
4788}
4789
4790/** get column of inverse basis matrix times constraint matrix B^-1 * A
4791 *
4792 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4793 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4794 * see also the explanation in lpi.h.
4795 */
4797 SCIP_LPI* lpi, /**< LP interface structure */
4798 int c, /**< column number */
4799 SCIP_Real* coef, /**< vector to return coefficients of the column */
4800 int* inds, /**< array to store the non-zero indices, or NULL */
4801 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4802 * (-1: if we do not store sparsity information) */
4803 )
4804{ /*lint --e{715}*/
4805 DVector col(lpi->spx->nRows());
4806
4807 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
4808
4809 assert( lpi != NULL );
4810 assert( lpi->spx != NULL );
4811 assert( lpi->spx->preStrongbranchingBasisFreed() );
4812 assert(coef != NULL);
4813
4814 /* extract column c of A */
4815 assert(c >= 0);
4816 assert(c < lpi->spx->nCols());
4817
4818 /* mark sparsity pattern as invalid */
4819 if( ninds != NULL )
4820 *ninds = -1;
4821
4822 col.clear();
4823 col = lpi->spx->colVector(c);
4824 col.reDim(lpi->spx->nRows());
4825
4826 /* solve */
4827 SCIP_CALL( lpiGetBInvVec(lpi, col.get_ptr(), coef) );
4828
4829 return SCIP_OKAY;
4830}
4831
4832/**@} */
4833
4834
4835
4836
4837/*
4838 * LP State Methods
4839 */
4840
4841/**@name LP State Methods */
4842/**@{ */
4843
4844/** stores LPi state (like basis information) into lpistate object */
4846 SCIP_LPI* lpi, /**< LP interface structure */
4847 BMS_BLKMEM* blkmem, /**< block memory */
4848 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4849 )
4850{
4851 int ncols;
4852 int nrows;
4853
4854 SCIPdebugMessage("calling SCIPlpiGetState()\n");
4855
4856 assert(blkmem != NULL);
4857 assert(lpi != NULL);
4858 assert(lpi->spx != NULL);
4859 assert(lpistate != NULL);
4860
4861 assert( lpi->spx->preStrongbranchingBasisFreed() );
4862
4863 ncols = lpi->spx->nCols();
4864 nrows = lpi->spx->nRows();
4865 assert(ncols >= 0);
4866 assert(nrows >= 0);
4867
4868 /* allocate lpistate data */
4869 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
4870
4871 /* allocate enough memory for storing uncompressed basis information */
4872 SCIP_CALL( ensureCstatMem(lpi, ncols) );
4873 SCIP_CALL( ensureRstatMem(lpi, nrows) );
4874
4875 /* get unpacked basis information */
4876 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
4877
4878 /* pack LPi state data */
4879 (*lpistate)->ncols = ncols;
4880 (*lpistate)->nrows = nrows;
4881 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
4882
4883 return SCIP_OKAY;
4884}
4885
4886/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
4887 * columns and rows since the state was stored with SCIPlpiGetState()
4888 */
4890 SCIP_LPI* lpi, /**< LP interface structure */
4891 BMS_BLKMEM* /*blkmem*/, /**< block memory */
4892 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
4893 )
4894{
4895 int lpncols;
4896 int lpnrows;
4897 int i;
4898
4899 SCIPdebugMessage("calling SCIPlpiSetState()\n");
4900
4901 assert(lpi != NULL);
4902 assert(lpi->spx != NULL);
4903 assert(lpistate != NULL);
4904 /* assert(blkmem != NULL); */
4905
4906 assert( lpi->spx->preStrongbranchingBasisFreed() );
4907
4908 lpncols = lpi->spx->nCols();
4909 lpnrows = lpi->spx->nRows();
4910 assert(lpistate->ncols <= lpncols);
4911 assert(lpistate->nrows <= lpnrows);
4912
4913 /* allocate enough memory for storing uncompressed basis information */
4914 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
4915 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
4916
4917 /* unpack LPi state data */
4918 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
4919
4920 /* extend the basis to the current LP beyond the previously existing columns */
4921 for( i = lpistate->ncols; i < lpncols; ++i )
4922 {
4923 SCIP_Real bnd = lpi->spx->lower(i);
4924 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4925 {
4926 /* if lower bound is +/- infinity -> try upper bound */
4927 bnd = lpi->spx->lower(i);
4928 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4929 lpi->cstat[i] = (int) SCIP_BASESTAT_ZERO; /* variable is free */
4930 else
4931 lpi->cstat[i] = (int) SCIP_BASESTAT_UPPER; /* use finite upper bound */
4932 }
4933 else
4934 lpi->cstat[i] = (int) SCIP_BASESTAT_LOWER; /* use finite lower bound */
4935 }
4936 for( i = lpistate->nrows; i < lpnrows; ++i )
4937 lpi->rstat[i] = (int) SCIP_BASESTAT_BASIC; /*lint !e641*/
4938
4939 /* load basis information */
4940 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4941
4942 return SCIP_OKAY;
4943}
4944
4945/** clears current LPi state (like basis information) of the solver */
4947 SCIP_LPI* lpi /**< LP interface structure */
4948 )
4949{ /*lint --e{715}*/
4950 SCIPdebugMessage("calling SCIPlpiClearState()\n");
4951
4952 assert(lpi != NULL);
4953 assert(lpi->spx != NULL);
4954
4955 try
4956 {
4957 lpi->spx->reLoad();
4958 }
4959#ifndef NDEBUG
4960 catch( const SPxException& x )
4961 {
4962 std::string s = x.what();
4963 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4964#else
4965 catch( const SPxException& )
4966 {
4967#endif
4968 assert( lpi->spx->getStatus() != SPxSolver::OPTIMAL );
4969 return SCIP_LPERROR;
4970 }
4971
4972 return SCIP_OKAY;
4973}
4974
4975/** frees LPi state information */
4977 SCIP_LPI* lpi, /**< LP interface structure */
4978 BMS_BLKMEM* blkmem, /**< block memory */
4979 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4980 )
4981{ /*lint --e{715}*/
4982 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4983
4984 assert(lpi != NULL);
4985 assert(lpistate != NULL);
4986 assert(blkmem != NULL);
4987
4988 if ( *lpistate != NULL )
4989 lpistateFree(lpistate, blkmem);
4990
4991 return SCIP_OKAY;
4992}
4993
4994/** checks, whether the given LP state contains simplex basis information */
4996 SCIP_LPI* lpi, /**< LP interface structure */
4997 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4998 )
4999{ /*lint --e{715}*/
5000 assert(lpi != NULL);
5001 return TRUE;
5002}
5003
5004/** reads LP state (like basis information from a file */
5006 SCIP_LPI* lpi, /**< LP interface structure */
5007 const char* fname /**< file name */
5008 )
5009{
5010 SCIPdebugMessage("calling SCIPlpiReadState()\n");
5011 assert(lpi != NULL);
5012 assert(lpi->spx != NULL);
5013 assert(fname != NULL);
5014
5015 assert( lpi->spx->preStrongbranchingBasisFreed() );
5016
5017 bool success;
5018 SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
5019
5020 return success ? SCIP_OKAY : SCIP_LPERROR;
5021}
5022
5023/** writes LPi state (i.e. basis information) to a file */
5025 SCIP_LPI* lpi, /**< LP interface structure */
5026 const char* fname /**< file name */
5027 )
5028{
5029 assert(lpi != NULL);
5030 assert(lpi->spx != NULL);
5031 assert(fname != NULL);
5032 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
5033
5034 assert( lpi->spx->preStrongbranchingBasisFreed() );
5035
5036 bool res;
5037 SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
5038
5039 if ( ! res )
5040 return SCIP_LPERROR;
5041
5042 return SCIP_OKAY;
5043}
5044
5045/**@} */
5046
5047
5048
5049
5050/*
5051 * LP Pricing Norms Methods
5052 */
5053
5054/**@name LP Pricing Norms Methods */
5055/**@{ */
5056
5057/** stores LPi pricing norms information
5058 * @todo should we store norm information?
5059 */
5061 SCIP_LPI* lpi, /**< LP interface structure */
5062 BMS_BLKMEM* blkmem, /**< block memory */
5063 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
5064 )
5065{
5066#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5067 int nrows;
5068 int ncols;
5069
5070 assert(blkmem != NULL);
5071 assert(lpi != NULL);
5072 assert(lpi->spx != NULL);
5073 assert(lpinorms != NULL);
5074
5075 lpi->spx->getNdualNorms(nrows, ncols);
5076
5077 if( nrows == 0 && ncols == 0)
5078 {
5079 (*lpinorms = NULL);
5080 return SCIP_OKAY;
5081 }
5082
5083 /* allocate lpinorms data */
5084 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
5085 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
5086 (*lpinorms)->nrows = 0;
5087 (*lpinorms)->ncols = 0;
5088
5089 SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
5090
5091 if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
5092 {
5093 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5094 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
5095 BMSfreeBlockMemory(blkmem, lpinorms);
5096 assert(*lpinorms == NULL);
5097 }
5098#ifndef NDEBUG
5099 else
5100 {
5101 assert(nrows == (*lpinorms)->nrows);
5102 assert(ncols == (*lpinorms)->ncols);
5103 }
5104#endif
5105#else
5106 (*lpinorms) = NULL;
5107#endif
5108
5109 return SCIP_OKAY;
5110}
5111
5112/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
5113 * columns and rows since the state was stored with SCIPlpiGetNorms()
5114 */
5116 SCIP_LPI* lpi, /**< LP interface structure */
5117 BMS_BLKMEM* blkmem, /**< block memory */
5118 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
5119 )
5120{
5121#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5122 assert(blkmem != NULL);
5123 assert(lpi != NULL);
5124 assert(lpi->spx != NULL);
5125
5126 /* if there was no pricing norms information available, the LPi norms were not stored */
5127 if( lpinorms == NULL )
5128 return SCIP_OKAY;
5129
5130 assert(lpinorms->nrows <= lpi->spx->nRows());
5131 assert(lpinorms->ncols <= lpi->spx->nCols());
5132
5133 if( lpinorms->nrows == 0 )
5134 return SCIP_OKAY;
5135
5136 SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
5137 (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->nRows(), lpi->spx->nCols());
5138
5139 if( !lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms) )
5140 SCIPdebugMessage("loading of LPi norms failed\n");
5141#endif
5142
5143 return SCIP_OKAY;
5144}
5145
5146/** frees pricing norms information */
5148 SCIP_LPI* lpi, /**< LP interface structure */
5149 BMS_BLKMEM* blkmem, /**< block memory */
5150 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
5151 )
5152{
5153#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5154 assert(lpi != NULL);
5155 assert(lpinorms != NULL);
5156
5157 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5158
5159 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
5160 BMSfreeBlockMemory(blkmem, lpinorms);
5161 assert(*lpinorms == NULL);
5162#endif
5163
5164 return SCIP_OKAY;
5165}
5166
5167/**@} */
5168
5169
5170
5171
5172/*
5173 * Parameter Methods
5174 */
5175
5176/**@name Parameter Methods */
5177/**@{ */
5178
5179/** gets integer parameter of LP */
5181 SCIP_LPI* lpi, /**< LP interface structure */
5182 SCIP_LPPARAM type, /**< parameter number */
5183 int* ival /**< buffer to store the parameter value */
5184 )
5185{
5186 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
5187
5188 assert(lpi != NULL);
5189 assert(lpi->spx != NULL);
5190 assert(ival != NULL);
5191
5192 switch( type )
5193 {
5195 *ival = lpi->spx->getFromScratch();
5196 break;
5197 case SCIP_LPPAR_LPINFO:
5198 *ival = lpi->spx->getLpInfo();
5199 break;
5200 case SCIP_LPPAR_LPITLIM:
5201 *ival = lpi->spx->getIterationLimit();
5202 if( *ival == -1 )
5203 *ival = INT_MAX;
5204 break;
5206 *ival = lpi->spx->getPresolving();
5207 break;
5208 case SCIP_LPPAR_PRICING:
5209 *ival = (int)lpi->pricing;
5210 break;
5211 case SCIP_LPPAR_SCALING:
5212 *ival = lpi->spx->getScaling();
5213 break;
5214#if SOPLEX_VERSION >= 201
5215 case SCIP_LPPAR_TIMING:
5216 *ival = (int) lpi->spx->getTiming();
5217 break;
5218#endif
5219#if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
5221 *ival = (int) lpi->spx->random.getSeed();
5222 break;
5223#endif
5224 default:
5225 return SCIP_PARAMETERUNKNOWN;
5226 } /*lint !e788*/
5227
5228 return SCIP_OKAY;
5229}
5230
5231/** sets integer parameter of LP */
5233 SCIP_LPI* lpi, /**< LP interface structure */
5234 SCIP_LPPARAM type, /**< parameter number */
5235 int ival /**< parameter value */
5236 )
5237{
5238 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
5239
5240 assert(lpi != NULL);
5241 assert(lpi->spx != NULL);
5242
5243 switch( type )
5244 {
5246 assert(ival == TRUE || ival == FALSE);
5247 lpi->spx->setFromScratch(bool(ival));
5248 break;
5249 case SCIP_LPPAR_LPINFO:
5250 assert(ival == TRUE || ival == FALSE);
5251 lpi->spx->setLpInfo(bool(ival));
5252 break;
5253 case SCIP_LPPAR_LPITLIM:
5254 assert( ival >= 0 );
5255 /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
5256 if( ival >= INT_MAX )
5257 ival = -1;
5258 lpi->spx->setIterationLimit(ival);
5259 break;
5261 assert(ival == TRUE || ival == FALSE);
5262 lpi->spx->setPresolving(bool(ival));
5263 break;
5264 case SCIP_LPPAR_PRICING:
5265 lpi->pricing = (SCIP_PRICING)ival;
5266 switch( lpi->pricing )
5267 {
5269 case SCIP_PRICING_AUTO:
5270 lpi->spx->setAutoPricer();
5271 break;
5272 case SCIP_PRICING_FULL:
5273 lpi->spx->setFullPricer();
5274 break;
5276 lpi->spx->setParmultPricer();
5277 break;
5278 case SCIP_PRICING_STEEP:
5279 lpi->spx->setSteepPricer();
5280 break;
5282 lpi->spx->setSteepQStartPricer();
5283 break;
5284 case SCIP_PRICING_DEVEX:
5285 lpi->spx->setDevexPricer();
5286 break;
5287 default:
5288 return SCIP_LPERROR;
5289 }
5290 break;
5291 case SCIP_LPPAR_SCALING:
5292 assert(ival == TRUE || ival == FALSE);
5293 lpi->spx->setScaling(ival);
5294 break;
5295#if SOPLEX_VERSION >= 201
5296 case SCIP_LPPAR_TIMING:
5297 assert(ival >= 0 && ival < 3);
5298 lpi->spx->setTiming((Timer::TYPE) ival);
5299 break;
5300#endif
5301#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 2)
5303 lpi->spx->random.setSeed((unsigned int) ival);
5304 break;
5305#endif
5306#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
5308 assert(ival >= 0 && ival < 3);
5309 lpi->spx->setSolutionPolishing((SPxSolver::SolutionPolish) ival);
5310 break;
5311#endif
5312
5313 default:
5314 return SCIP_PARAMETERUNKNOWN;
5315 } /*lint !e788*/
5316
5317 return SCIP_OKAY;
5318}
5319
5320/** gets floating point parameter of LP */
5322 SCIP_LPI* lpi, /**< LP interface structure */
5323 SCIP_LPPARAM type, /**< parameter number */
5324 SCIP_Real* dval /**< buffer to store the parameter value */
5325 )
5326{
5327 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
5328
5329 assert(lpi != NULL);
5330 assert(lpi->spx != NULL);
5331 assert(dval != NULL);
5332
5333 switch( type )
5334 {
5335 case SCIP_LPPAR_FEASTOL:
5336 *dval = lpi->spx->feastol();
5337 break;
5338#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5340 *dval = lpi->spx->opttol();
5341 break;
5342#endif
5343 case SCIP_LPPAR_OBJLIM:
5344 if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5345 *dval = lpi->spx->getObjUpLimit();
5346 else
5347 *dval = lpi->spx->getObjLoLimit();
5348 break;
5349 case SCIP_LPPAR_LPTILIM:
5350 *dval = lpi->spx->terminationTime();
5351 break;
5353 *dval = lpi->rowrepswitch;
5354 break;
5356 *dval = lpi->conditionlimit;
5357 break;
5358 default:
5359 return SCIP_PARAMETERUNKNOWN;
5360 } /*lint !e788*/
5361
5362 return SCIP_OKAY;
5363}
5364
5365/** sets floating point parameter of LP */
5367 SCIP_LPI* lpi, /**< LP interface structure */
5368 SCIP_LPPARAM type, /**< parameter number */
5369 SCIP_Real dval /**< parameter value */
5370 )
5371{
5372 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
5373
5374 assert(lpi != NULL);
5375 assert(lpi->spx != NULL);
5376
5377 switch( type )
5378 {
5379 case SCIP_LPPAR_FEASTOL:
5380 /* 0 < dval */
5381 assert( dval > 0.0 );
5382 lpi->spx->setFeastol(dval);
5383 break;
5384#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5386 /* 0 < dval */
5387 assert( dval > 0.0 );
5388 lpi->spx->setOpttol(dval);
5389 break;
5390#endif
5391 case SCIP_LPPAR_OBJLIM:
5392 if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5393 lpi->spx->setObjUpLimit(dval);
5394 else
5395 lpi->spx->setObjLoLimit(dval);
5396 break;
5397 case SCIP_LPPAR_LPTILIM:
5398 assert( dval > 0.0 );
5399 /* soplex requires 0 <= dval
5400 *
5401 * However for consistency we assert the timelimit to be strictly positive.
5402 */
5403 lpi->spx->setTerminationTime(dval);
5404 break;
5406 assert( dval >= 0.0 || dval == -1.0 );
5407 lpi->rowrepswitch = dval;
5408 break;
5410 lpi->conditionlimit = dval;
5411 lpi->checkcondition = (dval >= 0.0);
5412 break;
5413 default:
5414 return SCIP_PARAMETERUNKNOWN;
5415 } /*lint !e788*/
5416
5417 return SCIP_OKAY;
5418}
5419
5420/** interrupts the currently ongoing lp solve or disables the interrupt */
5422 SCIP_LPI* lpi, /**< LP interface structure */
5423 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
5424 )
5425{
5426 /*lint --e{715}*/
5427 assert(lpi != NULL);
5428
5429 return SCIP_OKAY;
5430}
5431
5432/**@} */
5433
5434
5435
5436
5437/*
5438 * Numerical Methods
5439 */
5440
5441/**@name Numerical Methods */
5442/**@{ */
5443
5444/** returns value treated as infinity in the LP solver */
5446 SCIP_LPI* /*lpi*/ /**< LP interface structure */
5447 )
5448{
5449 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
5450
5451 return soplex::infinity;
5452}
5453
5454/** checks if given value is treated as infinity in the LP solver */
5456 SCIP_LPI* /*lpi*/, /**< LP interface structure */
5457 SCIP_Real val
5458 )
5459{
5460 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
5461
5462 return (val >= soplex::infinity);
5463}
5464
5465/**@} */
5466
5467
5468
5469
5470/*
5471 * File Interface Methods
5472 */
5473
5474/**@name File Interface Methods */
5475/**@{ */
5476
5477/** returns, whether the given file exists */
5478static
5480 const char* filename /**< file name */
5481 )
5482{
5483 FILE* f;
5484
5485 f = fopen(filename, "r");
5486 if( f == NULL )
5487 return FALSE;
5488
5489 fclose(f);
5490
5491 return TRUE;
5492}
5493
5494/** reads LP from a file */
5496 SCIP_LPI* lpi, /**< LP interface structure */
5497 const char* fname /**< file name */
5498 )
5499{
5500 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
5501
5502 assert(lpi != NULL);
5503 assert(lpi->spx != NULL);
5504 assert(fname != NULL);
5505
5506 assert( lpi->spx->preStrongbranchingBasisFreed() );
5507
5508 if( !fileExists(fname) )
5509 return SCIP_NOFILE;
5510
5511 try
5512 {
5513 if( !lpi->spx->readLP(fname) )
5514 return SCIP_READERROR;
5515 }
5516#ifndef NDEBUG
5517 catch( const SPxException& x )
5518 {
5519 std::string s = x.what();
5520 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5521#else
5522 catch( const SPxException& )
5523 {
5524#endif
5525 return SCIP_READERROR;
5526 }
5527
5528 return SCIP_OKAY;
5529}
5530
5531/** writes LP to a file */
5533 SCIP_LPI* lpi, /**< LP interface structure */
5534 const char* fname /**< file name */
5535 )
5536{
5537 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
5538
5539 assert(lpi != NULL);
5540 assert(lpi->spx != NULL);
5541 assert(fname != NULL);
5542
5543 try
5544 {
5545 lpi->spx->writeFile(fname);
5546 }
5547#ifndef NDEBUG
5548 catch( const SPxException& x )
5549 {
5550 std::string s = x.what();
5551 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5552#else
5553 catch( const SPxException& )
5554 {
5555#endif
5556 return SCIP_WRITEERROR;
5557 }
5558
5559 return SCIP_OKAY;
5560}
5561
5562/**@} */
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_VAR ** y
Definition: circlepacking.c:64
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_VAR ** x
Definition: circlepacking.c:63
unsigned short Type
Definition: cons_xor.c:131
#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
#define infinity
Definition: gastrans.c:80
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_spx1.cpp:2247
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4889
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4796
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx1.cpp:5321
SCIP_Real SCIPlpiInfinity(SCIP_LPI *)
Definition: lpi_spx1.cpp:5445
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3735
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:2320
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *, SCIP_Real val)
Definition: lpi_spx1.cpp:5455
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2170
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:4946
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3601
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3513
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:4082
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5005
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_spx1.cpp:2033
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx1.cpp:3882
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_spx1.cpp:5180
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5532
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_spx1.cpp:1688
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3643
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_spx1.cpp:5366
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_spx1.cpp:3313
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_spx1.cpp:5115
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_spx1.cpp:2573
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_spx1.cpp:1705
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_spx1.cpp:3387
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_spx1.cpp:2819
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_spx1.cpp:1721
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx1.cpp:3919
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx1.cpp:3805
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2454
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3774
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3065
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx1.cpp:3492
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5147
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3748
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_spx1.cpp:2188
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3545
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx1.cpp:3787
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5024
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_spx1.cpp:1780
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_spx1.cpp:3343
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:2879
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3576
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5495
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx1.cpp:3972
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3656
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5060
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3761
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4995
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx1.cpp:5232
const char * SCIPlpiGetSolverName(void)
Definition: lpi_spx1.cpp:1663
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:4169
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3528
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4391
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_spx1.cpp:2111
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_spx1.cpp:2606
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4691
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2721
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4736
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_spx1.cpp:2665
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3473
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_spx1.cpp:1672
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_spx1.cpp:3049
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3675
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2749
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_spx1.cpp:1713
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3079
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_spx1.cpp:2849
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_spx1.cpp:3417
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_spx1.cpp:3826
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3616
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:2001
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_spx1.cpp:2794
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4976
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3563
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3005
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_spx1.cpp:1891
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2961
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_spx1.cpp:1813
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3629
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx1.cpp:3951
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx1.cpp:4256
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1741
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1680
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_spx1.cpp:2340
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_spx1.cpp:2777
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3699
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_spx1.cpp:2556
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_spx1.cpp:5421
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_spx1.cpp:1973
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:2139
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2384
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_spx1.cpp:2539
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4845
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_spx1.cpp:2296
interface methods for specific LP solvers
SCIP_DUALPACKET ROWPACKET
Definition: lpi_clp.cpp:128
SCIP_DUALPACKET COLPACKET
Definition: lpi_clp.cpp:126
static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:1515
#define NULL
Definition: lpi_spx1.cpp:161
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:1531
static SCIP_Bool fileExists(const char *filename)
Definition: lpi_spx1.cpp:5479
#define SOPLEX_TRY(messagehdlr, x)
Definition: lpi_spx1.cpp:172
static int rowpacketNum(int nrows)
Definition: lpi_spx1.cpp:1506
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi, SPxSolver::Representation rep, SPxSolver::Type type)
Definition: lpi_spx1.cpp:2913
SCIP_DUALPACKET ROWPACKET
Definition: lpi_spx1.cpp:1400
#define SOPLEX_VERBLEVEL
Definition: lpi_spx1.cpp:151
static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx1.cpp:1446
static char * spxdesc
Definition: lpi_spx1.cpp:1646
#define COLS_PER_PACKET
Definition: lpi_spx1.cpp:1399
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition: lpi_spx1.cpp:1571
#define AUTOPRICING_ITERSWITCH
Definition: lpi_spx1.cpp:43
SCIP_DUALPACKET COLPACKET
Definition: lpi_spx1.cpp:1398
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_spx1.cpp:3095
static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx1.cpp:1468
static int colpacketNum(int ncols)
Definition: lpi_spx1.cpp:1497
char * initSpxDesc()
Definition: lpi_spx1.cpp:1648
#define SOPLEX_SUBVERSION
Definition: lpi_spx1.cpp:98
static SCIP_RETCODE getRedCostEst(SPxSCIP *spx, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:4027
static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
Definition: lpi_spx1.cpp:1547
#define SOPLEX_TRY_ABORT(x)
Definition: lpi_spx1.cpp:217
static SPxLP::SPxSense spxObjsen(SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1597
#define ROWS_PER_PACKET
Definition: lpi_spx1.cpp:1401
static const char spxname[20]
Definition: lpi_spx1.cpp:1643
static void invalidateSolution(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1616
static SCIP_RETCODE lpiGetBInvVec(SCIP_LPI *lpi, SCIP_Real *rhs, SCIP_Real *coef)
Definition: lpi_spx1.cpp:4562
#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 BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
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
static SCIP_RETCODE readFile(SCIP *scip, CMININPUT *cmininput, const char *filename)
Definition: reader_cmin.c:1148
@ 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_Real rowrepswitch
Definition: lpi_spx1.cpp:1416
SCIP_PRICING pricing
Definition: lpi_clp.cpp:112
int cstatsize
Definition: lpi_clp.cpp:109
SCIP_MESSAGEHDLR * messagehdlr
Definition: lpi_cpx.c:185
SLUFactor * factorization
Definition: lpi_spx1.cpp:1415
SPxSCIP * spx
Definition: lpi_spx1.cpp:1408
SCIP_Bool checkcondition
Definition: lpi_cpx.c:175
int index
Definition: struct_var.h:254
@ 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_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_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
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63