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-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file lpi_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
1305 // compute size
1306 if ( namestoragesize == 0 )
1307 {
1308 // the following may overestimate the space requirements
1309 *storageleft = -m_colnames->memSize();
1310 }
1311 else
1312 {
1313 NameSet* names = m_colnames;
1314 assert( names != 0 );
1315 int sizeleft = namestoragesize;
1316 char* s = namestorage;
1317 for (int j = firstcol; j <= lastcol; ++j)
1318 {
1319 const char* t = (*names)[j];
1320 colnames[j-firstcol] = s;
1321 while( *t != '\0' && sizeleft >= 0 )
1322 {
1323 *(s++) = *(t++);
1324 --sizeleft;
1325 }
1326 *(s++) = '\0';
1327 }
1328 if ( sizeleft == 0 )
1329 {
1330 *storageleft = namestoragesize - m_colnames->memSize();
1331 assert( *storageleft <= 0 );
1332 }
1333 else
1334 *storageleft = sizeleft;
1335 }
1336 }
1337
1338 /** copy row names into namestorage with access via row */
1339 void getRowNames(
1340 int firstrow, /**< first row to get name from LP */
1341 int lastrow, /**< last row to get name from LP */
1342 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) */
1343 char* namestorage, /**< storage for row names */
1344 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1345 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) */
1346 )
1347 {
1348 assert( m_rownames != NULL );
1349
1350 // compute size
1351 if ( namestoragesize == 0 )
1352 {
1353 // the following may overestimate the space requirements
1354 *storageleft = -m_rownames->memSize();
1355 }
1356 else
1357 {
1358 NameSet* names = m_rownames;
1359 assert( names != 0 );
1360 int sizeleft = namestoragesize;
1361 char* s = namestorage;
1362 for (int i = firstrow; i <= lastrow; ++i)
1363 {
1364 const char* t = (*names)[i];
1365 rownames[i-firstrow] = s;
1366 while( *t != '\0' && sizeleft >= 0 )
1367 {
1368 *(s++) = *(t++);
1369 --sizeleft;
1370 }
1371 *(s++) = '\0';
1372 }
1373 if ( sizeleft == 0 )
1374 {
1375 *storageleft = m_rownames->memSize() - namestoragesize;
1376 assert( *storageleft <= 0 );
1377 }
1378 else
1379 *storageleft = sizeleft;
1380 }
1381 }
1382}; /*lint !e1748*/
1383
1384
1385
1386
1387/********************************************************************/
1388/*----------------------------- C --------------------------------*/
1389/********************************************************************/
1390
1391#include "lpi/lpi.h"
1392#include "scip/bitencode.h"
1393
1394typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
1395#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
1396typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
1397#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
1398
1399
1400
1401/** LP interface */
1402struct SCIP_LPi
1403{
1404 SPxSCIP* spx; /**< our SPxSolver implementation */
1405 int* cstat; /**< array for storing column basis status */
1406 int* rstat; /**< array for storing row basis status */
1407 int cstatsize; /**< size of cstat array */
1408 int rstatsize; /**< size of rstat array */
1409 SCIP_PRICING pricing; /**< current pricing strategy */
1410 SCIP_Bool solved; /**< was the current LP solved? */
1411 SLUFactor* factorization; /**< factorization possibly needed for basis inverse */
1412 SCIP_Real rowrepswitch; /**< use row representation if number of rows divided by number of columns exceeds this value */
1413 SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
1414 SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
1415 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
1416};
1417
1418/** LPi state stores basis information */
1419struct SCIP_LPiState
1420{
1421 int ncols; /**< number of LP columns */
1422 int nrows; /**< number of LP rows */
1423 COLPACKET* packcstat; /**< column basis status in compressed form */
1424 ROWPACKET* packrstat; /**< row basis status in compressed form */
1425};
1426
1427/** LPi norms to store dual steepest edge */
1428struct SCIP_LPiNorms
1429{
1430 int nrows; /**< number of stored norms corresponding to rows */
1431 int ncols; /**< number of stored norms corresponding to cols */
1432 SCIP_Real* norms; /**< norms to be (re)stored */
1433};
1434
1435
1436/*
1437 * dynamic memory arrays
1438 */
1439
1440/** resizes cstat array to have at least num entries */
1441static
1443 SCIP_LPI* lpi, /**< LP interface structure */
1444 int num /**< minimal number of entries in array */
1445 )
1446{
1447 assert(lpi != NULL);
1448
1449 if( num > lpi->cstatsize )
1450 {
1451 int newsize;
1452
1453 newsize = MAX(2*lpi->cstatsize, num);
1454 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
1455 lpi->cstatsize = newsize;
1456 }
1457 assert(num <= lpi->cstatsize);
1458
1459 return SCIP_OKAY;
1460}
1461
1462/** resizes rstat array to have at least num entries */
1463static
1465 SCIP_LPI* lpi, /**< LP interface structure */
1466 int num /**< minimal number of entries in array */
1467 )
1468{
1469 assert(lpi != NULL);
1470
1471 if( num > lpi->rstatsize )
1472 {
1473 int newsize;
1474
1475 newsize = MAX(2*lpi->rstatsize, num);
1476 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
1477 lpi->rstatsize = newsize;
1478 }
1479 assert(num <= lpi->rstatsize);
1480
1481 return SCIP_OKAY;
1482}
1483
1484
1485
1486
1487/*
1488 * LPi state methods
1489 */
1490
1491/** returns the number of packets needed to store column packet information */
1492static
1494 int ncols /**< number of columns to store */
1495 )
1496{
1497 return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
1498}
1499
1500/** returns the number of packets needed to store row packet information */
1501static
1503 int nrows /**< number of rows to store */
1504 )
1505{
1506 return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
1507}
1508
1509/** store row and column basis status in a packed LPi state object */
1510static
1512 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
1513 const int* cstat, /**< basis status of columns in unpacked format */
1514 const int* rstat /**< basis status of rows in unpacked format */
1515 )
1516{
1517 assert(lpistate != NULL);
1518 assert(lpistate->packcstat != NULL);
1519 assert(lpistate->packrstat != NULL);
1520
1521 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
1522 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
1523}
1524
1525/** unpacks row and column basis status from a packed LPi state object */
1526static
1528 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
1529 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
1530 int* rstat /**< buffer for storing basis status of rows in unpacked format */
1531 )
1532{
1533 assert(lpistate != NULL);
1534 assert(lpistate->packcstat != NULL);
1535 assert(lpistate->packrstat != NULL);
1536
1537 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
1538 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
1539}
1540
1541/** creates LPi state information object */
1542static
1544 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
1545 BMS_BLKMEM* blkmem, /**< block memory */
1546 int ncols, /**< number of columns to store */
1547 int nrows /**< number of rows to store */
1548 )
1549{
1550 assert(lpistate != NULL);
1551 assert(blkmem != NULL);
1552 assert(ncols >= 0);
1553 assert(nrows >= 0);
1554
1555 int nColPackets = colpacketNum(ncols);
1556 int nRowPackets = rowpacketNum(nrows);
1557
1558 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
1559 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
1560 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
1561
1562 return SCIP_OKAY;
1563}
1564
1565/** frees LPi state information */
1566static
1568 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
1569 BMS_BLKMEM* blkmem /**< block memory */
1570 )
1571{
1572 assert(blkmem != NULL);
1573 assert(lpistate != NULL);
1574 assert(*lpistate != NULL);
1575
1576 int nColPackets = colpacketNum((*lpistate)->ncols);
1577 int nRowPackets = rowpacketNum((*lpistate)->nrows);
1578
1579 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
1580 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
1581 BMSfreeBlockMemory(blkmem, lpistate);
1582}
1583
1584
1585
1586
1587/*
1588 * local methods
1589 */
1590
1591/** converts SCIP's objective sense into SoPlex's objective sense */
1592static
1593SPxLP::SPxSense spxObjsen(
1594 SCIP_OBJSEN objsen /**< SCIP's objective sense value */
1595 )
1596{
1597 switch( objsen )
1598 {
1600 return SPxLP::MAXIMIZE;
1602 return SPxLP::MINIMIZE;
1603 default:
1604 SCIPerrorMessage("invalid objective sense\n");
1605 SCIPABORT();
1606 return SPxLP::MINIMIZE; /*lint !e527 */
1607 }
1608}
1609
1610/** marks the current LP to be unsolved */
1611static
1613{
1614 assert(lpi != NULL);
1615 lpi->solved = FALSE;
1616 if ( lpi->factorization != 0 )
1617 {
1618 delete lpi->factorization;
1619 lpi->factorization = 0;
1620 }
1621}
1622
1623
1624
1625/*
1626 * LP Interface Methods
1627 */
1628
1629
1630/*
1631 * Miscellaneous Methods
1632 */
1633
1634char* initSpxDesc( );
1635
1636#if (SOPLEX_SUBVERSION > 0)
1637 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'};
1638#else
1639 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'};
1640#endif
1641
1642static char* spxdesc = initSpxDesc();
1643
1645{
1646 spxdesc = new char[200];
1647 (void)snprintf(spxdesc, 200, "%s [GitHash: %s]", "Linear Programming Solver developed at Zuse Institute Berlin (soplex.zib.de)"
1648#ifdef SCIP_WITH_LPSCHECK
1649 " - including CPLEX double check"
1650#endif
1651 , getGitHash());
1652 return spxdesc;
1653}
1654
1655/**@name Miscellaneous Methods */
1656/**@{ */
1657
1658/** gets name and version of LP solver */
1660 void
1661 )
1662{
1663 SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
1664 return spxname;
1665}
1666
1667/** gets description of LP solver (developer, webpage, ...) */
1669 void
1670 )
1671{
1672 return spxdesc;
1673}
1674
1675/** gets pointer for LP solver - use only with great care */
1677 SCIP_LPI* lpi /**< pointer to an LP interface structure */
1678 )
1679{
1680 return (void*) lpi->spx;
1681}
1682
1683/** pass integrality information about variables to the solver */
1685 SCIP_LPI* lpi, /**< pointer to an LP interface structure */
1686 int ncols, /**< length of integrality array */
1687 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
1688 )
1689{
1690#if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1691 assert(ncols == lpi->spx->nCols() || (ncols == 0 && intInfo == NULL));
1692 lpi->spx->setIntegralityInformation(ncols, intInfo);
1693 return SCIP_OKAY;
1694#else
1695 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1696 return SCIP_LPERROR;
1697#endif
1698}
1699
1700/** informs about availability of a primal simplex solving method */
1702 void
1703 )
1704{
1705 return TRUE;
1706}
1707
1708/** informs about availability of a dual simplex solving method */
1710 void
1711 )
1712{
1713 return TRUE;
1714}
1715
1716/** informs about availability of a barrier solving method */
1718 void
1719 )
1720{
1721 return FALSE;
1722}
1723
1724/**@} */
1725
1726
1727
1728
1729/*
1730 * LPI Creation and Destruction Methods
1731 */
1732
1733/**@name LPI Creation and Destruction Methods */
1734/**@{ */
1735
1736/** creates an LP problem object */
1738 SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1739 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1740 const char* name, /**< problem name */
1741 SCIP_OBJSEN objsen /**< objective sense */
1742 )
1743{
1744 assert(lpi != NULL);
1745 assert(name != NULL);
1746
1747 /* create SoPlex object */
1748 SCIP_ALLOC( BMSallocMemory(lpi) );
1749
1750 /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1751 (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1752 SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1753 (*lpi)->cstat = NULL;
1754 (*lpi)->rstat = NULL;
1755 (*lpi)->cstatsize = 0;
1756 (*lpi)->rstatsize = 0;
1757 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1758 (*lpi)->factorization = 0;
1759 (*lpi)->rowrepswitch = SCIPlpiInfinity(*lpi);
1760 (*lpi)->conditionlimit = -1.0;
1761 (*lpi)->checkcondition = FALSE;
1762 (*lpi)->messagehdlr = messagehdlr;
1763
1764 invalidateSolution(*lpi);
1765
1766 /* set objective sense */
1767 SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
1768
1769 /* set default pricing */
1770 SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1771
1772 return SCIP_OKAY;
1773}
1774
1775/** deletes an LP problem object */
1777 SCIP_LPI** lpi /**< pointer to an LP interface structure */
1778 )
1779{
1780 assert(lpi != NULL);
1781 assert(*lpi != NULL);
1782 assert((*lpi)->spx != NULL);
1783
1784 /* free LP using destructor and free memory via blockmemshell */
1785 (*lpi)->spx->~SPxSCIP();
1786 BMSfreeMemory(&((*lpi)->spx));
1787
1788 /* free memory */
1789 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1790 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1791 BMSfreeMemory(lpi);
1792
1793 return SCIP_OKAY;
1794}
1795
1796/**@} */
1797
1798
1799
1800
1801/*
1802 * Modification Methods
1803 */
1804
1805/**@name Modification Methods */
1806/**@{ */
1807
1808/** copies LP data with column matrix into LP solver */
1810 SCIP_LPI* lpi, /**< LP interface structure */
1811 SCIP_OBJSEN objsen, /**< objective sense */
1812 int ncols, /**< number of columns */
1813 const SCIP_Real* obj, /**< objective function values of columns */
1814 const SCIP_Real* lb, /**< lower bounds of columns */
1815 const SCIP_Real* ub, /**< upper bounds of columns */
1816 char** colnames, /**< column names, or NULL */
1817 int nrows, /**< number of rows */
1818 const SCIP_Real* lhs, /**< left hand sides of rows */
1819 const SCIP_Real* rhs, /**< right hand sides of rows */
1820 char** /*rownames*/, /**< row names, or NULL */
1821 int nnonz, /**< number of nonzero elements in the constraint matrix */
1822 const int* beg, /**< start index of each column in ind- and val-array */
1823 const int* ind, /**< row indices of constraint matrix entries */
1824 const SCIP_Real* val /**< values of constraint matrix entries */
1825 )
1826{
1827#ifndef NDEBUG
1828 {
1829 int j;
1830 for( j = 0; j < nnonz; j++ )
1831 assert( val[j] != 0 );
1832 }
1833#endif
1834
1835 SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1836
1837 assert(lpi != NULL);
1838 assert(lpi->spx != NULL);
1839 assert(lhs != NULL);
1840 assert(rhs != NULL);
1841 assert(obj != NULL);
1842 assert(lb != NULL);
1843 assert(ub != NULL);
1844 assert(beg != NULL);
1845 assert(ind != NULL);
1846 assert(val != NULL);
1847
1848 invalidateSolution(lpi);
1849 assert( lpi->spx->preStrongbranchingBasisFreed() );
1850
1851 try
1852 {
1853 SPxSCIP* spx = lpi->spx;
1854 LPRowSet rows(nrows);
1855 DSVector emptyVector(0);
1856 int i;
1857
1858 spx->clear();
1859
1860 /* set objective sense */
1861 spx->setSense(spxObjsen(objsen));
1862
1863 /* create empty rows with given sides */
1864 for( i = 0; i < nrows; ++i )
1865 rows.add(lhs[i], emptyVector, rhs[i]);
1866 spx->addRows(rows);
1867
1868 /* create column vectors with coefficients and bounds */
1869 SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1870 }
1871#ifndef NDEBUG
1872 catch( const SPxException& x )
1873 {
1874 std::string s = x.what();
1875 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1876#else
1877 catch( const SPxException& )
1878 {
1879#endif
1880 return SCIP_LPERROR;
1881 }
1882
1883 return SCIP_OKAY;
1884}
1885
1886/** adds columns to the LP */
1888 SCIP_LPI* lpi, /**< LP interface structure */
1889 int ncols, /**< number of columns to be added */
1890 const SCIP_Real* obj, /**< objective function values of new columns */
1891 const SCIP_Real* lb, /**< lower bounds of new columns */
1892 const SCIP_Real* ub, /**< upper bounds of new columns */
1893 char** /*colnames*/, /**< column names, or NULL */
1894 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1895 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1896 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1897 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1898 )
1899{
1900 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1901
1902 assert(lpi != NULL);
1903 assert(lpi->spx != NULL);
1904 assert(obj != NULL);
1905 assert(lb != NULL);
1906 assert(ub != NULL);
1907 assert(nnonz == 0 || beg != NULL);
1908 assert(nnonz == 0 || ind != NULL);
1909 assert(nnonz == 0 || val != NULL);
1910 assert(nnonz >= 0);
1911 assert(ncols >= 0);
1912
1913 invalidateSolution(lpi);
1914
1915 assert( lpi->spx->preStrongbranchingBasisFreed() );
1916
1917#ifndef NDEBUG
1918 if ( nnonz > 0 )
1919 {
1920 /* perform check that no new rows are added - this is likely to be a mistake */
1921 int nrows = lpi->spx->nRows();
1922 for (int j = 0; j < nnonz; ++j)
1923 {
1924 assert( 0 <= ind[j] && ind[j] < nrows );
1925 assert( val[j] != 0.0 );
1926 }
1927 }
1928#endif
1929
1930 SPxSCIP* spx = lpi->spx;
1931 try
1932 {
1933 LPColSet cols(ncols);
1934 DSVector colVector(ncols);
1935 int start;
1936 int last;
1937 int i;
1938
1939 /* create column vectors with coefficients and bounds */
1940 for( i = 0; i < ncols; ++i )
1941 {
1942 colVector.clear();
1943 if( nnonz > 0 )
1944 {
1945 start = beg[i];
1946 last = (i == ncols-1 ? nnonz : beg[i+1]);
1947 colVector.add( last-start, &ind[start], &val[start] );
1948 }
1949 cols.add(obj[i], lb[i], colVector, ub[i]);
1950 }
1951 spx->addCols(cols);
1952 }
1953#ifndef NDEBUG
1954 catch( const SPxException& x )
1955 {
1956 std::string s = x.what();
1957 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1958#else
1959 catch( const SPxException& )
1960 {
1961#endif
1962 return SCIP_LPERROR;
1963 }
1964
1965 return SCIP_OKAY;
1966}
1967
1968/** deletes all columns in the given range from LP */
1970 SCIP_LPI* lpi, /**< LP interface structure */
1971 int firstcol, /**< first column to be deleted */
1972 int lastcol /**< last column to be deleted */
1973 )
1974{
1975 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1976
1977 assert(lpi != NULL);
1978 assert(lpi->spx != NULL);
1979 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
1980
1981 invalidateSolution(lpi);
1982
1983 assert( lpi->spx->preStrongbranchingBasisFreed() );
1984
1985 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRange(firstcol, lastcol) );
1986
1987 return SCIP_OKAY;
1988}
1989
1990/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1992 SCIP_LPI* lpi, /**< LP interface structure */
1993 int* dstat /**< deletion status of columns
1994 * input: 1 if column should be deleted, 0 if not
1995 * output: new position of column, -1 if column was deleted */
1996 )
1997{
1998 int ncols;
1999 int i;
2000
2001 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
2002
2003 assert(lpi != NULL);
2004 assert(lpi->spx != NULL);
2005 assert(dstat != NULL);
2006
2007 invalidateSolution(lpi);
2008
2009 assert( lpi->spx->preStrongbranchingBasisFreed() );
2010
2011 ncols = lpi->spx->nCols();
2012
2013 /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
2014 for( i = 0; i < ncols; ++i )
2015 dstat[i] *= -1;
2016
2017 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeCols(dstat) );
2018
2019 return SCIP_OKAY;
2020}
2021
2022/** adds rows to the LP */
2024 SCIP_LPI* lpi, /**< LP interface structure */
2025 int nrows, /**< number of rows to be added */
2026 const SCIP_Real* lhs, /**< left hand sides of new rows */
2027 const SCIP_Real* rhs, /**< right hand sides of new rows */
2028 char** /*rownames*/, /**< row names, or NULL */
2029 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
2030 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
2031 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
2032 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
2033 )
2034{
2035 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
2036
2037 assert(lpi != NULL);
2038 assert(lpi->spx != NULL);
2039 assert(lhs != NULL);
2040 assert(rhs != NULL);
2041 assert(nnonz == 0 || beg != NULL);
2042 assert(nnonz == 0 || ind != NULL);
2043 assert(nnonz == 0 || val != NULL);
2044
2045 invalidateSolution(lpi);
2046
2047 assert( lpi->spx->preStrongbranchingBasisFreed() );
2048
2049#ifndef NDEBUG
2050 if ( nnonz > 0 )
2051 {
2052 /* perform check that no new columns are added - this is likely to be a mistake */
2053 int ncols = lpi->spx->nCols();
2054 for (int j = 0; j < nnonz; ++j)
2055 {
2056 assert( 0 <= ind[j] && ind[j] < ncols );
2057 assert( val[j] != 0.0 );
2058 }
2059 }
2060#endif
2061
2062 try
2063 {
2064 SPxSCIP* spx = lpi->spx;
2065 LPRowSet rows(nrows);
2066 DSVector rowVector;
2067 int start;
2068 int last;
2069 int i;
2070
2071 /* create row vectors with given sides */
2072 for( i = 0; i < nrows; ++i )
2073 {
2074 rowVector.clear();
2075 if( nnonz > 0 )
2076 {
2077 start = beg[i];
2078 last = (i == nrows-1 ? nnonz : beg[i+1]);
2079 rowVector.add( last-start, &ind[start], &val[start] );
2080 }
2081 rows.add(lhs[i], rowVector, rhs[i]);
2082 }
2083 spx->addRows(rows);
2084 }
2085#ifndef NDEBUG
2086 catch( const SPxException& x )
2087 {
2088 std::string s = x.what();
2089 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2090#else
2091 catch( const SPxException& )
2092 {
2093#endif
2094 return SCIP_LPERROR;
2095 }
2096
2097 return SCIP_OKAY;
2098}
2099
2100/** deletes all rows in the given range from LP */
2102 SCIP_LPI* lpi, /**< LP interface structure */
2103 int firstrow, /**< first row to be deleted */
2104 int lastrow /**< last row to be deleted */
2105 )
2106{
2107 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
2108
2109 assert(lpi != NULL);
2110 assert(lpi->spx != NULL);
2111 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2112
2113 invalidateSolution(lpi);
2114
2115 assert( lpi->spx->preStrongbranchingBasisFreed() );
2116
2117 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRange(firstrow, lastrow) );
2118
2119 return SCIP_OKAY;
2120}
2121
2122/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
2124 SCIP_LPI* lpi, /**< LP interface structure */
2125 int* dstat /**< deletion status of rows
2126 * input: 1 if row should be deleted, 0 if not
2127 * output: new position of row, -1 if row was deleted */
2128 )
2129{
2130 int nrows;
2131 int i;
2132
2133 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
2134
2135 assert(lpi != NULL);
2136 assert(lpi->spx != NULL);
2137
2138 invalidateSolution(lpi);
2139
2140 assert( lpi->spx->preStrongbranchingBasisFreed() );
2141
2142 nrows = lpi->spx->nRows();
2143
2144 /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
2145 for( i = 0; i < nrows; ++i )
2146 dstat[i] *= -1;
2147
2148 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRows(dstat) );
2149
2150 return SCIP_OKAY;
2151}
2152
2153/** clears the whole LP */
2155 SCIP_LPI* lpi /**< LP interface structure */
2156 )
2157{
2158 SCIPdebugMessage("calling SCIPlpiClear()\n");
2159
2160 assert(lpi != NULL);
2161 assert(lpi->spx != NULL);
2162
2163 invalidateSolution(lpi);
2164
2165 assert( lpi->spx->preStrongbranchingBasisFreed() );
2166 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clear() );
2167
2168 return SCIP_OKAY;
2169}
2170
2171/** changes lower and upper bounds of columns */
2173 SCIP_LPI* lpi, /**< LP interface structure */
2174 int ncols, /**< number of columns to change bounds for */
2175 const int* ind, /**< column indices or NULL if ncols is zero */
2176 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
2177 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
2178 )
2179{
2180 int i;
2181
2182 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
2183
2184 assert(lpi != NULL);
2185 assert(lpi->spx != NULL);
2186 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
2187 if( ncols <= 0 )
2188 return SCIP_OKAY;
2189
2190 invalidateSolution(lpi);
2191
2192 assert( lpi->spx->preStrongbranchingBasisFreed() );
2193
2194 try
2195 {
2196 for( i = 0; i < ncols; ++i )
2197 {
2198 assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2199
2200 if ( SCIPlpiIsInfinity(lpi, lb[i]) )
2201 {
2202 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
2203 return SCIP_LPERROR;
2204 }
2205 if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
2206 {
2207 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
2208 return SCIP_LPERROR;
2209 }
2210
2211 lpi->spx->changeBounds(ind[i], lb[i], ub[i]);
2212 assert(lpi->spx->lower(ind[i]) <= lpi->spx->upper(ind[i]) + Param::epsilon());
2213 }
2214 }
2215#ifndef NDEBUG
2216 catch( const SPxException& x )
2217 {
2218 std::string s = x.what();
2219 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2220#else
2221 catch( const SPxException& )
2222 {
2223#endif
2224 return SCIP_LPERROR;
2225 }
2226
2227 return SCIP_OKAY;
2228}
2229
2230/** changes left and right hand sides of rows */
2232 SCIP_LPI* lpi, /**< LP interface structure */
2233 int nrows, /**< number of rows to change sides for */
2234 const int* ind, /**< row indices */
2235 const SCIP_Real* lhs, /**< new values for left hand sides */
2236 const SCIP_Real* rhs /**< new values for right hand sides */
2237 )
2238{
2239 int i;
2240
2241 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
2242
2243 assert(lpi != NULL);
2244 assert(lpi->spx != NULL);
2245 assert(ind != NULL);
2246 assert(lhs != NULL);
2247 assert(rhs != NULL);
2248 if( nrows <= 0 )
2249 return SCIP_OKAY;
2250
2251 invalidateSolution(lpi);
2252
2253 assert( lpi->spx->preStrongbranchingBasisFreed() );
2254
2255 try
2256 {
2257 for( i = 0; i < nrows; ++i )
2258 {
2259 assert(0 <= ind[i] && ind[i] < lpi->spx->nRows());
2260 lpi->spx->changeRange(ind[i], lhs[i], rhs[i]);
2261 assert(lpi->spx->lhs(ind[i]) <= lpi->spx->rhs(ind[i]) + Param::epsilon());
2262 }
2263 }
2264#ifndef NDEBUG
2265 catch( const SPxException& x )
2266 {
2267 std::string s = x.what();
2268 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2269#else
2270 catch( const SPxException& )
2271 {
2272#endif
2273 return SCIP_LPERROR;
2274 }
2275
2276 return SCIP_OKAY;
2277}
2278
2279/** changes a single coefficient */
2281 SCIP_LPI* lpi, /**< LP interface structure */
2282 int row, /**< row number of coefficient to change */
2283 int col, /**< column number of coefficient to change */
2284 SCIP_Real newval /**< new value of coefficient */
2285 )
2286{
2287 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
2288
2289 assert(lpi != NULL);
2290 assert(lpi->spx != NULL);
2291 assert(0 <= row && row < lpi->spx->nRows());
2292 assert(0 <= col && col < lpi->spx->nCols());
2293
2294 invalidateSolution(lpi);
2295
2296 assert( lpi->spx->preStrongbranchingBasisFreed() );
2297
2298 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElement(row, col, newval) );
2299
2300 return SCIP_OKAY;
2301}
2302
2303/** changes the objective sense */
2305 SCIP_LPI* lpi, /**< LP interface structure */
2306 SCIP_OBJSEN objsen /**< new objective sense */
2307 )
2308{
2309 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
2310
2311 assert(lpi != NULL);
2312 assert(lpi->spx != NULL);
2313
2314 invalidateSolution(lpi);
2315
2316 assert( lpi->spx->preStrongbranchingBasisFreed() );
2317
2318 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setSense(spxObjsen(objsen)) );
2319
2320 return SCIP_OKAY;
2321}
2322
2323/** changes objective values of columns in the LP */
2325 SCIP_LPI* lpi, /**< LP interface structure */
2326 int ncols, /**< number of columns to change objective value for */
2327 const int* ind, /**< column indices to change objective value for */
2328 const SCIP_Real* obj /**< new objective values for columns */
2329 )
2330{
2331 int i;
2332
2333 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
2334
2335 assert(lpi != NULL);
2336 assert(lpi->spx != NULL);
2337 assert(ind != NULL);
2338 assert(obj != NULL);
2339
2340 invalidateSolution(lpi);
2341
2342 assert( lpi->spx->preStrongbranchingBasisFreed() );
2343
2344 try
2345 {
2346 for( i = 0; i < ncols; ++i )
2347 {
2348 assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2349 lpi->spx->changeObj(ind[i], obj[i]);
2350 }
2351 }
2352#ifndef NDEBUG
2353 catch( const SPxException& x )
2354 {
2355 std::string s = x.what();
2356 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2357#else
2358 catch( const SPxException& )
2359 {
2360#endif
2361 return SCIP_LPERROR;
2362 }
2363
2364 return SCIP_OKAY;
2365}
2366
2367/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
2369 SCIP_LPI* lpi, /**< LP interface structure */
2370 int row, /**< row number to scale */
2371 SCIP_Real scaleval /**< scaling multiplier */
2372 )
2373{
2374 SCIP_Real lhs;
2375 SCIP_Real rhs;
2376
2377 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
2378
2379 assert(lpi != NULL);
2380 assert(lpi->spx != NULL);
2381 assert(scaleval != 0.0);
2382
2383 try
2384 {
2385 invalidateSolution(lpi);
2386
2387 assert( lpi->spx->preStrongbranchingBasisFreed() );
2388
2389 /* get the row vector and the row's sides */
2390 SVector rowvec = lpi->spx->rowVector(row);
2391 lhs = lpi->spx->lhs(row);
2392 rhs = lpi->spx->rhs(row);
2393
2394 /* scale the row vector */
2395 rowvec *= scaleval;
2396
2397 /* adjust the sides */
2398 if( lhs > -soplex::infinity )
2399 lhs *= scaleval;
2400 else if( scaleval < 0.0 )
2401 lhs = soplex::infinity;
2402 if( rhs < soplex::infinity )
2403 rhs *= scaleval;
2404 else if( scaleval < 0.0 )
2405 rhs = -soplex::infinity;
2406 if( scaleval < 0.0 )
2407 {
2408 SCIP_Real oldlhs = lhs;
2409 lhs = rhs;
2410 rhs = oldlhs;
2411 }
2412
2413 /* create the new row */
2414 LPRow lprow(lhs, rowvec, rhs);
2415
2416 /* change the row in the LP */
2417 lpi->spx->changeRow(row, lprow);
2418 assert(lpi->spx->lhs(row) <= lpi->spx->rhs(row));
2419 }
2420#ifndef NDEBUG
2421 catch( const SPxException& x )
2422 {
2423 std::string s = x.what();
2424 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2425#else
2426 catch( const SPxException& )
2427 {
2428#endif
2429 return SCIP_LPERROR;
2430 }
2431
2432 return SCIP_OKAY;
2433}
2434
2435/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
2436 * are divided by the scalar; for negative scalars, the column's bounds are switched
2437 */
2439 SCIP_LPI* lpi, /**< LP interface structure */
2440 int col, /**< column number to scale */
2441 SCIP_Real scaleval /**< scaling multiplier */
2442 )
2443{
2444 SCIP_Real obj;
2445 SCIP_Real lb;
2446 SCIP_Real ub;
2447
2448 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
2449
2450 assert(lpi != NULL);
2451 assert(lpi->spx != NULL);
2452 assert(scaleval != 0.0);
2453
2454 try
2455 {
2456 invalidateSolution(lpi);
2457
2458 assert( lpi->spx->preStrongbranchingBasisFreed() );
2459
2460 /* get the col vector and the col's bounds and objective value */
2461 SVector colvec = lpi->spx->colVector(col);
2462 obj = lpi->spx->obj(col);
2463 lb = lpi->spx->lower(col);
2464 ub = lpi->spx->upper(col);
2465
2466 /* scale the col vector */
2467 colvec *= scaleval;
2468
2469 /* scale the objective value */
2470 obj *= scaleval;
2471
2472 /* adjust the bounds */
2473 if( lb > -soplex::infinity )
2474 lb /= scaleval;
2475 else if( scaleval < 0.0 )
2476 lb = soplex::infinity;
2477 if( ub < soplex::infinity )
2478 ub /= scaleval;
2479 else if( scaleval < 0.0 )
2480 ub = -soplex::infinity;
2481 if( scaleval < 0.0 )
2482 {
2483 SCIP_Real oldlb = lb;
2484 lb = ub;
2485 ub = oldlb;
2486 }
2487
2488 /* create the new col (in LPCol's constructor, the upper bound is given first!) */
2489 LPCol lpcol(obj, colvec, ub, lb);
2490
2491 /* change the col in the LP */
2492 lpi->spx->changeCol(col, lpcol);
2493 assert(lpi->spx->lower(col) <= lpi->spx->upper(col));
2494 }
2495#ifndef NDEBUG
2496 catch( const SPxException& x )
2497 {
2498 std::string s = x.what();
2499 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2500#else
2501 catch( const SPxException& )
2502 {
2503#endif
2504 return SCIP_LPERROR;
2505 }
2506
2507 return SCIP_OKAY;
2508}
2509
2510/**@} */
2511
2512
2513
2514
2515/*
2516 * Data Accessing Methods
2517 */
2518
2519/**@name Data Accessing Methods */
2520/**@{ */
2521
2522/** gets the number of rows in the LP */
2524 SCIP_LPI* lpi, /**< LP interface structure */
2525 int* nrows /**< pointer to store the number of rows */
2526 )
2527{
2528 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
2529
2530 assert(lpi != NULL);
2531 assert(lpi->spx != NULL);
2532 assert(nrows != NULL);
2533
2534 *nrows = lpi->spx->nRows();
2535
2536 return SCIP_OKAY;
2537}
2538
2539/** gets the number of columns in the LP */
2541 SCIP_LPI* lpi, /**< LP interface structure */
2542 int* ncols /**< pointer to store the number of cols */
2543 )
2544{
2545 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
2546
2547 assert(lpi != NULL);
2548 assert(lpi->spx != NULL);
2549 assert(ncols != NULL);
2550
2551 *ncols = lpi->spx->nCols();
2552
2553 return SCIP_OKAY;
2554}
2555
2556/** gets the number of nonzero elements in the LP constraint matrix */
2558 SCIP_LPI* lpi, /**< LP interface structure */
2559 int* nnonz /**< pointer to store the number of nonzeros */
2560 )
2561{
2562 int i;
2563
2564 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
2565
2566 assert(lpi != NULL);
2567 assert(lpi->spx != NULL);
2568 assert(nnonz != NULL);
2569
2570 /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
2571 *nnonz = 0;
2572 if( lpi->spx->nRows() < lpi->spx->nCols() )
2573 {
2574 for( i = 0; i < lpi->spx->nRows(); ++i )
2575 (*nnonz) += lpi->spx->rowVector(i).size();
2576 }
2577 else
2578 {
2579 for( i = 0; i < lpi->spx->nCols(); ++i )
2580 (*nnonz) += lpi->spx->colVector(i).size();
2581 }
2582
2583 return SCIP_OKAY;
2584}
2585
2586/** gets columns from LP problem object; the arrays have to be large enough to store all values
2587 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
2588 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2589 */
2591 SCIP_LPI* lpi, /**< LP interface structure */
2592 int firstcol, /**< first column to get from LP */
2593 int lastcol, /**< last column to get from LP */
2594 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
2595 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
2596 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2597 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
2598 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
2599 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2600 )
2601{
2602 int i;
2603 int j;
2604
2605 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
2606
2607 assert(lpi != NULL);
2608 assert(lpi->spx != NULL);
2609 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2610 assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
2611 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2612
2613 if( lb != NULL )
2614 {
2615 const Vector& lbvec = lpi->spx->lower();
2616 const Vector& ubvec = lpi->spx->upper();
2617 for( i = firstcol; i <= lastcol; ++i )
2618 {
2619 lb[i-firstcol] = lbvec[i];
2620 ub[i-firstcol] = ubvec[i];
2621 }
2622 }
2623
2624 if( nnonz != NULL )
2625 {
2626 *nnonz = 0;
2627 for( i = firstcol; i <= lastcol; ++i )
2628 {
2629 beg[i-firstcol] = *nnonz;
2630 const SVector& cvec = lpi->spx->colVector(i);
2631 for( j = 0; j < cvec.size(); ++j )
2632 {
2633 ind[*nnonz] = cvec.index(j);
2634 val[*nnonz] = cvec.value(j);
2635 (*nnonz)++;
2636 }
2637 }
2638 }
2639
2640 return SCIP_OKAY;
2641}
2642
2643/** gets rows from LP problem object; the arrays have to be large enough to store all values.
2644 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2645 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2646 */
2648 SCIP_LPI* lpi, /**< LP interface structure */
2649 int firstrow, /**< first row to get from LP */
2650 int lastrow, /**< last row to get from LP */
2651 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2652 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2653 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2654 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2655 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2656 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2657 )
2658{
2659 int i;
2660 int j;
2661
2662 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2663
2664 assert(lpi != NULL);
2665 assert(lpi->spx != NULL);
2666 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2667 assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2668 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2669
2670 if( lhs != NULL )
2671 {
2672 const Vector& lhsvec = lpi->spx->lhs();
2673 const Vector& rhsvec = lpi->spx->rhs();
2674 for( i = firstrow; i <= lastrow; ++i )
2675 {
2676 lhs[i-firstrow] = lhsvec[i];
2677 rhs[i-firstrow] = rhsvec[i];
2678 }
2679 }
2680
2681 if( nnonz != NULL )
2682 {
2683 *nnonz = 0;
2684 for( i = firstrow; i <= lastrow; ++i )
2685 {
2686 beg[i-firstrow] = *nnonz;
2687 const SVector& rvec = lpi->spx->rowVector(i);
2688 for( j = 0; j < rvec.size(); ++j )
2689 {
2690 ind[*nnonz] = rvec.index(j);
2691 val[*nnonz] = rvec.value(j);
2692 (*nnonz)++;
2693 }
2694 }
2695 }
2696
2697 return SCIP_OKAY;
2698}
2699
2700/** gets column names */
2702 SCIP_LPI* lpi, /**< LP interface structure */
2703 int firstcol, /**< first column to get name from LP */
2704 int lastcol, /**< last column to get name from LP */
2705 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2706 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2707 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2708 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2709 )
2710{
2711 assert( lpi != NULL );
2712 assert( lpi->spx != NULL );
2713 assert( colnames != NULL || namestoragesize == 0 );
2714 assert( namestorage != NULL || namestoragesize == 0 );
2715 assert( namestoragesize >= 0 );
2716 assert( storageleft != NULL );
2717 assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols() );
2718
2719 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2720
2721 lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2722
2723 return SCIP_OKAY;
2724}
2725
2726/** gets row names */
2728 SCIP_LPI* lpi, /**< LP interface structure */
2729 int firstrow, /**< first row to get name from LP */
2730 int lastrow, /**< last row to get name from LP */
2731 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2732 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2733 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2734 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2735 )
2736{
2737 assert( lpi != NULL );
2738 assert( lpi->spx != NULL );
2739 assert( rownames != NULL || namestoragesize == 0 );
2740 assert( namestorage != NULL || namestoragesize == 0 );
2741 assert( namestoragesize >= 0 );
2742 assert( storageleft != NULL );
2743 assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows() );
2744
2745 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2746
2747 lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2748
2749 return SCIP_OKAY;
2750}
2751
2752/** gets objective sense of the LP */
2754 SCIP_LPI* lpi, /**< LP interface structure */
2755 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2756 )
2757{
2758 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2759
2760 assert(lpi != NULL);
2761 assert(lpi->spx != NULL);
2762 assert(objsen != NULL);
2763
2764 *objsen = (lpi->spx->getSense() == SPxLP::MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2765
2766 return SCIP_OKAY;
2767}
2768
2769/** gets objective coefficients from LP problem object */
2771 SCIP_LPI* lpi, /**< LP interface structure */
2772 int firstcol, /**< first column to get objective coefficient for */
2773 int lastcol, /**< last column to get objective coefficient for */
2774 SCIP_Real* vals /**< array to store objective coefficients */
2775 )
2776{
2777 int i;
2778
2779 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2780
2781 assert(lpi != NULL);
2782 assert(lpi->spx != NULL);
2783 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2784 assert(vals != NULL);
2785
2786 for( i = firstcol; i <= lastcol; ++i )
2787 vals[i-firstcol] = lpi->spx->obj(i);
2788
2789 return SCIP_OKAY;
2790}
2791
2792/** gets current bounds from LP problem object */
2794 SCIP_LPI* lpi, /**< LP interface structure */
2795 int firstcol, /**< first column to get objective value for */
2796 int lastcol, /**< last column to get objective value for */
2797 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2798 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2799 )
2800{
2801 int i;
2802
2803 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2804
2805 assert(lpi != NULL);
2806 assert(lpi->spx != NULL);
2807 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2808
2809 for( i = firstcol; i <= lastcol; ++i )
2810 {
2811 if( lbs != NULL )
2812 lbs[i-firstcol] = lpi->spx->lower(i);
2813 if( ubs != NULL )
2814 ubs[i-firstcol] = lpi->spx->upper(i);
2815 }
2816
2817 return SCIP_OKAY;
2818}
2819
2820/** gets current row sides from LP problem object */
2822 SCIP_LPI* lpi, /**< LP interface structure */
2823 int firstrow, /**< first row to get sides for */
2824 int lastrow, /**< last row to get sides for */
2825 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2826 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2827 )
2828{
2829 int i;
2830
2831 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2832
2833 assert(lpi != NULL);
2834 assert(lpi->spx != NULL);
2835 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2836
2837 for( i = firstrow; i <= lastrow; ++i )
2838 {
2839 if( lhss != NULL )
2840 lhss[i-firstrow] = lpi->spx->lhs(i);
2841 if( rhss != NULL )
2842 rhss[i-firstrow] = lpi->spx->rhs(i);
2843 }
2844
2845 return SCIP_OKAY;
2846}
2847
2848/** gets a single coefficient */
2850 SCIP_LPI* lpi, /**< LP interface structure */
2851 int row, /**< row number of coefficient */
2852 int col, /**< column number of coefficient */
2853 SCIP_Real* val /**< pointer to store the value of the coefficient */
2854 )
2855{
2856 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2857
2858 assert(lpi != NULL);
2859 assert(lpi->spx != NULL);
2860 assert(0 <= col && col < lpi->spx->nCols());
2861 assert(0 <= row && row < lpi->spx->nRows());
2862 assert(val != NULL);
2863
2864 *val = lpi->spx->colVector(col)[row];
2865
2866 return SCIP_OKAY;
2867}
2868
2869/**@} */
2870
2871
2872
2873
2874/*
2875 * Solving Methods
2876 */
2877
2878/**@name Solving Methods */
2879/**@{ */
2880
2881/** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2882static
2884 SCIP_LPI* lpi, /**< LP interface structure */
2885 SPxSolver::Representation rep, /**< basis representation */
2886 SPxSolver::Type type /**< algorithm type */
2887 )
2888{
2889 assert( lpi != NULL );
2890 assert( lpi->spx != NULL );
2891 assert( rep == SPxSolver::ROW || rep == SPxSolver::COLUMN );
2892 assert( type == SPxSolver::ENTER || type == SPxSolver::LEAVE );
2893
2894 SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows, rep=%s\n", lpi->spx->nCols(), lpi->spx->nRows(),
2895 rep == SPxSolver::COLUMN ? "column" : "row");
2896
2897 invalidateSolution(lpi);
2898
2899 assert( lpi->spx->preStrongbranchingBasisFreed() );
2900
2901 /* set basis representation and algorithm type */
2902 lpi->spx->setRep(rep);
2903 lpi->spx->setType(type);
2904
2905#ifdef SCIP_WITH_LPSCHECK
2906 lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2907#endif
2908
2909 SPxSolver::Status status = lpi->spx->solve();
2910 SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->getStatus(), lpi->spx->basis().status());
2911 lpi->solved = TRUE;
2912
2913 switch( status )
2914 {
2915 case SPxSolver::ABORT_TIME:
2916 case SPxSolver::ABORT_ITER:
2917 case SPxSolver::ABORT_VALUE:
2918 case SPxSolver::SINGULAR:
2919 case SPxSolver::REGULAR:
2920 case SPxSolver::UNKNOWN:
2921 case SPxSolver::OPTIMAL:
2922 case SPxSolver::UNBOUNDED:
2923 case SPxSolver::INFEASIBLE:
2924 return SCIP_OKAY;
2925 default:
2926 return SCIP_LPERROR;
2927 } /*lint !e788*/
2928}
2929
2930/** calls primal simplex to solve the LP */
2932 SCIP_LPI* lpi /**< LP interface structure */
2933 )
2934{
2935 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2936
2937 SCIP_RETCODE retcode;
2938 SCIP_Bool rowrep;
2939
2940 assert(lpi != NULL);
2941 assert(lpi->spx != NULL);
2942
2943 /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2944 factor 1.1 for switching back to column representation */
2945 if( lpi->rowrepswitch >= 0 )
2946 {
2947 rowrep = lpi->spx->rep() == SPxSolver::ROW;
2948
2949 if( !rowrep )
2950 rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2951 else
2952 rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2953 }
2954 else
2955 rowrep = FALSE;
2956
2957 /* SoPlex doesn't distinct between the primal and dual simplex; however
2958 * we can force SoPlex to start with the desired method:
2959 * If the representation is COLUMN:
2960 * - ENTER = PRIMAL
2961 * - LEAVE = DUAL
2962 *
2963 * If the representation is ROW:
2964 * - ENTER = DUAL
2965 * - LEAVE = PRIMAL
2966 */
2967 retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::LEAVE) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::ENTER);
2968 assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
2969 assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
2970
2971 return retcode;
2972}
2973
2974/** calls dual simplex to solve the LP */
2976 SCIP_LPI* lpi /**< LP interface structure */
2977 )
2978{
2979 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2980
2981 SCIP_RETCODE retcode;
2982 SCIP_Bool rowrep;
2983
2984 assert(lpi != NULL);
2985 assert(lpi->spx != NULL);
2986
2987 /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2988 factor 1.1 for switching back to column representation */
2989 if( lpi->rowrepswitch >= 0 )
2990 {
2991 rowrep = lpi->spx->rep() == SPxSolver::ROW;
2992
2993 if( !rowrep )
2994 rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2995 else
2996 rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2997 }
2998 else
2999 rowrep = FALSE;
3000
3001 /* SoPlex doesn't distinct between the primal and dual simplex; however
3002 * we can force SoPlex to start with the desired method:
3003 * If the representation is COLUMN:
3004 * - ENTER = PRIMAL
3005 * - LEAVE = DUAL
3006 *
3007 * If the representation is ROW:
3008 * - ENTER = DUAL
3009 * - LEAVE = PRIMAL
3010 */
3011 retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::ENTER) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::LEAVE);
3012 assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
3013 assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
3014
3015 return retcode;
3016}
3017
3018/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
3020 SCIP_LPI* lpi, /**< LP interface structure */
3021 SCIP_Bool crossover /**< perform crossover */
3022 )
3023{ /*lint --e{715}*/
3024 assert(lpi != NULL);
3025 assert(lpi->spx != NULL);
3026
3027 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
3028
3029 /* SoPlex does not support barrier (yet) */
3030 SCIPerrorMessage("SCIPlpiSolveBarrier() not supported by SoPlex\n");
3031 return SCIP_INVALIDCALL;
3032}
3033
3034/** start strong branching - call before any strongbranching */
3036 SCIP_LPI* lpi /**< LP interface structure */
3037 )
3038{
3039 assert(lpi != NULL);
3040 assert(lpi->spx != NULL);
3041
3042 assert( lpi->spx->preStrongbranchingBasisFreed() );
3043 lpi->spx->savePreStrongbranchingBasis();
3044
3045 return SCIP_OKAY;
3046}
3047
3048/** end strong branching - call after any strongbranching */
3050 SCIP_LPI* lpi /**< LP interface structure */
3051 )
3052{
3053 assert(lpi != NULL);
3054 assert(lpi->spx != NULL);
3055
3056 assert( ! lpi->spx->preStrongbranchingBasisFreed() );
3057 lpi->spx->restorePreStrongbranchingBasis();
3058 lpi->spx->freePreStrongbranchingBasis();
3059
3060 return SCIP_OKAY;
3061}
3062
3063/** performs strong branching iterations on one arbitrary candidate */
3064static
3066 SCIP_LPI* lpi, /**< LP interface structure */
3067 int col, /**< column to apply strong branching on */
3068 SCIP_Real psol, /**< current primal solution value of column */
3069 int itlim, /**< iteration limit for strong branchings */
3070 SCIP_Real* down, /**< stores dual bound after branching column down */
3071 SCIP_Real* up, /**< stores dual bound after branching column up */
3072 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3073 * otherwise, it can only be used as an estimate value */
3074 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3075 * otherwise, it can only be used as an estimate value */
3076 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3077 )
3078{
3079 SPxSCIP* spx;
3080 SPxSolver::Status status;
3081 SCIP_Real oldlb;
3082 SCIP_Real oldub;
3083 SCIP_Real newlb;
3084 SCIP_Real newub;
3085 bool fromparentbasis;
3086 bool error;
3087 int oldItlim;
3088
3089 SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
3090
3091 assert(lpi != NULL);
3092 assert(lpi->spx != NULL);
3093 /* assert(down != NULL);
3094 * assert(up != NULL); temporary hack for cloud branching */
3095 assert(downvalid != NULL);
3096 assert(upvalid != NULL);
3097
3098 spx = lpi->spx;
3099 status = SPxSolver::UNKNOWN;
3100 fromparentbasis = false;
3101 error = false;
3102 oldItlim = spx->getIterationLimit();
3103
3104 /* get current bounds of column */
3105 oldlb = spx->lower(col);
3106 oldub = spx->upper(col);
3107
3108 *downvalid = FALSE;
3109 *upvalid = FALSE;
3110
3111 if( iter != NULL )
3112 *iter = 0;
3113
3114 /* set the algorithm type to use dual simplex */
3115 lpi->spx->setType( lpi->spx->rep() == SPxSolver::ROW ? SPxSolver::ENTER : SPxSolver::LEAVE);
3116
3117 /* down branch */
3118 newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
3119 if( newub >= oldlb - 0.5 && down != NULL )
3120 {
3121 SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
3122
3123 spx->changeUpper(col, newub);
3124 assert(spx->lower(col) <= spx->upper(col));
3125
3126 spx->setIterationLimit(itlim);
3127 do
3128 {
3129#ifdef SCIP_WITH_LPSCHECK
3130 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3131#endif
3132 status = spx->solve();
3133 SCIPdebugMessage(" --> Terminate with status %d\n", status);
3134 switch( status )
3135 {
3136 case SPxSolver::OPTIMAL:
3137 *down = spx->value();
3138 *downvalid = TRUE;
3139 SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3140 break;
3141 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3142 case SPxSolver::ABORT_ITER:
3143 case SPxSolver::ABORT_CYCLING:
3144 *down = spx->value();
3145 break;
3146 case SPxSolver::ABORT_VALUE:
3147 case SPxSolver::INFEASIBLE:
3148 *down = spx->terminationValue();
3149 *downvalid = TRUE;
3150 break;
3151 default:
3152 error = true;
3153 break;
3154 } /*lint !e788*/
3155 if( iter != NULL )
3156 (*iter) += spx->iterations();
3157
3158#ifdef STRONGBRANCH_RESTOREBASIS
3159 /* we restore the pre-strong-branching basis by default (and don't solve again) */
3160 assert( ! spx->preStrongbranchingBasisFreed() );
3161 spx->restorePreStrongbranchingBasis();
3162 fromparentbasis = false;
3163#else
3164 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3165 * pre-strong-branching basis and try again with reduced iteration limit */
3166 if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3167 {
3168 SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n", itlim - spx->iterations());
3169 spx->setIterationLimit(itlim - spx->iterations());
3170 spx->restorePreStrongbranchingBasis();
3171 fromparentbasis = true;
3172 error = false;
3173 }
3174 /* otherwise don't solve again */
3175 else
3176 fromparentbasis = false;
3177#endif
3178 }
3179 while( fromparentbasis );
3180
3181 spx->changeUpper(col, oldub);
3182 assert(spx->lower(col) <= spx->upper(col));
3183 }
3184 else if( down != NULL )
3185 {
3186 *down = spx->terminationValue();
3187 *downvalid = TRUE;
3188 }
3189 else
3190 *downvalid = TRUE;
3191
3192 /* up branch */
3193 if( !error )
3194 {
3195 newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
3196 if( newlb <= oldub + 0.5 && up != NULL )
3197 {
3198 SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
3199
3200 spx->changeLower(col, newlb);
3201 assert(spx->lower(col) <= spx->upper(col));
3202
3203 spx->setIterationLimit(itlim);
3204 do
3205 {
3206#ifdef SCIP_WITH_LPSCHECK
3207 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3208#endif
3209 status = spx->solve();
3210 SCIPdebugMessage(" --> Terminate with status %d\n", status);
3211 switch( status )
3212 {
3213 case SPxSolver::OPTIMAL:
3214 *up = spx->value();
3215 *upvalid = TRUE;
3216 SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3217 break;
3218 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3219 case SPxSolver::ABORT_ITER:
3220 case SPxSolver::ABORT_CYCLING:
3221 *up = spx->value();
3222 break;
3223 case SPxSolver::ABORT_VALUE:
3224 case SPxSolver::INFEASIBLE:
3225 *up = spx->terminationValue();
3226 *upvalid = TRUE;
3227 break;
3228 default:
3229 error = true;
3230 break;
3231 } /*lint !e788*/
3232 if( iter != NULL )
3233 (*iter) += spx->iterations();
3234
3235#ifdef STRONGBRANCH_RESTOREBASIS
3236 /* we restore the pre-strong-branching basis by default (and don't solve again) */
3237 assert( ! spx->preStrongbranchingBasisFreed() );
3238 spx->restorePreStrongbranchingBasis();
3239 fromparentbasis = false;
3240#else
3241 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3242 * pre-strong-branching basis and try again with reduced iteration limit */
3243 if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3244 {
3245 SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->iterations());
3246 spx->restorePreStrongbranchingBasis();
3247 spx->setIterationLimit(itlim - spx->iterations());
3248 error = false;
3249 fromparentbasis = true;
3250 }
3251 /* otherwise don't solve again */
3252 else
3253 fromparentbasis = false;
3254#endif
3255 }
3256 while( fromparentbasis );
3257
3258 spx->changeLower(col, oldlb);
3259 assert(spx->lower(col) <= spx->upper(col));
3260 }
3261 else if( up != NULL )
3262 {
3263 *up = spx->terminationValue();
3264 *upvalid = TRUE;
3265 }
3266 else
3267 *upvalid = TRUE;
3268 }
3269
3270 /* reset old iteration limit */
3271 spx->setIterationLimit(oldItlim);
3272
3273 if( error )
3274 {
3275 SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status));
3276 return SCIP_LPERROR;
3277 }
3278
3279 return SCIP_OKAY;
3280}
3281
3282/** performs strong branching iterations on one @b fractional candidate */
3284 SCIP_LPI* lpi, /**< LP interface structure */
3285 int col, /**< column to apply strong branching on */
3286 SCIP_Real psol, /**< fractional current primal solution value of column */
3287 int itlim, /**< iteration limit for strong branchings */
3288 SCIP_Real* down, /**< stores dual bound after branching column down */
3289 SCIP_Real* up, /**< stores dual bound after branching column up */
3290 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3291 * otherwise, it can only be used as an estimate value */
3292 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3293 * otherwise, it can only be used as an estimate value */
3294 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3295 )
3296{
3297 SCIP_RETCODE retcode;
3298
3299 /* pass call on to lpiStrongbranch() */
3300 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3301
3302 /* pass SCIP_LPERROR to SCIP without a back trace */
3303 if( retcode == SCIP_LPERROR )
3304 return SCIP_LPERROR;
3305
3306 /* evaluate retcode */
3307 SCIP_CALL( retcode );
3308
3309 return SCIP_OKAY;
3310}
3311
3312/** performs strong branching iterations on given @b fractional candidates */
3314 SCIP_LPI* lpi, /**< LP interface structure */
3315 int* cols, /**< columns to apply strong branching on */
3316 int ncols, /**< number of columns */
3317 SCIP_Real* psols, /**< fractional current primal solution values of columns */
3318 int itlim, /**< iteration limit for strong branchings */
3319 SCIP_Real* down, /**< stores dual bounds after branching columns down */
3320 SCIP_Real* up, /**< stores dual bounds after branching columns up */
3321 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3322 * otherwise, they can only be used as an estimate values */
3323 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3324 * otherwise, they can only be used as an estimate values */
3325 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3326 )
3327{
3328 SCIP_RETCODE retcode;
3329
3330 assert( cols != NULL );
3331 assert( psols != NULL );
3332 assert( down != NULL );
3333 assert( up != NULL );
3334 assert( downvalid != NULL );
3335 assert( upvalid != NULL );
3336 assert( down != NULL );
3337
3338 if ( iter != NULL )
3339 *iter = 0;
3340
3341 for (int j = 0; j < ncols; ++j)
3342 {
3343 /* pass call on to lpiStrongbranch() */
3344 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3345
3346 /* pass SCIP_LPERROR to SCIP without a back trace */
3347 if( retcode == SCIP_LPERROR )
3348 return SCIP_LPERROR;
3349
3350 /* evaluate retcode */
3351 SCIP_CALL( retcode );
3352 }
3353 return SCIP_OKAY;
3354}
3355
3356/** performs strong branching iterations on one candidate with @b integral value */
3358 SCIP_LPI* lpi, /**< LP interface structure */
3359 int col, /**< column to apply strong branching on */
3360 SCIP_Real psol, /**< current integral primal solution value of column */
3361 int itlim, /**< iteration limit for strong branchings */
3362 SCIP_Real* down, /**< stores dual bound after branching column down */
3363 SCIP_Real* up, /**< stores dual bound after branching column up */
3364 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3365 * otherwise, it can only be used as an estimate value */
3366 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3367 * otherwise, it can only be used as an estimate value */
3368 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3369 )
3370{
3371 SCIP_RETCODE retcode;
3372
3373 /* pass call on to lpiStrongbranch() */
3374 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, 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 given candidates with @b integral values */
3388 SCIP_LPI* lpi, /**< LP interface structure */
3389 int* cols, /**< columns to apply strong branching on */
3390 int ncols, /**< number of columns */
3391 SCIP_Real* psols, /**< current integral primal solution values of columns */
3392 int itlim, /**< iteration limit for strong branchings */
3393 SCIP_Real* down, /**< stores dual bounds after branching columns down */
3394 SCIP_Real* up, /**< stores dual bounds after branching columns up */
3395 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3396 * otherwise, they can only be used as an estimate values */
3397 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3398 * otherwise, they can only be used as an estimate values */
3399 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3400 )
3401{
3402 SCIP_RETCODE retcode;
3403
3404 assert( cols != NULL );
3405 assert( psols != NULL );
3406 assert( down != NULL );
3407 assert( up != NULL );
3408 assert( downvalid != NULL );
3409 assert( upvalid != NULL );
3410 assert( down != NULL );
3411
3412 if ( iter != NULL )
3413 *iter = 0;
3414
3415 for (int j = 0; j < ncols; ++j)
3416 {
3417 /* pass call on to lpiStrongbranch() */
3418 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3419
3420 /* pass SCIP_LPERROR to SCIP without a back trace */
3421 if( retcode == SCIP_LPERROR )
3422 return SCIP_LPERROR;
3423
3424 /* evaluate retcode */
3425 SCIP_CALL( retcode );
3426 }
3427
3428 return SCIP_OKAY;
3429}
3430/**@} */
3431
3432
3433
3434
3435/*
3436 * Solution Information Methods
3437 */
3438
3439/**@name Solution Information Methods */
3440/**@{ */
3441
3442/** returns whether a solve method was called after the last modification of the LP */
3444 SCIP_LPI* lpi /**< LP interface structure */
3445 )
3446{
3447 assert(lpi != NULL);
3448
3449 return lpi->solved;
3450}
3451
3452/** gets information about primal and dual feasibility of the current LP solution
3453 *
3454 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
3455 * returns true. If the LP is changed, this information might be invalidated.
3456 *
3457 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
3458 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
3459 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
3460 * the problem might actually be feasible).
3461 */
3463 SCIP_LPI* lpi, /**< LP interface structure */
3464 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
3465 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
3466 )
3467{
3468 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
3469
3470 assert(lpi != NULL);
3471 assert(primalfeasible != NULL);
3472 assert(dualfeasible != NULL);
3473
3474 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
3475 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
3476
3477 return SCIP_OKAY;
3478}
3479
3480/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
3481 * this does not necessarily mean, that the solver knows and can return the primal ray
3482 */
3484 SCIP_LPI* lpi /**< LP interface structure */
3485 )
3486{
3487 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
3488
3489 assert(lpi != NULL);
3490 assert(lpi->spx != NULL);
3491
3492 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3493}
3494
3495/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
3496 * and the solver knows and can return the primal ray
3497 */
3499 SCIP_LPI* lpi /**< LP interface structure */
3500 )
3501{
3502 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
3503
3504 assert(lpi != NULL);
3505 assert(lpi->spx != NULL);
3506
3507#if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3508 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3509#else
3510 return FALSE;
3511#endif
3512}
3513
3514/** returns TRUE iff LP is proven to be primal unbounded */
3516 SCIP_LPI* lpi /**< LP interface structure */
3517 )
3518{
3519 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
3520
3521 assert(lpi != NULL);
3522 assert(lpi->spx != NULL);
3523
3524 assert(lpi->spx->getStatus() != SPxSolver::UNBOUNDED || lpi->spx->basis().status() == SPxBasis::UNBOUNDED);
3525
3526 /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
3527 * feasible point; hence we have to check the perturbation
3528 */
3529 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED && !lpi->spx->isPerturbed());
3530}
3531
3532/** returns TRUE iff LP is proven to be primal infeasible */
3534 SCIP_LPI* lpi /**< LP interface structure */
3535 )
3536{
3537 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3538
3539 assert(lpi != NULL);
3540 assert(lpi->spx != NULL);
3541
3542 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3543}
3544
3545/** returns TRUE iff LP is proven to be primal feasible */
3547 SCIP_LPI* lpi /**< LP interface structure */
3548 )
3549{
3550 SPxBasis::SPxStatus basestatus;
3551
3552 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3553
3554 assert(lpi != NULL);
3555 assert(lpi->spx != NULL);
3556
3557 basestatus = lpi->spx->basis().status();
3558
3559 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3560 * still return true as long as perturbation plus violation is within tolerances
3561 */
3562 assert(basestatus == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3563
3564 return basestatus == SPxBasis::OPTIMAL ||
3565 ((basestatus == SPxBasis::PRIMAL || basestatus == SPxBasis::UNBOUNDED) && !lpi->spx->isPerturbed());
3566}
3567
3568/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3569 * this does not necessarily mean, that the solver knows and can return the dual ray
3570 */
3572 SCIP_LPI* lpi /**< LP interface structure */
3573 )
3574{
3575 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3576
3577 assert(lpi != NULL);
3578 assert(lpi->spx != NULL);
3579
3580 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3581}
3582
3583/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3584 * and the solver knows and can return the dual ray
3585 */
3587 SCIP_LPI* lpi /**< LP interface structure */
3588 )
3589{
3590 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3591
3592 assert(lpi != NULL);
3593 assert(lpi->spx != NULL);
3594
3595 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3596}
3597
3598/** returns TRUE iff LP is dual unbounded */
3600 SCIP_LPI* lpi /**< LP interface structure */
3601 )
3602{
3603 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3604
3605 assert(lpi != NULL);
3606 assert(lpi->spx != NULL);
3607
3608 return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE && lpi->spx->basis().status() == SPxBasis::DUAL
3609 && !lpi->spx->isPerturbed());
3610}
3611
3612/** returns TRUE iff LP is dual infeasible */
3614 SCIP_LPI* lpi /**< LP interface structure */
3615 )
3616{
3617 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3618
3619 assert(lpi != NULL);
3620 assert(lpi->spx != NULL);
3621
3622 return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3623}
3624
3625/** returns TRUE iff LP is proven to be dual feasible */
3627 SCIP_LPI* lpi /**< LP interface structure */
3628 )
3629{
3630 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3631
3632 assert(lpi != NULL);
3633 assert(lpi->spx != NULL);
3634
3635 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3636 * still return true as long as perturbation plus violation is within tolerances
3637 */
3638 assert(lpi->spx->basis().status() == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3639
3640 return (lpi->spx->basis().status() == SPxBasis::OPTIMAL) ||
3641 (lpi->spx->basis().status() == SPxBasis::DUAL && !lpi->spx->isPerturbed());
3642}
3643
3644/** returns TRUE iff LP was solved to optimality */
3646 SCIP_LPI* lpi /**< LP interface structure */
3647 )
3648{
3649 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3650
3651 assert(lpi != NULL);
3652 assert(lpi->spx != NULL);
3653 assert((lpi->spx->basis().status() == SPxBasis::OPTIMAL)
3655
3656 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3657 * still return true as long as perturbation plus violation is within tolerances
3658 */
3659 return (lpi->spx->basis().status() == SPxBasis::OPTIMAL);
3660}
3661
3662/** returns TRUE iff current LP solution is stable
3663 *
3664 * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3665 * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3666 * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3667 * SCIPlpiIsStable() should return false.
3668 */
3670 SCIP_LPI* lpi /**< LP interface structure */
3671 )
3672{
3673 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3674
3675 assert(lpi != NULL);
3676 assert(lpi->spx != NULL);
3677
3678#if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3679 /* If the condition number of the basis should be checked, everything above the specified threshold is counted
3680 * as instable.
3681 */
3682 if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3683 {
3684#ifndef NDEBUG
3685 SCIP_RETCODE retcode;
3686#endif
3687 SCIP_Real kappa;
3688
3689#ifndef NDEBUG
3690 retcode =
3691#endif
3693 assert(kappa != SCIP_INVALID); /*lint !e777*/
3694 assert(retcode == SCIP_OKAY);
3695
3696 if( kappa > lpi->conditionlimit )
3697 return FALSE;
3698 }
3699#endif
3700
3701 return (lpi->spx->getStatus() != SPxSolver::ERROR && lpi->spx->getStatus() != SPxSolver::SINGULAR);
3702}
3703
3704/** returns TRUE iff the objective limit was reached */
3706 SCIP_LPI* lpi /**< LP interface structure */
3707 )
3708{
3709 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3710
3711 assert(lpi != NULL);
3712 assert(lpi->spx != NULL);
3713
3714 return (lpi->spx->getStatus() == SPxSolver::ABORT_VALUE);
3715}
3716
3717/** returns TRUE iff the iteration limit was reached */
3719 SCIP_LPI* lpi /**< LP interface structure */
3720 )
3721{
3722 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3723
3724 assert(lpi != NULL);
3725 assert(lpi->spx != NULL);
3726
3727 return (lpi->spx->getStatus() == SPxSolver::ABORT_ITER);
3728}
3729
3730/** returns TRUE iff the time limit was reached */
3732 SCIP_LPI* lpi /**< LP interface structure */
3733 )
3734{
3735 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3736
3737 assert(lpi != NULL);
3738 assert(lpi->spx != NULL);
3739
3740 return (lpi->spx->getStatus() == SPxSolver::ABORT_TIME);
3741}
3742
3743/** returns the internal solution status of the solver */
3745 SCIP_LPI* lpi /**< LP interface structure */
3746 )
3747{
3748 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3749
3750 assert(lpi != NULL);
3751 assert(lpi->spx != NULL);
3752
3753 return static_cast<int>(lpi->spx->getStatus());
3754}
3755
3756/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3758 SCIP_LPI* lpi, /**< LP interface structure */
3759 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3760 )
3761{ /*lint --e{715}*/
3762 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3763
3764 assert(lpi != NULL);
3765 assert(lpi->spx != NULL);
3766 assert(success != NULL);
3767
3768 /* instable situations cannot be ignored */
3769 *success = FALSE;
3770
3771 return SCIP_OKAY;
3772}
3773
3774/** gets objective value of solution */
3776 SCIP_LPI* lpi, /**< LP interface structure */
3777 SCIP_Real* objval /**< stores the objective value */
3778 )
3779{
3780 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3781
3782 assert(lpi != NULL);
3783 assert(lpi->spx != NULL);
3784 assert(objval != NULL);
3785
3786 *objval = lpi->spx->value();
3787
3788 return SCIP_OKAY;
3789}
3790
3791/** gets primal and dual solution vectors for feasible LPs
3792 *
3793 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3794 * SCIPlpiIsOptimal() returns true.
3795 */
3797 SCIP_LPI* lpi, /**< LP interface structure */
3798 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3799 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3800 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3801 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3802 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3803 )
3804{
3805 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3806
3807 assert(lpi != NULL);
3808 assert(lpi->spx != NULL);
3809
3810 if( objval != NULL )
3811 *objval = lpi->spx->value();
3812
3813 try
3814 {
3815 if( primsol != NULL )
3816 {
3817 Vector tmp(lpi->spx->nCols(), primsol);
3818 (void)lpi->spx->getPrimal(tmp);
3819 }
3820 if( dualsol != NULL )
3821 {
3822 Vector tmp(lpi->spx->nRows(), dualsol);
3823 (void)lpi->spx->getDual(tmp);
3824 }
3825 if( activity != NULL )
3826 {
3827 Vector tmp(lpi->spx->nRows(), activity);
3828 (void)lpi->spx->getSlacks(tmp); /* in SoPlex, the activities are called "slacks" */
3829 }
3830 if( redcost != NULL )
3831 {
3832 Vector tmp(lpi->spx->nCols(), redcost);
3833 (void)lpi->spx->getRedCost(tmp);
3834 }
3835 }
3836#ifndef NDEBUG
3837 catch( const SPxException& x )
3838 {
3839 std::string s = x.what();
3840 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3841#else
3842 catch( const SPxException& )
3843 {
3844#endif
3845 return SCIP_LPERROR;
3846 }
3847
3848 return SCIP_OKAY;
3849}
3850
3851/** gets primal ray for unbounded LPs */
3853 SCIP_LPI* lpi, /**< LP interface structure */
3854 SCIP_Real* ray /**< primal ray */
3855 )
3856{ /*lint --e{715}*/
3857 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3858
3859 assert(lpi != NULL);
3860 assert(lpi->spx != NULL);
3861 assert(ray != NULL);
3862
3863#if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3864 try
3865 {
3866 Vector tmp(lpi->spx->nCols(), ray);
3867 (void)lpi->spx->getPrimalray(tmp);
3868 }
3869#ifndef NDEBUG
3870 catch( const SPxException& x )
3871 {
3872 std::string s = x.what();
3873 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3874#else
3875 catch( const SPxException& )
3876 {
3877#endif
3878 return SCIP_LPERROR;
3879 }
3880
3881 return SCIP_OKAY;
3882#else
3883 SCIPerrorMessage("SCIPlpiGetPrimalRay() not supported by SoPlex versions <= 1.5.0\n");
3884 return SCIP_LPERROR;
3885#endif
3886}
3887
3888/** gets dual farkas proof for infeasibility */
3890 SCIP_LPI* lpi, /**< LP interface structure */
3891 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3892 )
3893{
3894 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3895
3896 assert(lpi != NULL);
3897 assert(lpi->spx != NULL);
3898 assert(dualfarkas != NULL);
3899
3900 try
3901 {
3902 Vector tmp(lpi->spx->nRows(), dualfarkas);
3903 (void)lpi->spx->getDualfarkas(tmp);
3904 }
3905#ifndef NDEBUG
3906 catch( const SPxException& x )
3907 {
3908 std::string s = x.what();
3909 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3910#else
3911 catch( const SPxException& )
3912 {
3913#endif
3914 return SCIP_LPERROR;
3915 }
3916
3917 return SCIP_OKAY;
3918}
3919
3920/** gets the number of LP iterations of the last solve call */
3922 SCIP_LPI* lpi, /**< LP interface structure */
3923 int* iterations /**< pointer to store the number of iterations of the last solve call */
3924 )
3925{
3926 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3927
3928 assert(lpi != NULL);
3929 assert(lpi->spx != NULL);
3930 assert(iterations != NULL);
3931
3932 *iterations = lpi->spx->iterations();
3933
3934 return SCIP_OKAY;
3935}
3936
3937/** gets information about the quality of an LP solution
3938 *
3939 * Such information is usually only available, if also a (maybe not optimal) solution is available.
3940 * The LPI should return SCIP_INVALID for @p quality, if the requested quality is not available.
3941 */
3943 SCIP_LPI* lpi, /**< LP interface structure */
3944 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3945 SCIP_Real* quality /**< pointer to store quality number */
3946 )
3947{
3948 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3949
3950 assert(lpi != NULL);
3951 assert(quality != NULL);
3952
3953#if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3954 int maxiter;
3955 Real tolerance;
3956
3957 SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3958
3959 switch( qualityindicator )
3960 {
3962 maxiter = 20;
3963 tolerance = 1e-6;
3964 break;
3965
3967 maxiter = 10000;
3968 tolerance = 1e-9;
3969 break;
3970
3971 default:
3972 SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3973 return SCIP_INVALIDDATA;
3974 }
3975
3976 *quality = lpi->spx->basis().condition(maxiter, tolerance);
3977#else
3978 *quality = SCIP_INVALID;
3979#endif
3980 return SCIP_OKAY;
3981}
3982
3983/**@} */
3984
3985
3986
3987
3988/*
3989 * LP Basis Methods
3990 */
3991
3992/**@name LP Basis Methods */
3993/**@{ */
3994
3995/** Return reduced cost of column @c col if this is readily available, otherwise return 0.0 */
3996static
3997SCIP_RETCODE getRedCostEst(SPxSCIP* spx, int col, SCIP_Real* val)
3998{
3999 assert( spx != NULL );
4000 assert( val != NULL );
4001
4002 *val = 0.0;
4003
4004 /* Return if the vectors are not set up. The vectors are not set up if for instance we preformed
4005 * strong branching before. */
4006 if (! spx->isInitialized() )
4007 return SCIP_OKAY;
4008
4009 assert( 0 <= col && col < spx->nCols() );
4010
4011 if( spx->rep() == SPxSolver::COLUMN )
4012 {
4013 /* in column case the reduced costs are available: */
4014 if (spx->getSense() == SPxLP::MINIMIZE)
4015 *val = spx->pVec()[col] - spx->maxObj()[col];
4016 else
4017 *val = spx->maxObj()[col] - spx->pVec()[col];
4018 }
4019 else
4020 {
4021 assert( spx->rep() == SPxSolver::ROW );
4022
4023 /* In row case for computing the reduced costs one needs to pass through the basis. We skip this expensive part. */
4024#ifdef SCIP_DISABLED_CODE
4025 /* Here is the code necessary to compute the reduced costs for row representation: */
4026 SCIP_Real sign = 1.0;
4027 if ( spx->getSense() == SPxLP::MINIMIZE )
4028 sign = -1.0;
4029
4030 if ( spx->isColBasic(col) )
4031 {
4032 /* It seems necessary to search through the basis in order to find the correct position */
4033 for (int i = spx->dim() - 1; i >= 0; --i)
4034 {
4035 SPxId id = spx->basis().baseId(i);
4036 if ( id.isSPxColId() && col == spx->number(SPxColId(id)) )
4037 {
4038 *val = sign * spx->fVec()[i];
4039 break;
4040 }
4041 }
4042 }
4043#endif
4044 }
4045
4046 return SCIP_OKAY;
4047}
4048
4049
4050
4051/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
4053 SCIP_LPI* lpi, /**< LP interface structure */
4054 int* cstat, /**< array to store column basis status, or NULL */
4055 int* rstat /**< array to store row basis status, or NULL */
4056 )
4057{
4058 int i;
4059
4060 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
4061
4062 assert(lpi != NULL);
4063 assert(lpi->spx != NULL);
4064
4065 assert( lpi->spx->preStrongbranchingBasisFreed() );
4066
4067 if( rstat != NULL )
4068 {
4069 for( i = 0; i < lpi->spx->nRows(); ++i )
4070 {
4071 switch( lpi->spx->getBasisRowStatus(i) )
4072 {
4073 case SPxSolver::BASIC:
4074 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4075 break;
4076 case SPxSolver::FIXED:
4077 case SPxSolver::ON_LOWER:
4078 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4079 break;
4080 case SPxSolver::ON_UPPER:
4081 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4082 break;
4083 case SPxSolver::ZERO:
4084 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4085 return SCIP_LPERROR;
4086 case SPxSolver::UNDEFINED:
4087 default:
4088 SCIPerrorMessage("invalid basis status\n");
4089 SCIPABORT();
4090 return SCIP_INVALIDDATA; /*lint !e527*/
4091 }
4092 }
4093 }
4094
4095 if( cstat != NULL )
4096 {
4097 for( i = 0; i < lpi->spx->nCols(); ++i )
4098 {
4099 SCIP_Real val = 0.0;
4100 switch( lpi->spx->getBasisColStatus(i) )
4101 {
4102 case SPxSolver::BASIC:
4103 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4104 break;
4105 case SPxSolver::FIXED:
4106 /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
4107 * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
4108 * this case there is no problem at all. If the basis is saved and/or used in some other
4109 * solver, it usually is very cheap to perform the pivots necessary to get an optimal
4110 * basis. */
4111 SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
4112 if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
4113 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4114 else
4115 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4116 break;
4117 case SPxSolver::ON_LOWER:
4118 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4119 break;
4120 case SPxSolver::ON_UPPER:
4121 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4122 break;
4123 case SPxSolver::ZERO:
4124 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
4125 break;
4126 case SPxSolver::UNDEFINED:
4127 default:
4128 SCIPerrorMessage("invalid basis status\n");
4129 SCIPABORT();
4130 return SCIP_INVALIDDATA; /*lint !e527*/
4131 }
4132 }
4133 }
4134
4135 return SCIP_OKAY;
4136}
4137
4138/** sets current basis status for columns and rows */
4140 SCIP_LPI* lpi, /**< LP interface structure */
4141 const int* cstat, /**< array with column basis status */
4142 const int* rstat /**< array with row basis status */
4143 )
4144{
4145 int i;
4146 int ncols;
4147 int nrows;
4148
4149 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
4150
4151 assert(lpi != NULL);
4152 assert(lpi->spx != NULL);
4153
4154 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
4155 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
4156
4157 assert(cstat != NULL || ncols == 0);
4158 assert(rstat != NULL || nrows == 0);
4159
4160 assert( lpi->spx->preStrongbranchingBasisFreed() );
4161 invalidateSolution(lpi);
4162
4163 DataArray<SPxSolver::VarStatus>& m_colstat = lpi->spx->colStat();
4164 DataArray<SPxSolver::VarStatus>& m_rowstat = lpi->spx->rowStat();
4165
4166 m_colstat.reSize(ncols);
4167 m_rowstat.reSize(nrows);
4168
4169 for( i = 0; i < nrows; ++i )
4170 {
4171 assert( rstat != 0 ); /* for lint */
4172 switch( rstat[i] )
4173 {
4175 m_rowstat[i] = SPxSolver::ON_LOWER;
4176 break;
4178 m_rowstat[i] = SPxSolver::BASIC;
4179 break;
4181 m_rowstat[i] = SPxSolver::ON_UPPER;
4182 break;
4183 case SCIP_BASESTAT_ZERO:
4184 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4185 return SCIP_LPERROR; /*lint !e429*/
4186 default:
4187 SCIPerrorMessage("invalid basis status\n");
4188 SCIPABORT();
4189 return SCIP_INVALIDDATA; /*lint !e527*/
4190 }
4191 }
4192
4193 for( i = 0; i < ncols; ++i )
4194 {
4195 assert( cstat != 0 ); /* for lint */
4196 switch( cstat[i] )
4197 {
4199 m_colstat[i] = SPxSolver::ON_LOWER;
4200 break;
4202 m_colstat[i] = SPxSolver::BASIC;
4203 break;
4205 m_colstat[i] = SPxSolver::ON_UPPER;
4206 break;
4207 case SCIP_BASESTAT_ZERO:
4208 m_colstat[i] = SPxSolver::ZERO;
4209 break;
4210 default:
4211 SCIPerrorMessage("invalid basis status\n");
4212 SCIPABORT();
4213 return SCIP_INVALIDDATA; /*lint !e527*/
4214 }
4215 }
4216
4217 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(m_rowstat.get_const_ptr(), m_colstat.get_const_ptr()) );
4218 (void) lpi->spx->updateStatus();
4219
4220 lpi->spx->freePreStrongbranchingBasis();
4221
4222 return SCIP_OKAY;
4223}
4224
4225/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
4227 SCIP_LPI* lpi, /**< LP interface structure */
4228 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
4229 )
4230{
4231 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
4232
4233 SPxSolver* spx;
4234
4235 assert(lpi != NULL);
4236 assert(lpi->spx != NULL);
4237 assert(bind != NULL);
4238
4239 assert( lpi->spx->preStrongbranchingBasisFreed() );
4240
4241 /* the LPi defines the basis as column basis, i.e., as the set of (indices of) non-fixed columns and rows; if SoPlex
4242 * uses row representation, this is just the complement of the basis
4243 */
4244 spx = lpi->spx;
4245
4246 /* for column representation, return the basis */
4247 if( spx->rep() == SPxSolver::COLUMN )
4248 {
4249 for( int i = 0; i < spx->nRows(); ++i )
4250 {
4251 SPxId id = spx->basis().baseId(i);
4252
4253 bind[i] = (id.isSPxColId() ? spx->number(id) : - 1 - spx->number(id));
4254 }
4255 }
4256 /* for row representation, return the complement of the basis; for this, we need to loop through all rows and columns */
4257 else
4258 {
4259 int k = 0;
4260 int nrows = spx->nRows();
4261 int ncols = spx->nCols();
4262
4263 assert( spx->rep() == SPxSolver::ROW );
4264
4265 for( int i = 0; i < nrows; ++i )
4266 {
4267 if( !spx->isRowBasic(i) )
4268 {
4269 bind[k++] = -1 - i;
4270 if( k >= nrows )
4271 break;
4272 }
4273 }
4274
4275 for( int j = 0; j < ncols && k < nrows; ++j )
4276 {
4277 if( !spx->isColBasic(j) )
4278 bind[k++] = j;
4279 }
4280
4281 assert(k == nrows);
4282 }
4283
4284 return SCIP_OKAY;
4285}
4286
4287#ifdef OLD_BINV
4288/* prepare a factorization of the basis matrix in column representation */
4289static
4290SCIP_RETCODE prepareFactorization(
4291 SCIP_LPI* lpi
4292 )
4293{
4294 SCIPdebugMessage("Preparing factorization for computation of basis inverse.\n");
4295
4296 try
4297 {
4298 /* if the factorization has not been set up, we compute a new factorization */
4299 if ( lpi->factorization == 0 )
4300 {
4301 SPxSolver* spx = lpi->spx;
4302
4303 /* matrix to store columns */
4304 DataArray <const SVector*> matrix(spx->nRows());
4305
4306 int k = 0;
4307 for (int i = 0; i < spx->nRows(); ++i)
4308 {
4309 if ( ! spx->isRowBasic(i) )
4310 matrix[k++] = new UnitVector(i);
4311 }
4312 for (int j = 0; j < spx->nCols(); ++j)
4313 {
4314 if ( ! spx->isColBasic(j) )
4315 matrix[k++] = &spx->colVector(j);
4316 }
4317 assert( k == spx->nRows() );
4318 assert( k == matrix.size() );
4319
4320 /* compute factorization */
4321 lpi->factorization = new SLUFactor;
4322#ifndef NDEBUG
4323 SLinSolver::Status status = lpi->factorization->load(matrix.get_ptr(), k);
4324#else
4325 (void) lpi->factorization->load(matrix.get_ptr(), k);
4326#endif
4327 assert( status == SLinSolver::OK );
4328 assert( k == lpi->factorization->dim() );
4329
4330 /* delete matrix columns corresponding to unit vectors */
4331 k = 0;
4332 for (int i = 0; i < spx->nRows(); ++i)
4333 {
4334 if ( ! spx->isRowBasic(i) )
4335 delete matrix[k++];
4336 }
4337 }
4338 }
4339#ifndef NDEBUG
4340 catch( const SPxException& x )
4341 {
4342 std::string s = x.what();
4343 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4344#else
4345 catch( const SPxException& )
4346 {
4347#endif
4348 return SCIP_LPERROR;
4349 }
4350
4351 return SCIP_OKAY;
4352}
4353#endif
4354
4355/** get row of inverse basis matrix B^-1
4356 *
4357 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4358 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4359 * see also the explanation in lpi.h.
4360 */
4362 SCIP_LPI* lpi, /**< LP interface structure */
4363 int r, /**< row number */
4364 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
4365 int* inds, /**< array to store the non-zero indices, or NULL */
4366 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4367 * (-1: if we do not store sparsity information) */
4368 )
4369{
4370 SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
4371
4372 assert( lpi != NULL );
4373 assert( lpi->spx != NULL );
4374 assert( lpi->spx->preStrongbranchingBasisFreed() );
4375 assert(coef != NULL);
4376
4377 int nCols = lpi->spx->nCols();
4378 int nRows = lpi->spx->nRows();
4379
4380 assert(r >= 0);
4381 assert(r < nRows);
4382
4383 try
4384 {
4385 SPxSolver* spx = lpi->spx;
4386
4387 /* in the column case use the existing factorization */
4388 if ( spx->rep() == SPxSolver::COLUMN )
4389 {
4390 SSVector x(nRows);
4391 spx->basis().coSolve(x, spx->unitVector(r));
4392
4393 /* copy sparse data to dense result vector based on coef array */
4394 if( ninds != NULL && inds != NULL )
4395 {
4396 int idx;
4397 /* during solving SoPlex may have destroyed the sparsity structure so we need to restore it */
4398 x.setup();
4399 *ninds = x.size();
4400 for( int i = 0; i < *ninds; ++i )
4401 {
4402 idx = x.index(i);
4403 coef[idx] = x[idx];
4404 /* set sparsity pattern of coef array */
4405 inds[i] = idx;
4406 }
4407 }
4408 else
4409 {
4410 /* @todo check whether we only need to copy nonzeros to coef - is coef cleared? */
4411 Vector y(nRows, coef);
4412 y = x;
4413 if( ninds != NULL )
4414 *ninds = -1;
4415 }
4416 }
4417 else
4418 {
4419 assert(spx->rep() == SPxSolver::ROW);
4420
4421#ifdef OLD_BINV
4422 DVector e(nRows);
4423
4424 /* prepare unit vector */
4425 e.clear();
4426 e[r] = 1.0;
4427
4428 /* factorization is deleted in invalidateSolution() */
4429 SCIP_CALL( prepareFactorization(lpi) );
4430 assert( lpi->factorization != 0 );
4431 assert( lpi->factorization->dim() == nRows );
4432
4433 /* solve system "x = e_r^T * B^-1" to get r'th row of B^-1 */
4434 lpi->factorization->solveLeft(x, e);
4435#else
4436 Vector x(nRows, coef); /* row of B^-1 has nrows entries - note that x is based on coef */
4437 /**@todo should rhs be a reference? */
4438 DSVector rhs(nCols);
4439 SSVector y(nCols);
4440 int* bind;
4441 int idx;
4442
4443 bind = NULL;
4444
4445 /**@todo should bind be stored globally in lpi? */
4446 /* get ordering of column basis matrix */
4447 SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4448 SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4449
4450 /* get vector corresponding to requested index r */
4451 idx = bind[r];
4452
4453 /* r corresponds to a row vector */
4454 if( idx < 0 )
4455 {
4456 idx = -idx-1;
4457
4458 /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4459 assert(idx >= 0);
4460 assert(idx < nRows);
4461 assert(!spx->isRowBasic(idx));
4462
4463 /* get row vector */
4464 rhs = spx->rowVector(idx);
4465 rhs *= -1.0;
4466 }
4467 /* r corresponds to a column vector */
4468 else
4469 {
4470 /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4471 assert(idx < nCols);
4472 assert(!spx->isColBasic(idx));
4473
4474 /* get unit vector */
4475 rhs = spx->unitVector(idx);
4476 }
4477
4478 /* solve system "y B = rhs", where B is the row basis matrix */
4479 spx->basis().solve(y, rhs);
4480
4481 /* initialize result vector x as zero */
4482 BMSclearMemoryArray(coef, nRows);
4483
4484 /* add nonzero entries */
4485 for( int i = 0; i < nCols; ++i )
4486 {
4487 SPxId id = spx->basis().baseId(i);
4488
4489 if( id.isSPxRowId() )
4490 {
4491 assert(spx->number(id) >= 0);
4492 assert(spx->number(id) < nRows);
4493 assert(bind[r] >= 0 || spx->number(id) != idx);
4494
4495 x[spx->number(id)] = y[i];
4496 }
4497 }
4498
4499 /* if r corresponds to a row vector, we have to add a 1 at position r */
4500 if( bind[r] < 0 )
4501 {
4502 assert(x[idx] == 0.0);
4503 x[idx] = 1.0;
4504 }
4505
4506 /* @todo implement returning of sparsity information like in column wise case */
4507 if( ninds != NULL )
4508 *ninds = -1;
4509
4510 /* free memory */
4511 BMSfreeMemoryArray(&bind);
4512#endif
4513 }
4514 }
4515#ifndef NDEBUG
4516 catch( const SPxException& x )
4517 {
4518 std::string s = x.what();
4519 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4520#else
4521 catch( const SPxException& )
4522 {
4523#endif
4524 return SCIP_LPERROR;
4525 }
4526
4527 return SCIP_OKAY;
4528}
4529
4530/** get solution of basis matrix B * coef = rhs */
4531static
4533 SCIP_LPI* lpi, /**< LP interface structure */
4534 SCIP_Real* rhs, /**< right-hand side vector */
4535 SCIP_Real* coef /**< vector to return coefficients */
4536 )
4537{
4538 SCIPdebugMessage("calling SCIPlpiGetBInvVec()\n");
4539
4540 assert(lpi != NULL);
4541 assert(lpi->spx != NULL);
4542 assert(lpi->spx->preStrongbranchingBasisFreed());
4543 assert(rhs != NULL);
4544 assert(coef != NULL);
4545
4546 int nCols = lpi->spx->nCols();
4547 int nRows = lpi->spx->nRows();
4548
4549 try
4550 {
4551 SPxSolver* spx = lpi->spx;
4552 Vector v(nRows, rhs);
4553 Vector x(nRows, coef);
4554
4555 /* in the column case use the existing factorization */
4556 if( spx->rep() == SPxSolver::COLUMN )
4557 {
4558 /* solve system "x = B^-1 * A_c" to get c'th column of B^-1 * A */
4559 spx->basis().solve(x, v);
4560 }
4561 else
4562 {
4563 assert(spx->rep() == SPxSolver::ROW);
4564
4565#ifdef OLD_BINV
4566 /* factorization is deleted in invalidateSolution() */
4567 SCIP_CALL( prepareFactorization(lpi) );
4568 assert(lpi->factorization != 0);
4569 assert(lpi->factorization->dim() == spx->nRows());
4570
4571 /* solve system B * x = v */
4572 lpi->factorization->solveRight(x, v);
4573#else
4574 DSVector rowrhs(nCols);
4575 SSVector y(nCols);
4576 int* bind;
4577
4578 bind = NULL;
4579
4580 /**@todo should bind be stored globally in lpi? */
4581 /* get ordering of column basis matrix */
4582 SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4583 SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4584
4585 /* fill right-hand side for row-based system */
4586 for( int i = 0; i < nCols; ++i )
4587 {
4588 SPxId id = spx->basis().baseId(i);
4589
4590 if( id.isSPxRowId() )
4591 {
4592 assert(spx->number(id) >= 0);
4593 assert(spx->number(id) < nRows);
4594
4595 rowrhs.add(i, v[spx->number(id)]);
4596 }
4597 else
4598 {
4599 assert(rowrhs[i] == 0.0);
4600 }
4601 }
4602
4603 /* solve system "B y = rowrhs", where B is the row basis matrix */
4604 spx->basis().coSolve(y, rowrhs);
4605
4606 /* fill result w.r.t. order given by bind */
4607 for( int i = 0; i < nRows; ++i )
4608 {
4609 int idx;
4610
4611 idx = bind[i];
4612
4613 if( idx < 0 )
4614 {
4615 idx = -idx-1;
4616
4617 /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4618 assert(idx >= 0);
4619 assert(idx < nRows);
4620 assert(!spx->isRowBasic(idx));
4621
4622 x[i] = v[idx] - (spx->rowVector(idx) * Vector(nCols, y.get_ptr())); /*lint !e1702*/
4623 }
4624 else
4625 {
4626 /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4627 assert(idx >= 0);
4628 assert(idx < nCols);
4629 assert(!spx->isColBasic(idx));
4630
4631 x[i] = y[idx];
4632 }
4633 }
4634
4635 /* free memory */
4636 BMSfreeMemoryArray(&bind);
4637#endif
4638 }
4639 }
4640#ifndef NDEBUG
4641 catch( const SPxException& x )
4642 {
4643 std::string s = x.what();
4644 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4645#else
4646 catch( const SPxException& )
4647 {
4648#endif
4649 return SCIP_LPERROR;
4650 }
4651
4652 return SCIP_OKAY;
4653}
4654
4655/** get column of inverse basis matrix B^-1
4656 *
4657 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4658 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4659 * see also the explanation in lpi.h.
4660 */
4662 SCIP_LPI* lpi, /**< LP interface structure */
4663 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
4664 * you have to call SCIPlpiGetBasisInd() to get the array which links the
4665 * B^-1 column numbers to the row and column numbers of the LP!
4666 * c must be between 0 and nrows-1, since the basis has the size
4667 * nrows * nrows */
4668 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
4669 int* inds, /**< array to store the non-zero indices, or NULL */
4670 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4671 * (-1: if we do not store sparsity information) */
4672 )
4673{ /*lint --e{715}*/
4674 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
4675
4676 assert( lpi != NULL );
4677 assert( lpi->spx != NULL );
4678 assert( lpi->spx->preStrongbranchingBasisFreed() );
4679 assert(coef != NULL);
4680
4681 /* mark sparsity pattern as invalid */
4682 if( ninds != NULL )
4683 *ninds = -1;
4684
4685 /* prepare unit vector */
4686 DVector e(lpi->spx->nRows());
4687
4688 e.clear();
4689
4690 assert(c >= 0);
4691 assert(c < lpi->spx->nRows());
4692 e[c] = 1.0;
4693
4694 /* solve */
4695 SCIP_CALL( lpiGetBInvVec(lpi, e.get_ptr(), coef) );
4696
4697 return SCIP_OKAY;
4698}
4699
4700/** get row of inverse basis matrix times constraint matrix B^-1 * A
4701 *
4702 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4703 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4704 * see also the explanation in lpi.h.
4705 */
4707 SCIP_LPI* lpi, /**< LP interface structure */
4708 int r, /**< row number */
4709 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
4710 SCIP_Real* coef, /**< vector to return coefficients of the row */
4711 int* inds, /**< array to store the non-zero indices, or NULL */
4712 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4713 * (-1: if we do not store sparsity information) */
4714 )
4715{
4716 SCIP_Real* buf;
4717 SCIP_Real* binv;
4718 int nrows;
4719 int ncols;
4720 int c;
4721
4722 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
4723
4724 assert(lpi != NULL);
4725 assert(lpi->spx != NULL);
4726 assert( lpi->spx->preStrongbranchingBasisFreed() );
4727 assert(coef != NULL);
4728
4729 nrows = lpi->spx->nRows();
4730 ncols = lpi->spx->nCols();
4731 buf = NULL;
4732
4733 /* get (or calculate) the row in B^-1 */
4734 if( binvrow == NULL )
4735 {
4736 SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
4737 SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
4738 binv = buf;
4739 }
4740 else
4741 binv = const_cast<SCIP_Real*>(binvrow);
4742
4743 assert(binv != NULL);
4744
4745 /* mark sparsity pattern as invalid */
4746 if( ninds != NULL )
4747 *ninds = -1;
4748
4749 /* calculate the scalar product of the row in B^-1 and A */
4750 soplex::Vector binvvec(nrows, binv);
4751 for( c = 0; c < ncols; ++c )
4752 coef[c] = binvvec * lpi->spx->colVector(c); /* scalar product */ /*lint !e1702*/
4753
4754 /* free memory if it was temporarily allocated */
4756
4757 return SCIP_OKAY;
4758}
4759
4760/** get column of inverse basis matrix times constraint matrix B^-1 * A
4761 *
4762 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4763 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4764 * see also the explanation in lpi.h.
4765 */
4767 SCIP_LPI* lpi, /**< LP interface structure */
4768 int c, /**< column number */
4769 SCIP_Real* coef, /**< vector to return coefficients of the column */
4770 int* inds, /**< array to store the non-zero indices, or NULL */
4771 int* ninds /**< pointer to store the number of non-zero indices, or NULL
4772 * (-1: if we do not store sparsity information) */
4773 )
4774{ /*lint --e{715}*/
4775 DVector col(lpi->spx->nRows());
4776
4777 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
4778
4779 assert( lpi != NULL );
4780 assert( lpi->spx != NULL );
4781 assert( lpi->spx->preStrongbranchingBasisFreed() );
4782 assert(coef != NULL);
4783
4784 /* extract column c of A */
4785 assert(c >= 0);
4786 assert(c < lpi->spx->nCols());
4787
4788 /* mark sparsity pattern as invalid */
4789 if( ninds != NULL )
4790 *ninds = -1;
4791
4792 col.clear();
4793 col = lpi->spx->colVector(c);
4794 col.reDim(lpi->spx->nRows());
4795
4796 /* solve */
4797 SCIP_CALL( lpiGetBInvVec(lpi, col.get_ptr(), coef) );
4798
4799 return SCIP_OKAY;
4800}
4801
4802/**@} */
4803
4804
4805
4806
4807/*
4808 * LP State Methods
4809 */
4810
4811/**@name LP State Methods */
4812/**@{ */
4813
4814/** stores LPi state (like basis information) into lpistate object */
4816 SCIP_LPI* lpi, /**< LP interface structure */
4817 BMS_BLKMEM* blkmem, /**< block memory */
4818 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4819 )
4820{
4821 int ncols;
4822 int nrows;
4823
4824 SCIPdebugMessage("calling SCIPlpiGetState()\n");
4825
4826 assert(blkmem != NULL);
4827 assert(lpi != NULL);
4828 assert(lpi->spx != NULL);
4829 assert(lpistate != NULL);
4830
4831 assert( lpi->spx->preStrongbranchingBasisFreed() );
4832
4833 ncols = lpi->spx->nCols();
4834 nrows = lpi->spx->nRows();
4835 assert(ncols >= 0);
4836 assert(nrows >= 0);
4837
4838 /* allocate lpistate data */
4839 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
4840
4841 /* allocate enough memory for storing uncompressed basis information */
4842 SCIP_CALL( ensureCstatMem(lpi, ncols) );
4843 SCIP_CALL( ensureRstatMem(lpi, nrows) );
4844
4845 /* get unpacked basis information */
4846 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
4847
4848 /* pack LPi state data */
4849 (*lpistate)->ncols = ncols;
4850 (*lpistate)->nrows = nrows;
4851 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
4852
4853 return SCIP_OKAY;
4854}
4855
4856/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
4857 * columns and rows since the state was stored with SCIPlpiGetState()
4858 */
4860 SCIP_LPI* lpi, /**< LP interface structure */
4861 BMS_BLKMEM* /*blkmem*/, /**< block memory */
4862 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
4863 )
4864{
4865 int lpncols;
4866 int lpnrows;
4867 int i;
4868
4869 SCIPdebugMessage("calling SCIPlpiSetState()\n");
4870
4871 assert(lpi != NULL);
4872 assert(lpi->spx != NULL);
4873 assert(lpistate != NULL);
4874 /* assert(blkmem != NULL); */
4875
4876 assert( lpi->spx->preStrongbranchingBasisFreed() );
4877
4878 lpncols = lpi->spx->nCols();
4879 lpnrows = lpi->spx->nRows();
4880 assert(lpistate->ncols <= lpncols);
4881 assert(lpistate->nrows <= lpnrows);
4882
4883 /* allocate enough memory for storing uncompressed basis information */
4884 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
4885 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
4886
4887 /* unpack LPi state data */
4888 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
4889
4890 /* extend the basis to the current LP beyond the previously existing columns */
4891 for( i = lpistate->ncols; i < lpncols; ++i )
4892 {
4893 SCIP_Real bnd = lpi->spx->lower(i);
4894 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4895 {
4896 /* if lower bound is +/- infinity -> try upper bound */
4897 bnd = lpi->spx->lower(i);
4898 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4899 lpi->cstat[i] = (int) SCIP_BASESTAT_ZERO; /* variable is free */
4900 else
4901 lpi->cstat[i] = (int) SCIP_BASESTAT_UPPER; /* use finite upper bound */
4902 }
4903 else
4904 lpi->cstat[i] = (int) SCIP_BASESTAT_LOWER; /* use finite lower bound */
4905 }
4906 for( i = lpistate->nrows; i < lpnrows; ++i )
4907 lpi->rstat[i] = (int) SCIP_BASESTAT_BASIC; /*lint !e641*/
4908
4909 /* load basis information */
4910 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4911
4912 return SCIP_OKAY;
4913}
4914
4915/** clears current LPi state (like basis information) of the solver */
4917 SCIP_LPI* lpi /**< LP interface structure */
4918 )
4919{ /*lint --e{715}*/
4920 SCIPdebugMessage("calling SCIPlpiClearState()\n");
4921
4922 assert(lpi != NULL);
4923 assert(lpi->spx != NULL);
4924
4925 try
4926 {
4927 lpi->spx->reLoad();
4928 }
4929#ifndef NDEBUG
4930 catch( const SPxException& x )
4931 {
4932 std::string s = x.what();
4933 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4934#else
4935 catch( const SPxException& )
4936 {
4937#endif
4938 assert( lpi->spx->getStatus() != SPxSolver::OPTIMAL );
4939 return SCIP_LPERROR;
4940 }
4941
4942 return SCIP_OKAY;
4943}
4944
4945/** frees LPi state information */
4947 SCIP_LPI* lpi, /**< LP interface structure */
4948 BMS_BLKMEM* blkmem, /**< block memory */
4949 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4950 )
4951{ /*lint --e{715}*/
4952 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4953
4954 assert(lpi != NULL);
4955 assert(lpistate != NULL);
4956 assert(blkmem != NULL);
4957
4958 if ( *lpistate != NULL )
4959 lpistateFree(lpistate, blkmem);
4960
4961 return SCIP_OKAY;
4962}
4963
4964/** checks, whether the given LP state contains simplex basis information */
4966 SCIP_LPI* lpi, /**< LP interface structure */
4967 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4968 )
4969{ /*lint --e{715}*/
4970 assert(lpi != NULL);
4971 return TRUE;
4972}
4973
4974/** reads LP state (like basis information from a file */
4976 SCIP_LPI* lpi, /**< LP interface structure */
4977 const char* fname /**< file name */
4978 )
4979{
4980 SCIPdebugMessage("calling SCIPlpiReadState()\n");
4981 assert(lpi != NULL);
4982 assert(lpi->spx != NULL);
4983 assert(fname != NULL);
4984
4985 assert( lpi->spx->preStrongbranchingBasisFreed() );
4986
4987 bool success;
4988 SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4989
4990 return success ? SCIP_OKAY : SCIP_LPERROR;
4991}
4992
4993/** writes LPi state (i.e. basis information) to a file */
4995 SCIP_LPI* lpi, /**< LP interface structure */
4996 const char* fname /**< file name */
4997 )
4998{
4999 assert(lpi != NULL);
5000 assert(lpi->spx != NULL);
5001 assert(fname != NULL);
5002 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
5003
5004 assert( lpi->spx->preStrongbranchingBasisFreed() );
5005
5006 bool res;
5007 SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
5008
5009 if ( ! res )
5010 return SCIP_LPERROR;
5011
5012 return SCIP_OKAY;
5013}
5014
5015/**@} */
5016
5017
5018
5019
5020/*
5021 * LP Pricing Norms Methods
5022 */
5023
5024/**@name LP Pricing Norms Methods */
5025/**@{ */
5026
5027/** stores LPi pricing norms information
5028 * @todo should we store norm information?
5029 */
5031 SCIP_LPI* lpi, /**< LP interface structure */
5032 BMS_BLKMEM* blkmem, /**< block memory */
5033 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
5034 )
5035{
5036#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5037 int nrows;
5038 int ncols;
5039
5040 assert(blkmem != NULL);
5041 assert(lpi != NULL);
5042 assert(lpi->spx != NULL);
5043 assert(lpinorms != NULL);
5044
5045 lpi->spx->getNdualNorms(nrows, ncols);
5046
5047 if( nrows == 0 && ncols == 0)
5048 {
5049 (*lpinorms = NULL);
5050 return SCIP_OKAY;
5051 }
5052
5053 /* allocate lpinorms data */
5054 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
5055 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
5056 (*lpinorms)->nrows = 0;
5057 (*lpinorms)->ncols = 0;
5058
5059 SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
5060
5061 if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
5062 {
5063 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5064 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
5065 BMSfreeBlockMemory(blkmem, lpinorms);
5066 assert(*lpinorms == NULL);
5067 }
5068#ifndef NDEBUG
5069 else
5070 {
5071 assert(nrows == (*lpinorms)->nrows);
5072 assert(ncols == (*lpinorms)->ncols);
5073 }
5074#endif
5075#else
5076 (*lpinorms) = NULL;
5077#endif
5078
5079 return SCIP_OKAY;
5080}
5081
5082/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
5083 * columns and rows since the state was stored with SCIPlpiGetNorms()
5084 */
5086 SCIP_LPI* lpi, /**< LP interface structure */
5087 BMS_BLKMEM* blkmem, /**< block memory */
5088 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
5089 )
5090{
5091#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5092 assert(blkmem != NULL);
5093 assert(lpi != NULL);
5094 assert(lpi->spx != NULL);
5095
5096 /* if there was no pricing norms information available, the LPi norms were not stored */
5097 if( lpinorms == NULL )
5098 return SCIP_OKAY;
5099
5100 assert(lpinorms->nrows <= lpi->spx->nRows());
5101 assert(lpinorms->ncols <= lpi->spx->nCols());
5102
5103 if( lpinorms->nrows == 0 )
5104 return SCIP_OKAY;
5105
5106 SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
5107 (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->nRows(), lpi->spx->nCols());
5108
5109 if( !lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms) )
5110 SCIPdebugMessage("loading of LPi norms failed\n");
5111#endif
5112
5113 return SCIP_OKAY;
5114}
5115
5116/** frees pricing norms information */
5118 SCIP_LPI* lpi, /**< LP interface structure */
5119 BMS_BLKMEM* blkmem, /**< block memory */
5120 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
5121 )
5122{
5123#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5124 assert(lpi != NULL);
5125 assert(lpinorms != NULL);
5126
5127 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5128
5129 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
5130 BMSfreeBlockMemory(blkmem, lpinorms);
5131 assert(*lpinorms == NULL);
5132#endif
5133
5134 return SCIP_OKAY;
5135}
5136
5137/**@} */
5138
5139
5140
5141
5142/*
5143 * Parameter Methods
5144 */
5145
5146/**@name Parameter Methods */
5147/**@{ */
5148
5149/** gets integer parameter of LP */
5151 SCIP_LPI* lpi, /**< LP interface structure */
5152 SCIP_LPPARAM type, /**< parameter number */
5153 int* ival /**< buffer to store the parameter value */
5154 )
5155{
5156 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
5157
5158 assert(lpi != NULL);
5159 assert(lpi->spx != NULL);
5160 assert(ival != NULL);
5161
5162 switch( type )
5163 {
5165 *ival = lpi->spx->getFromScratch();
5166 break;
5167 case SCIP_LPPAR_LPINFO:
5168 *ival = lpi->spx->getLpInfo();
5169 break;
5170 case SCIP_LPPAR_LPITLIM:
5171 *ival = lpi->spx->getIterationLimit();
5172 if( *ival == -1 )
5173 *ival = INT_MAX;
5174 break;
5176 *ival = lpi->spx->getPresolving();
5177 break;
5178 case SCIP_LPPAR_PRICING:
5179 *ival = (int)lpi->pricing;
5180 break;
5181 case SCIP_LPPAR_SCALING:
5182 *ival = lpi->spx->getScaling();
5183 break;
5184#if SOPLEX_VERSION >= 201
5185 case SCIP_LPPAR_TIMING:
5186 *ival = (int) lpi->spx->getTiming();
5187 break;
5188#endif
5189#if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
5191 *ival = (int) lpi->spx->random.getSeed();
5192 break;
5193#endif
5194 default:
5195 return SCIP_PARAMETERUNKNOWN;
5196 } /*lint !e788*/
5197
5198 return SCIP_OKAY;
5199}
5200
5201/** sets integer parameter of LP */
5203 SCIP_LPI* lpi, /**< LP interface structure */
5204 SCIP_LPPARAM type, /**< parameter number */
5205 int ival /**< parameter value */
5206 )
5207{
5208 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
5209
5210 assert(lpi != NULL);
5211 assert(lpi->spx != NULL);
5212
5213 switch( type )
5214 {
5216 assert(ival == TRUE || ival == FALSE);
5217 lpi->spx->setFromScratch(bool(ival));
5218 break;
5219 case SCIP_LPPAR_LPINFO:
5220 assert(ival == TRUE || ival == FALSE);
5221 lpi->spx->setLpInfo(bool(ival));
5222 break;
5223 case SCIP_LPPAR_LPITLIM:
5224 assert( ival >= 0 );
5225 /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
5226 if( ival >= INT_MAX )
5227 ival = -1;
5228 lpi->spx->setIterationLimit(ival);
5229 break;
5231 assert(ival == TRUE || ival == FALSE);
5232 lpi->spx->setPresolving(bool(ival));
5233 break;
5234 case SCIP_LPPAR_PRICING:
5235 lpi->pricing = (SCIP_PRICING)ival;
5236 switch( lpi->pricing )
5237 {
5239 case SCIP_PRICING_AUTO:
5240 lpi->spx->setAutoPricer();
5241 break;
5242 case SCIP_PRICING_FULL:
5243 lpi->spx->setFullPricer();
5244 break;
5246 lpi->spx->setParmultPricer();
5247 break;
5248 case SCIP_PRICING_STEEP:
5249 lpi->spx->setSteepPricer();
5250 break;
5252 lpi->spx->setSteepQStartPricer();
5253 break;
5254 case SCIP_PRICING_DEVEX:
5255 lpi->spx->setDevexPricer();
5256 break;
5257 default:
5258 return SCIP_LPERROR;
5259 }
5260 break;
5261 case SCIP_LPPAR_SCALING:
5262 assert(ival == TRUE || ival == FALSE);
5263 lpi->spx->setScaling(ival);
5264 break;
5265#if SOPLEX_VERSION >= 201
5266 case SCIP_LPPAR_TIMING:
5267 assert(ival >= 0 && ival < 3);
5268 lpi->spx->setTiming((Timer::TYPE) ival);
5269 break;
5270#endif
5271#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 2)
5273 lpi->spx->random.setSeed((unsigned int) ival);
5274 break;
5275#endif
5276#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
5278 assert(ival >= 0 && ival < 3);
5279 lpi->spx->setSolutionPolishing((SPxSolver::SolutionPolish) ival);
5280 break;
5281#endif
5282
5283 default:
5284 return SCIP_PARAMETERUNKNOWN;
5285 } /*lint !e788*/
5286
5287 return SCIP_OKAY;
5288}
5289
5290/** gets floating point parameter of LP */
5292 SCIP_LPI* lpi, /**< LP interface structure */
5293 SCIP_LPPARAM type, /**< parameter number */
5294 SCIP_Real* dval /**< buffer to store the parameter value */
5295 )
5296{
5297 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
5298
5299 assert(lpi != NULL);
5300 assert(lpi->spx != NULL);
5301 assert(dval != NULL);
5302
5303 switch( type )
5304 {
5305 case SCIP_LPPAR_FEASTOL:
5306 *dval = lpi->spx->feastol();
5307 break;
5308#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5310 *dval = lpi->spx->opttol();
5311 break;
5312#endif
5313 case SCIP_LPPAR_OBJLIM:
5314 if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5315 *dval = lpi->spx->getObjUpLimit();
5316 else
5317 *dval = lpi->spx->getObjLoLimit();
5318 break;
5319 case SCIP_LPPAR_LPTILIM:
5320 *dval = lpi->spx->terminationTime();
5321 break;
5323 *dval = lpi->rowrepswitch;
5324 break;
5326 *dval = lpi->conditionlimit;
5327 break;
5328 default:
5329 return SCIP_PARAMETERUNKNOWN;
5330 } /*lint !e788*/
5331
5332 return SCIP_OKAY;
5333}
5334
5335/** sets floating point parameter of LP */
5337 SCIP_LPI* lpi, /**< LP interface structure */
5338 SCIP_LPPARAM type, /**< parameter number */
5339 SCIP_Real dval /**< parameter value */
5340 )
5341{
5342 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
5343
5344 assert(lpi != NULL);
5345 assert(lpi->spx != NULL);
5346
5347 switch( type )
5348 {
5349 case SCIP_LPPAR_FEASTOL:
5350 /* 0 < dval */
5351 assert( dval > 0.0 );
5352 lpi->spx->setFeastol(dval);
5353 break;
5354#if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5356 /* 0 < dval */
5357 assert( dval > 0.0 );
5358 lpi->spx->setOpttol(dval);
5359 break;
5360#endif
5361 case SCIP_LPPAR_OBJLIM:
5362 if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5363 lpi->spx->setObjUpLimit(dval);
5364 else
5365 lpi->spx->setObjLoLimit(dval);
5366 break;
5367 case SCIP_LPPAR_LPTILIM:
5368 assert( dval > 0.0 );
5369 /* soplex requires 0 <= dval
5370 *
5371 * However for consistency we assert the timelimit to be strictly positive.
5372 */
5373 lpi->spx->setTerminationTime(dval);
5374 break;
5376 assert( dval >= 0.0 || dval == -1.0 );
5377 lpi->rowrepswitch = dval;
5378 break;
5380 lpi->conditionlimit = dval;
5381 lpi->checkcondition = (dval >= 0.0);
5382 break;
5383 default:
5384 return SCIP_PARAMETERUNKNOWN;
5385 } /*lint !e788*/
5386
5387 return SCIP_OKAY;
5388}
5389
5390/** interrupts the currently ongoing lp solve or disables the interrupt */
5392 SCIP_LPI* lpi, /**< LP interface structure */
5393 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
5394 )
5395{
5396 /*lint --e{715}*/
5397 assert(lpi != NULL);
5398
5399 return SCIP_OKAY;
5400}
5401
5402/**@} */
5403
5404
5405
5406
5407/*
5408 * Numerical Methods
5409 */
5410
5411/**@name Numerical Methods */
5412/**@{ */
5413
5414/** returns value treated as infinity in the LP solver */
5416 SCIP_LPI* /*lpi*/ /**< LP interface structure */
5417 )
5418{
5419 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
5420
5421 return soplex::infinity;
5422}
5423
5424/** checks if given value is treated as infinity in the LP solver */
5426 SCIP_LPI* /*lpi*/, /**< LP interface structure */
5427 SCIP_Real val
5428 )
5429{
5430 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
5431
5432 return (val >= soplex::infinity);
5433}
5434
5435/**@} */
5436
5437
5438
5439
5440/*
5441 * File Interface Methods
5442 */
5443
5444/**@name File Interface Methods */
5445/**@{ */
5446
5447/** returns, whether the given file exists */
5448static
5450 const char* filename /**< file name */
5451 )
5452{
5453 FILE* f;
5454
5455 f = fopen(filename, "r");
5456 if( f == NULL )
5457 return FALSE;
5458
5459 fclose(f);
5460
5461 return TRUE;
5462}
5463
5464/** reads LP from a file */
5466 SCIP_LPI* lpi, /**< LP interface structure */
5467 const char* fname /**< file name */
5468 )
5469{
5470 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
5471
5472 assert(lpi != NULL);
5473 assert(lpi->spx != NULL);
5474 assert(fname != NULL);
5475
5476 assert( lpi->spx->preStrongbranchingBasisFreed() );
5477
5478 if( !fileExists(fname) )
5479 return SCIP_NOFILE;
5480
5481 try
5482 {
5483 if( !lpi->spx->readLP(fname) )
5484 return SCIP_READERROR;
5485 }
5486#ifndef NDEBUG
5487 catch( const SPxException& x )
5488 {
5489 std::string s = x.what();
5490 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5491#else
5492 catch( const SPxException& )
5493 {
5494#endif
5495 return SCIP_READERROR;
5496 }
5497
5498 return SCIP_OKAY;
5499}
5500
5501/** writes LP to a file */
5503 SCIP_LPI* lpi, /**< LP interface structure */
5504 const char* fname /**< file name */
5505 )
5506{
5507 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
5508
5509 assert(lpi != NULL);
5510 assert(lpi->spx != NULL);
5511 assert(fname != NULL);
5512
5513 try
5514 {
5515 lpi->spx->writeFile(fname);
5516 }
5517#ifndef NDEBUG
5518 catch( const SPxException& x )
5519 {
5520 std::string s = x.what();
5521 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5522#else
5523 catch( const SPxException& )
5524 {
5525#endif
5526 return SCIP_WRITEERROR;
5527 }
5528
5529 return SCIP_OKAY;
5530}
5531
5532/**@} */
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:2231
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4859
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4766
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx1.cpp:5291
SCIP_Real SCIPlpiInfinity(SCIP_LPI *)
Definition: lpi_spx1.cpp:5415
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3705
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:2304
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *, SCIP_Real val)
Definition: lpi_spx1.cpp:5425
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2154
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:4916
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3571
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3483
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:4052
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:4975
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:2023
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx1.cpp:3852
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_spx1.cpp:5150
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5502
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_spx1.cpp:1684
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3613
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_spx1.cpp:5336
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:3283
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_spx1.cpp:5085
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_spx1.cpp:2557
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_spx1.cpp:1701
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:3357
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_spx1.cpp:2793
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_spx1.cpp:1717
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx1.cpp:3889
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx1.cpp:3775
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2438
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3744
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3035
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx1.cpp:3462
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5117
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3718
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_spx1.cpp:2172
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3515
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx1.cpp:3757
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:4994
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_spx1.cpp:1776
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:3313
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:2849
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3546
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5465
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx1.cpp:3942
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3626
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5030
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3731
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4965
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx1.cpp:5202
const char * SCIPlpiGetSolverName(void)
Definition: lpi_spx1.cpp:1659
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:4139
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3498
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4361
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_spx1.cpp:2101
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:2590
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4661
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2701
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4706
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:2647
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3443
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_spx1.cpp:1668
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_spx1.cpp:3019
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3645
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2727
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_spx1.cpp:1709
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3049
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_spx1.cpp:2821
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:3387
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:3796
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3586
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:1991
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_spx1.cpp:2770
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4946
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3533
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2975
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:1887
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2931
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:1809
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3599
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx1.cpp:3921
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx1.cpp:4226
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1737
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1676
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_spx1.cpp:2324
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_spx1.cpp:2753
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3669
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_spx1.cpp:2540
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_spx1.cpp:5391
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_spx1.cpp:1969
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:2123
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2368
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_spx1.cpp:2523
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4815
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_spx1.cpp:2280
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:1511
#define NULL
Definition: lpi_spx1.cpp:161
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:1527
static SCIP_Bool fileExists(const char *filename)
Definition: lpi_spx1.cpp:5449
#define SOPLEX_TRY(messagehdlr, x)
Definition: lpi_spx1.cpp:172
static int rowpacketNum(int nrows)
Definition: lpi_spx1.cpp:1502
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi, SPxSolver::Representation rep, SPxSolver::Type type)
Definition: lpi_spx1.cpp:2883
SCIP_DUALPACKET ROWPACKET
Definition: lpi_spx1.cpp:1396
#define SOPLEX_VERBLEVEL
Definition: lpi_spx1.cpp:151
static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx1.cpp:1442
static char * spxdesc
Definition: lpi_spx1.cpp:1642
#define COLS_PER_PACKET
Definition: lpi_spx1.cpp:1395
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition: lpi_spx1.cpp:1567
#define AUTOPRICING_ITERSWITCH
Definition: lpi_spx1.cpp:43
SCIP_DUALPACKET COLPACKET
Definition: lpi_spx1.cpp:1394
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:3065
static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx1.cpp:1464
static int colpacketNum(int ncols)
Definition: lpi_spx1.cpp:1493
char * initSpxDesc()
Definition: lpi_spx1.cpp:1644
#define SOPLEX_SUBVERSION
Definition: lpi_spx1.cpp:98
static SCIP_RETCODE getRedCostEst(SPxSCIP *spx, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:3997
static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
Definition: lpi_spx1.cpp:1543
#define SOPLEX_TRY_ABORT(x)
Definition: lpi_spx1.cpp:217
static SPxLP::SPxSense spxObjsen(SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1593
#define ROWS_PER_PACKET
Definition: lpi_spx1.cpp:1397
static const char spxname[20]
Definition: lpi_spx1.cpp:1639
static void invalidateSolution(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1612
static SCIP_RETCODE lpiGetBInvVec(SCIP_LPI *lpi, SCIP_Real *rhs, SCIP_Real *coef)
Definition: lpi_spx1.cpp:4532
#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:1412
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:1411
SPxSCIP * spx
Definition: lpi_spx1.cpp:1404
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