1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 #include <assert.h>
17 #include <iostream>
18 #include <sstream>
19
20 #include "soplex/spxdefines.h"
21 // #include "soplex.h"
22 #include "soplex/spxpricer.h"
23 #include "soplex/spxratiotester.h"
24 #include "soplex/spxstarter.h"
25 #include "soplex/spxout.h"
26 #include "soplex/timerfactory.h"
27
28 namespace soplex
29 {
30 template <class R>
31 bool SPxSolverBase<R>::read(std::istream& in, NameSet* rowNames,
32 NameSet* colNames, DIdxSet* intVars)
33 {
34 if(initialized)
35 {
36 clear();
37 unInit();
38
39 if(thepricer)
40 thepricer->clear();
41
42 if(theratiotester)
43 theratiotester->clear();
44 }
45
46 this->unLoad();
47
48 if(!SPxLPBase<R>::read(in, rowNames, colNames, intVars))
49 return false;
50
51 this->theLP = this;
52
53 return true;
54 }
55
56 template <class R>
57 void SPxSolverBase<R>::reLoad()
58 {
59 forceRecompNonbasicValue();
60 unInit();
61 this->unLoad();
62 this->theLP = this;
63 m_status = SPxSolverBase<R>::UNKNOWN;
64
65 if(thepricer)
66 thepricer->clear();
67
68 if(theratiotester)
69 theratiotester->clear();
70 }
71
72 template <class R>
73 void SPxSolverBase<R>::loadLP(const SPxLPBase<R>& lp, bool initSlackBasis)
74 {
75 clear();
76 unInit();
77 this->unLoad();
78 resetClockStats();
79
80 if(thepricer)
81 thepricer->clear();
82
83 if(theratiotester)
84 theratiotester->clear();
85
86 SPxLPBase<R>::operator=(lp);
87 reDim();
88 SPxBasisBase<R>::load(this, initSlackBasis);
89 }
90
91 template <class R>
92 void SPxSolverBase<R>::setBasisSolver(SLinSolver<R>* slu, const bool destroy)
93 {
94 // we need to set the outstream before we load the solver to ensure that the basis
95 // can be initialized with this pointer in loadSolver()
96 assert(spxout != 0);
97 slu->spxout = spxout;
98 SPxBasisBase<R>::loadBasisSolver(slu, destroy);
99 }
100
101 template <class R>
102 void SPxSolverBase<R>::loadBasis(const typename SPxBasisBase<R>::Desc& p_desc)
103 {
104 unInit();
105
106 if(SPxBasisBase<R>::status() == SPxBasisBase<R>::NO_PROBLEM)
107 {
108 SPxBasisBase<R>::load(this, false);
109 }
110
111 setBasisStatus(SPxBasisBase<R>::REGULAR);
112 SPxBasisBase<R>::loadDesc(p_desc);
113 }
114
115 template <class R>
116 void SPxSolverBase<R>::setPricer(SPxPricer<R>* x, const bool destroy)
117 {
118
119 assert(!freePricer || thepricer != 0);
120
121 if(freePricer)
122 {
123 delete thepricer;
124 thepricer = 0;
125 }
126
127 if(x != 0 && x != thepricer)
128 {
129 setPricing(FULL);
130
131 if(isInitialized())
132 x->load(this);
133 else
134 x->clear();
135 }
136
137 if(thepricer && thepricer != x)
138 thepricer->clear();
139
140 thepricer = x;
141
142 freePricer = destroy;
143 }
144
145 template <class R>
146 void SPxSolverBase<R>::setTester(SPxRatioTester<R>* x, const bool destroy)
147 {
148 assert(!freeRatioTester || theratiotester != 0);
149
150 if(freeRatioTester)
151 {
152 delete theratiotester;
153 theratiotester = 0;
154 }
155
156 theratiotester = x;
157
158 // set the solver pointer inside the ratiotester
159 if(theratiotester != 0)
160 {
161 if(isInitialized())
162 theratiotester->load(this);
163 else
164 theratiotester->clear();
165 }
166
167 freeRatioTester = destroy;
168 }
169
170 template <class R>
171 void SPxSolverBase<R>::setStarter(SPxStarter<R>* x, const bool destroy)
172 {
173
174 assert(!freeStarter || thestarter != 0);
175
176 if(freeStarter)
177 {
178 delete thestarter;
179 thestarter = 0;
180 }
181
182 thestarter = x;
183
184 freeStarter = destroy;
185 }
186
187 template <class R>
188 void SPxSolverBase<R>::setType(Type tp)
189 {
190
191 if(theType != tp)
192 {
193 theType = tp;
194
195 forceRecompNonbasicValue();
196
197 unInit();
198 #if 0
199 else
200 {
201 if(!matrixIsSetup)
202 {
203 SPxBasisBase<R>::load(this);
204 // SPxBasisBase<R>::load(desc());
205 // not needed, because load(this) allready loads descriptor
206 }
207
208 factorized = false;
209 m_numCycle = 0;
210 #endif
211 MSG_INFO3((*spxout), (*spxout) << "Switching to "
212 << static_cast<const char*>((tp == LEAVE)
213 ? "leaving" : "entering")
214 << " algorithm" << std::endl;)
215 }
216 }
217
218 template <class R>
219 void SPxSolverBase<R>::initRep(Representation p_rep)
220 {
221
222 R tmpfeastol = feastol();
223 R tmpopttol = opttol();
224
225 theRep = p_rep;
226
227 if(theRep == COLUMN)
228 {
229 thevectors = this->colSet();
230 thecovectors = this->rowSet();
231 theFrhs = &primRhs;
232 theFvec = &primVec;
233 theCoPrhs = &dualRhs;
234 theCoPvec = &dualVec;
235 thePvec = &addVec;
236 theRPvec = theCoPvec;
237 theCPvec = thePvec;
238 theUbound = &theUCbound;
239 theLbound = &theLCbound;
240 theCoUbound = &theURbound;
241 theCoLbound = &theLRbound;
242 }
243 else
244 {
245 assert(theRep == ROW);
246
247 thevectors = this->rowSet();
248 thecovectors = this->colSet();
249 theFrhs = &dualRhs;
250 theFvec = &dualVec;
251 theCoPrhs = &primRhs;
252 theCoPvec = &primVec;
253 thePvec = &addVec;
254 theRPvec = thePvec;
255 theCPvec = theCoPvec;
256 theUbound = &theURbound;
257 theLbound = &theLRbound;
258 theCoUbound = &theUCbound;
259 theCoLbound = &theLCbound;
260 }
261
262 unInit();
263 reDim();
264
265 forceRecompNonbasicValue();
266
267 setFeastol(tmpfeastol);
268 setOpttol(tmpopttol);
269
270 SPxBasisBase<R>::setRep();
271
272 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM)
273 SPxBasisBase<R>::loadDesc(this->desc());
274
275 if(thepricer && thepricer->solver() == this)
276 thepricer->setRep(p_rep);
277 }
278
279 template <class R>
280 void SPxSolverBase<R>::setRep(Representation p_rep)
281 {
282
283 if(p_rep != theRep)
284 initRep(p_rep);
285 }
286
287 // needed for strongbranching. use carefully
288 template <class R>
289 void SPxSolverBase<R>::reinitializeVecs()
290 {
291
292 initialized = true;
293
294 if(type() == ENTER)
295 {
296 if(rep() == COLUMN)
297 setPrimalBounds();
298 else
299 setDualRowBounds();
300
301 setEnterBounds();
302 computeEnterCoPrhs();
303 }
304 else
305 {
306 if(rep() == ROW)
307 setPrimalBounds();
308 else
309 setDualColBounds();
310
311 setLeaveBounds();
312 computeLeaveCoPrhs();
313 }
314
315 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
316 computePvec();
317 computeFrhs();
318 SPxBasisBase<R>::solve(*theFvec, *theFrhs);
319
320 theShift = 0.0;
321 lastShift = 0.0;
322
323 if(type() == ENTER)
324 {
325 computeCoTest();
326 computeTest();
327 }
328 else
329 {
330 computeFtest();
331 }
332
333 assert((testBounds(), 1));
334 }
335
336 template <class R>
337 void SPxSolverBase<R>::resetClockStats()
338 {
339 nClckSkipsLeft = 0;
340 nCallsToTimelim = 0;
341 theCumulativeTime = 0.0;
342 }
343
344 template <class R>
345 void SPxSolverBase<R>::init()
346 {
347
348 assert(thepricer != 0);
349 assert(theratiotester != 0);
350
351 if(!initialized)
352 {
353 initialized = true;
354 clearUpdateVecs();
355 reDim();
356
357 if(SPxBasisBase<R>::status() <= SPxBasisBase<R>::NO_PROBLEM || this->solver() != this)
358 SPxBasisBase<R>::load(this);
359
360 initialized = false;
361 }
362
363 if(!this->matrixIsSetup)
364 SPxBasisBase<R>::loadDesc(this->desc());
365
366 // Inna/Tobi: don't "upgrade" a singular basis to a regular one
367 if(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR)
368 return;
369
370 // catch pathological case for LPs with zero constraints
371 if(dim() == 0)
372 {
373 this->factorized = true;
374 }
375
376 // we better factorize explicitly before solving
377 if(!this->factorized)
378 {
379 try
380 {
381 SPxBasisBase<R>::factorize();
382 }
383 catch(const SPxException&)
384 {
385 // reload inital slack basis in case the factorization failed
386 assert(SPxBasisBase<R>::status() <= SPxBasisBase<R>::SINGULAR);
387 SPxBasisBase<R>::restoreInitialBasis();
388 SPxBasisBase<R>::factorize();
389 assert(this->factorized);
390 }
391 }
392
393 m_numCycle = 0;
394
395 if(type() == ENTER)
396 {
397 if(rep() == COLUMN)
398 {
399 setPrimalBounds();
400 setBasisStatus(SPxBasisBase<R>::PRIMAL);
401 }
402 else
403 {
404 setDualRowBounds();
405 setBasisStatus(SPxBasisBase<R>::DUAL);
406 }
407
408 setEnterBounds();
409 computeEnterCoPrhs();
410 // prepare support vectors for sparse pricing
411 infeasibilities.setMax(dim());
412 infeasibilitiesCo.setMax(coDim());
413 isInfeasible.reSize(dim());
414 isInfeasibleCo.reSize(coDim());
415 theratiotester->setDelta(entertol());
416 }
417 else
418 {
419 if(rep() == ROW)
420 {
421 setPrimalBounds();
422 setBasisStatus(SPxBasisBase<R>::PRIMAL);
423 }
424 else
425 {
426 setDualColBounds();
427 setBasisStatus(SPxBasisBase<R>::DUAL);
428 }
429
430 setLeaveBounds();
431 computeLeaveCoPrhs();
432 // prepare support vectors for sparse pricing
433 infeasibilities.setMax(dim());
434 isInfeasible.reSize(dim());
435 theratiotester->setDelta(leavetol());
436 }
437
438 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
439 computePvec();
440 computeFrhs();
441 SPxBasisBase<R>::solve(*theFvec, *theFrhs);
442
443 theShift = 0.0;
444
445 if(type() == ENTER)
446 {
447 shiftFvec();
448 lastShift = theShift + entertol();
449
450 computeCoTest();
451 computeTest();
452 }
453 else
454 {
455 shiftPvec();
456 lastShift = theShift + leavetol();
457
458 computeFtest();
459 }
460
461 if(!initialized)
462 {
463 // if(thepricer->solver() != this)
464 thepricer->load(this);
465 // if(theratiotester->solver() != this)
466 theratiotester->load(this);
467 initialized = true;
468 }
469 }
470
471 template <class R>
472 void SPxSolverBase<R>::setPricing(Pricing pr)
473 {
474 thePricing = pr;
475
476 if(initialized && type() == ENTER)
477 {
478 computePvec();
479 computeCoTest();
480 computeTest();
481 }
482 }
483
484 template <class R>
485 void SPxSolverBase<R>::setDecompStatus(DecompStatus decomp_stat)
486 {
487 if(decomp_stat == FINDSTARTBASIS)
488 getStartingDecompBasis = true;
489 else
490 getStartingDecompBasis = false;
491 }
492
493 /*
494 The following method resizes all vectors and arrays of |SoPlex|
495 (excluding inherited vectors).
496 */
497 template <class R>
498 void SPxSolverBase<R>::reDim()
499 {
500
501 int newsize = SPxLPBase<R>::nCols() > SPxLPBase<R>::nRows() ? SPxLPBase<R>::nCols() :
502 SPxLPBase<R>::nRows();
503
504 if(newsize > unitVecs.size())
505 {
506 unitVecs.reSize(newsize);
507
508 while(newsize-- > 0)
509 unitVecs[newsize] = UnitVectorBase<R>(newsize);
510 }
511
512 if(isInitialized())
513 {
514 theFrhs->reDim(dim());
515 theFvec->reDim(dim());
516 thePvec->reDim(coDim());
517
518 theCoPrhs->reDim(dim());
519 theCoPvec->reDim(dim());
520
521 theTest.reDim(coDim());
522 theCoTest.reDim(dim());
523
524 theURbound.reDim(SPxLPBase<R>::nRows());
525 theLRbound.reDim(SPxLPBase<R>::nRows());
526 theUCbound.reDim(SPxLPBase<R>::nCols());
527 theLCbound.reDim(SPxLPBase<R>::nCols());
528 theUBbound.reDim(dim());
529 theLBbound.reDim(dim());
530 }
531 }
532
533 template <class R>
534 void SPxSolverBase<R>::clear()
535 {
536 unitVecs.reSize(0);
537
538 dualRhs.clear();
539 dualVec.clear();
540 primRhs.clear();
541 primVec.clear();
542 addVec.clear();
543 theURbound.clear();
544 theLRbound.clear();
545 theUCbound.clear();
546 theLCbound.clear();
547 theTest.clear();
548 theCoTest.clear();
549
550 forceRecompNonbasicValue();
551 unInit();
552 SPxLPBase<R>::clear();
553 setBasisStatus(SPxBasisBase<R>::NO_PROBLEM);
554
555 // clear the basis only when theLP is present, because LP data (nrows, ncols) is used in reDim()
556 if(this->theLP != 0)
557 SPxBasisBase<R>::reDim();
558
559 infeasibilities.clear();
560 infeasibilitiesCo.clear();
561 isInfeasible.clear();
562 isInfeasibleCo.clear();
563 }
564
565 template <class R>
566 void SPxSolverBase<R>::unscaleLPandReloadBasis()
567 {
568 SPxLPBase<R>::unscaleLP();
569 SPxBasisBase<R>::invalidate();
570 unInit();
571 init();
572 }
573
574 template <class R>
575 void SPxSolverBase<R>::invalidateBasis()
576 {
577 SPxBasisBase<R>::invalidate();
578 unInit();
579 init();
580 }
581
582 template <class R>
583 void SPxSolverBase<R>::clearUpdateVecs(void)
584 {
585 theFvec->clearUpdate();
586 thePvec->clearUpdate();
587 theCoPvec->clearUpdate();
588 solveVector2 = 0;
589 solveVector3 = 0;
590 coSolveVector2 = 0;
591 coSolveVector3 = 0;
592 }
593
594 /*
595 When the basis matrix factorization is recomputed from scratch,
596 we also recompute the vectors.
597 */
598 template <class R>
599 void SPxSolverBase<R>::factorize()
600 {
601
602 MSG_INFO3((*spxout), (*spxout) << " --- refactorizing basis matrix" << std::endl;)
603
604 try
605 {
606 SPxBasisBase<R>::factorize();
607 }
608 catch(const SPxStatusException&)
609 {
610 assert(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR);
611 m_status = SINGULAR;
612 std::stringstream s;
613 s << "Basis is singular (numerical troubles, feastol = " << feastol() << ", opttol = " << opttol()
614 << ")";
615 throw SPxStatusException(s.str());
616 }
617
618 if(!initialized)
619 {
620 init(); // not sure if init() is neccessary here
621 // we must not go on here because not all vectors (e.g. fVec) may be set up correctly
622 return;
623 }
624
625 if(SPxBasisBase<R>::status() >= SPxBasisBase<R>::REGULAR)
626 {
627 #ifndef NDEBUG
628 VectorBase<R> ftmp(fVec());
629 VectorBase<R> ptmp(pVec());
630 VectorBase<R> ctmp(coPvec());
631 #endif // NDEBUG
632
633 if(type() == LEAVE)
634 {
635 /* we have to recompute theFrhs, because roundoff errors can occur during updating, especially when
636 * columns/rows with large bounds are present
637 */
638 computeFrhs();
639 SPxBasisBase<R>::solve(*theFvec, *theFrhs);
640 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
641
642 #ifndef NDEBUG
643 ftmp -= fVec();
644 ptmp -= pVec();
645 ctmp -= coPvec();
646
647 if(ftmp.length() > DEFAULT_BND_VIOL)
648 {
649 MSG_DEBUG(std::cout << "DSOLVE21 fVec: " << ftmp.length() << std::endl;)
650 ftmp = fVec();
651 this->multBaseWith(ftmp);
652 ftmp -= fRhs();
653
654 if(ftmp.length() > DEFAULT_BND_VIOL)
655 MSG_INFO1((*spxout), (*spxout) << "ESOLVE29 " << this->iteration() << ": fVec error = "
656 << ftmp.length() << " exceeding DEFAULT_BND_VIOL = " << DEFAULT_BND_VIOL << std::endl;)
657 }
658
659 if(ctmp.length() > DEFAULT_BND_VIOL)
660 {
661 MSG_DEBUG(std::cout << "DSOLVE23 coPvec: " << ctmp.length() << std::endl;)
662 ctmp = coPvec();
663 this->multWithBase(ctmp);
664 ctmp -= coPrhs();
665
666 if(ctmp.length() > DEFAULT_BND_VIOL)
667 MSG_INFO1((*spxout), (*spxout) << "ESOLVE30 " << this->iteration() << ": coPvec error = "
668 << ctmp.length() << " exceeding DEFAULT_BND_VIOL = " << DEFAULT_BND_VIOL << std::endl;)
669 }
670
671 if(ptmp.length() > DEFAULT_BND_VIOL)
672 {
673 MSG_DEBUG(std::cout << "DSOLVE24 pVec: " << ptmp.length() << std::endl;)
674 }
675
676 #endif // NDEBUG
677
678 computeFtest();
679 }
680 else
681 {
682 assert(type() == ENTER);
683
684 SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
685 computeCoTest();
686
687 if(pricing() == FULL)
688 {
689 /* to save time only recompute the row activities (in row rep) when we are already nearly optimal to
690 * avoid missing any violations from previous updates */
691 if(rep() == ROW && m_pricingViolCo < entertol() && m_pricingViol < entertol())
692 computePvec();
693
694 /* was deactivated, but this leads to warnings in testVecs() */
695 computeTest();
696 }
697 }
698 }
699
700 #ifdef ENABLE_ADDITIONAL_CHECKS
701
702 /* moved this test after the computation of fTest and coTest below, since these vectors might not be set up at top, e.g. for an initial basis */
703 if(SPxBasisBase<R>::status() > SPxBasisBase<R>::SINGULAR)
704 testVecs();
705
706 #endif
707 }
708
709 /* We compute how much the current solution violates (primal or dual) feasibility. In the
710 row/enter or column/leave algorithm the maximum violation of dual feasibility is
711 computed. In the row/leave or column/enter algorithm the primal feasibility is checked.
712 Additionally, the violation from pricing is taken into account. */
713 template <class R>
714 R SPxSolverBase<R>::maxInfeas() const
715 {
716 R inf = 0.0;
717
718 if(type() == ENTER)
719 {
720 if(m_pricingViolUpToDate && m_pricingViolCoUpToDate)
721 inf = m_pricingViol + m_pricingViolCo;
722
723 for(int i = 0; i < dim(); i++)
724 {
725 if((*theFvec)[i] > theUBbound[i])
726 inf = MAXIMUM(inf, (*theFvec)[i] - theUBbound[i]);
727 else if((*theFvec)[i] < theLBbound[i])
728 inf = MAXIMUM(inf, theLBbound[i] - (*theFvec)[i]);
729 }
730 }
731 else
732 {
733 assert(type() == LEAVE);
734
735 if(m_pricingViolUpToDate)
736 inf = m_pricingViol;
737
738 for(int i = 0; i < dim(); i++)
739 {
740 if((*theCoPvec)[i] > (*theCoUbound)[i])
741 inf = MAXIMUM(inf, (*theCoPvec)[i] - (*theCoUbound)[i]);
742 else if((*theCoPvec)[i] < (*theCoLbound)[i])
743 inf = MAXIMUM(inf, (*theCoLbound)[i] - (*theCoPvec)[i]);
744 }
745
746 for(int i = 0; i < coDim(); i++)
747 {
748 if((*thePvec)[i] > (*theUbound)[i])
749 inf = MAXIMUM(inf, (*thePvec)[i] - (*theUbound)[i]);
750 else if((*thePvec)[i] < (*theLbound)[i])
751 inf = MAXIMUM(inf, (*theLbound)[i] - (*thePvec)[i]);
752 }
753 }
754
755 return inf;
756 }
757
758 /* check for (dual) violations above tol and immediately return false w/o checking the remaining values
759 This method is useful for verifying whether an objective limit can be used as termination criterion */
760 template <class R>
761 bool SPxSolverBase<R>::noViols(R tol) const
762 {
763 assert(tol >= 0.0);
764
765 if(type() == ENTER)
766 {
767 for(int i = 0; i < dim(); i++)
768 {
769 if((*theFvec)[i] - theUBbound[i] > tol)
770 return false;
771
772 if(theLBbound[i] - (*theFvec)[i] > tol)
773 return false;
774 }
775 }
776 else
777 {
778 assert(type() == LEAVE);
779
780 for(int i = 0; i < dim(); i++)
781 {
782 if((*theCoPvec)[i] - (*theCoUbound)[i] > tol)
783 return false;
784
785 if((*theCoLbound)[i] - (*theCoPvec)[i] > tol)
786 return false;
787 }
788
789 for(int i = 0; i < coDim(); i++)
790 {
791 if((*thePvec)[i] - (*theUbound)[i] > tol)
792 return false;
793
794 if((*theLbound)[i] - (*thePvec)[i] > tol)
795 return false;
796 }
797 }
798
799 return true;
800 }
801
802 template <class R>
803 R SPxSolverBase<R>::nonbasicValue()
804 {
805 int i;
806 StableSum<R> val;
807 const typename SPxBasisBase<R>::Desc& ds = this->desc();
808
809 #ifndef ENABLE_ADDITIONAL_CHECKS
810
811 // if the value is available we don't need to recompute it
812 if(m_nonbasicValueUpToDate)
813 return m_nonbasicValue;
814
815 #endif
816
817 if(rep() == COLUMN)
818 {
819 if(type() == LEAVE)
820 {
821 for(i = this->nCols() - 1; i >= 0; --i)
822 {
823 switch(ds.colStatus(i))
824 {
825 case SPxBasisBase<R>::Desc::P_ON_UPPER :
826 val += theUCbound[i] * SPxLPBase<R>::upper(i);
827 //@ val += maxObj(i) * SPxLPBase<R>::upper(i);
828 break;
829
830 case SPxBasisBase<R>::Desc::P_ON_LOWER :
831 val += theLCbound[i] * SPxLPBase<R>::lower(i);
832 //@ val += maxObj(i) * SPxLPBase<R>::lower(i);
833 break;
834
835 case SPxBasisBase<R>::Desc::P_FIXED :
836 assert(EQ(SPxLPBase<R>::lower(i), SPxLPBase<R>::upper(i)));
837 val += this->maxObj(i) * SPxLPBase<R>::lower(i);
838 break;
839
840 default:
841 break;
842 }
843 }
844
845 for(i = this->nRows() - 1; i >= 0; --i)
846 {
847 switch(ds.rowStatus(i))
848 {
849 case SPxBasisBase<R>::Desc::P_ON_UPPER :
850 val += theLRbound[i] * SPxLPBase<R>::rhs(i);
851 break;
852
853 case SPxBasisBase<R>::Desc::P_ON_LOWER :
854 val += theURbound[i] * SPxLPBase<R>::lhs(i);
855 break;
856
857 case SPxBasisBase<R>::Desc::P_FIXED :
858 assert(EQ(SPxLPBase<R>::lhs(i), SPxLPBase<R>::rhs(i)));
859 val += this->maxRowObj(i) * SPxLPBase<R>::lhs(i);
860 break;
861
862 default:
863 break;
864 }
865 }
866 }
867 else
868 {
869 assert(type() == ENTER);
870
871 for(i = this->nCols() - 1; i >= 0; --i)
872 {
873 switch(ds.colStatus(i))
874 {
875 case SPxBasisBase<R>::Desc::P_ON_UPPER :
876 val += this->maxObj(i) * theUCbound[i];
877 break;
878
879 case SPxBasisBase<R>::Desc::P_ON_LOWER :
880 val += this->maxObj(i) * theLCbound[i];
881 break;
882
883 case SPxBasisBase<R>::Desc::P_FIXED :
884 assert(EQ(theLCbound[i], theUCbound[i]));
885 val += this->maxObj(i) * theLCbound[i];
886 break;
887
888 default:
889 break;
890 }
891 }
892
893 for(i = this->nRows() - 1; i >= 0; --i)
894 {
895 switch(ds.rowStatus(i))
896 {
897 case SPxBasisBase<R>::Desc::P_ON_UPPER :
898 val += this->maxRowObj(i) * theLRbound[i];
899 break;
900
901 case SPxBasisBase<R>::Desc::P_ON_LOWER :
902 val += this->maxRowObj(i) * theURbound[i];
903 break;
904
905 case SPxBasisBase<R>::Desc::P_FIXED :
906 assert(EQ(theLRbound[i], theURbound[i]));
907 val += this->maxRowObj(i) * theURbound[i];
908 break;
909
910 default:
911 break;
912 }
913 }
914 }
915 }
916 else
917 {
918 assert(rep() == ROW);
919 assert(type() == ENTER);
920
921 for(i = this->nCols() - 1; i >= 0; --i)
922 {
923 switch(ds.colStatus(i))
924 {
925 case SPxBasisBase<R>::Desc::D_ON_UPPER :
926 val += theUCbound[i] * this->lower(i);
927 break;
928
929 case SPxBasisBase<R>::Desc::D_ON_LOWER :
930 val += theLCbound[i] * this->upper(i);
931 break;
932
933 case SPxBasisBase<R>::Desc::D_ON_BOTH :
934 val += theLCbound[i] * this->upper(i);
935 val += theUCbound[i] * this->lower(i);
936 break;
937
938 default:
939 break;
940 }
941 }
942
943 for(i = this->nRows() - 1; i >= 0; --i)
944 {
945 switch(ds.rowStatus(i))
946 {
947 case SPxBasisBase<R>::Desc::D_ON_UPPER :
948 val += theURbound[i] * this->lhs(i);
949 break;
950
951 case SPxBasisBase<R>::Desc::D_ON_LOWER :
952 val += theLRbound[i] * this->rhs(i);
953 break;
954
955 case SPxBasisBase<R>::Desc::D_ON_BOTH :
956 val += theLRbound[i] * this->rhs(i);
957 val += theURbound[i] * this->lhs(i);
958 break;
959
960 default:
961 break;
962 }
963 }
964 }
965
966 #ifdef ENABLE_ADDITIONAL_CHECKS
967
968 if(m_nonbasicValueUpToDate && NE(m_nonbasicValue, val))
969 {
970 MSG_ERROR(std::cerr << "stored nonbasic value: " << m_nonbasicValue
971 << ", correct nonbasic value: " << val
972 << ", violation: " << val - m_nonbasicValue << std::endl;)
973 assert(EQrel(m_nonbasicValue, val, 1e-12));
974 }
975
976 #endif
977
978 if(!m_nonbasicValueUpToDate)
979 {
980 m_nonbasicValue = R(val);
981 m_nonbasicValueUpToDate = true;
982 }
983
984 return val;
985 }
986
987 template <class R>
988 R SPxSolverBase<R>::value()
989 {
990 assert(isInitialized());
991
992 R x;
993
994 // calling value() without having a suitable status is an error.
995 if(!isInitialized())
996 return R(infinity);
997
998 if(rep() == ROW)
999 {
1000 if(type() == LEAVE)
1001 x = int(SPxLPBase<R>::spxSense()) * (coPvec() *
1002 fRhs()); // the contribution of maxRowObj() is missing
1003 else
1004 x = int(SPxLPBase<R>::spxSense()) * (nonbasicValue() + (coPvec() * fRhs()));
1005 }
1006 else
1007 x = int(SPxLPBase<R>::spxSense()) * (nonbasicValue() + fVec() * coPrhs());
1008
1009 return x + this->objOffset();
1010 }
1011
1012 template <class R>
1013 bool SPxSolverBase<R>::updateNonbasicValue(R objChange)
1014 {
1015 if(m_nonbasicValueUpToDate)
1016 m_nonbasicValue += objChange;
1017
1018 MSG_DEBUG(std::cout
1019 << "Iteration: " << this->iteration()
1020 << ": updated objValue: " << objChange
1021 << ", new value: " << m_nonbasicValue
1022 << ", correct value: " << nonbasicValue()
1023 << std::endl;
1024 )
1025
1026 return m_nonbasicValueUpToDate;
1027 }
1028
1029
1030
1031 template <class R>
1032 void SPxSolverBase<R>::setFeastol(R d)
1033 {
1034
1035 if(d <= 0.0)
1036 throw SPxInterfaceException("XSOLVE30 Cannot set feastol less than or equal to zero.");
1037
1038 if(theRep == COLUMN)
1039 m_entertol = d;
1040 else
1041 m_leavetol = d;
1042 }
1043
1044 template <class R>
1045 void SPxSolverBase<R>::setOpttol(R d)
1046 {
1047
1048 if(d <= 0.0)
1049 throw SPxInterfaceException("XSOLVE31 Cannot set opttol less than or equal to zero.");
1050
1051 if(theRep == COLUMN)
1052 m_leavetol = d;
1053 else
1054 m_entertol = d;
1055 }
1056
1057 template <class R>
1058 void SPxSolverBase<R>::setDelta(R d)
1059 {
1060
1061 if(d <= 0.0)
1062 throw SPxInterfaceException("XSOLVE32 Cannot set delta less than or equal to zero.");
1063
1064 m_entertol = d;
1065 m_leavetol = d;
1066 }
1067
1068 template <class R>
1069 void SPxSolverBase<R>::hyperPricing(bool h)
1070 {
1071 hyperPricingEnter = h;
1072 hyperPricingLeave = h;
1073
1074 if(h)
1075 {
1076 updateViols.setMax(dim());
1077 updateViolsCo.setMax(coDim());
1078 }
1079 }
1080
1081 template <class R>
1082 SPxSolverBase<R>::SPxSolverBase(
1083 Type p_type,
1084 Representation p_rep,
1085 Timer::TYPE ttype)
1086 : theType(p_type)
1087 , thePricing(FULL)
1088 , theRep(p_rep)
1089 , polishObj(POLISH_OFF)
1090 , theTime(nullptr)
1091 , timerType(ttype)
1092 , theCumulativeTime(0.0)
1093 , maxIters(-1)
1094 , maxTime(R(infinity))
1095 , nClckSkipsLeft(0)
1096 , nCallsToTimelim(0)
1097 , objLimit(R(infinity))
1098 , m_status(UNKNOWN)
1099 , m_nonbasicValue(0.0)
1100 , m_nonbasicValueUpToDate(false)
1101 , m_pricingViol(0.0)
1102 , m_pricingViolUpToDate(false)
1103 , m_pricingViolCo(0.0)
1104 , m_pricingViolCoUpToDate(false)
1105 , m_numViol(0)
1106 , theShift(0)
1107 , m_maxCycle(100)
1108 , m_numCycle(0)
1109 , initialized(false)
1110 , solveVector2(0)
1111 , solveVector3(0)
1112 , coSolveVector2(0)
1113 , coSolveVector3(0)
1114 , freePricer(false)
1115 , freeRatioTester(false)
1116 , freeStarter(false)
1117 , displayLine(0)
1118 , displayFreq(200)
1119 , sparsePricingFactor(SPARSITYFACTOR)
1120 , getStartingDecompBasis(false)
1121 , computeDegeneracy(false)
1122 , degenCompIterOffset(0)
1123 , fullPerturbation(false)
1124 , printBasisMetric(0)
1125 , unitVecs(0)
1126 , primVec(0, Param::epsilon())
1127 , dualVec(0, Param::epsilon())
1128 , addVec(0, Param::epsilon())
1129 , thepricer(0)
1130 , theratiotester(0)
1131 , thestarter(0)
1132 , boundrange(0.0)
1133 , siderange(0.0)
1134 , objrange(0.0)
1135 , infeasibilities(0)
1136 , infeasibilitiesCo(0)
1137 , isInfeasible(0)
1138 , isInfeasibleCo(0)
1139 , sparsePricingLeave(false)
1140 , sparsePricingEnter(false)
1141 , sparsePricingEnterCo(false)
1142 , hyperPricingLeave(true)
1143 , hyperPricingEnter(true)
1144 , remainingRoundsLeave(0)
1145 , remainingRoundsEnter(0)
1146 , remainingRoundsEnterCo(0)
1147 , weights(0)
1148 , coWeights(0)
1149 , weightsAreSetup(false)
1150 , multSparseCalls(0)
1151 , multFullCalls(0)
1152 , multColwiseCalls(0)
1153 , multUnsetupCalls(0)
1154 , integerVariables(0)
1155 {
1156 theTime = TimerFactory::createTimer(timerType);
1157
1158 multTimeSparse = TimerFactory::createTimer(timerType);
1159 multTimeFull = TimerFactory::createTimer(timerType);
1160 multTimeColwise = TimerFactory::createTimer(timerType);
1161 multTimeUnsetup = TimerFactory::createTimer(timerType);
1162
1163 setDelta(DEFAULT_BND_VIOL);
1164
1165 this->theLP = this;
1166 initRep(p_rep);
1167
1168 // info: SPxBasisBase is not consistent in this moment.
1169 //assert(SPxSolverBase<R>::isConsistent());
1170 }
1171
1172 template <class R>
1173 SPxSolverBase<R>::~SPxSolverBase()
1174 {
1175 assert(!freePricer || thepricer != 0);
1176 assert(!freeRatioTester || theratiotester != 0);
1177 assert(!freeStarter || thestarter != 0);
1178
1179 if(freePricer)
1180 {
1181 delete thepricer;
1182 thepricer = 0;
1183 }
1184
1185 if(freeRatioTester)
1186 {
1187 delete theratiotester;
1188 theratiotester = 0;
1189 }
1190
1191 if(freeStarter)
1192 {
1193 delete thestarter;
1194 thestarter = 0;
1195 }
1196
1197 // free the timers
1198 assert(theTime);
1199 assert(multTimeSparse);
1200 assert(multTimeFull);
1201 assert(multTimeColwise);
1202 assert(multTimeUnsetup);
1203 theTime->~Timer();
1204 multTimeSparse->~Timer();
1205 multTimeFull->~Timer();
1206 multTimeColwise->~Timer();
1207 multTimeUnsetup->~Timer();
1208 spx_free(theTime);
1209 spx_free(multTimeSparse);
1210 spx_free(multTimeFull);
1211 spx_free(multTimeColwise);
1212 spx_free(multTimeUnsetup);
1213 }
1214
1215
1216 template <class R>
1217 SPxSolverBase<R>& SPxSolverBase<R>::operator=(const SPxSolverBase<R>& base)
1218 {
1219 if(this != &base)
1220 {
1221 SPxLPBase<R>::operator=(base);
1222 SPxBasisBase<R>::operator=(base);
1223 theType = base.theType;
1224 thePricing = base.thePricing;
1225 theRep = base.theRep;
1226 polishObj = base.polishObj;
1227 timerType = base.timerType;
1228 maxIters = base.maxIters;
1229 maxTime = base.maxTime;
1230 objLimit = base.objLimit;
1231 m_status = base.m_status;
1232 m_nonbasicValue = base.m_nonbasicValue;
1233 m_nonbasicValueUpToDate = base.m_nonbasicValueUpToDate;
1234 m_pricingViol = base.m_pricingViol;
1235 m_pricingViolUpToDate = base.m_pricingViolUpToDate;
1236 m_pricingViolCo = base.m_pricingViolCo;
1237 m_pricingViolCoUpToDate = base.m_pricingViolCoUpToDate;
1238 m_numViol = base.m_numViol;
1239 m_entertol = base.m_entertol;
1240 m_leavetol = base.m_leavetol;
1241 theShift = base.theShift;
1242 lastShift = base.lastShift;
1243 m_maxCycle = base.m_maxCycle;
1244 m_numCycle = base.m_numCycle;
1245 initialized = base.initialized;
1246 instableLeaveNum = base.instableLeaveNum;
1247 instableLeave = base.instableLeave;
1248 instableLeaveVal = base.instableLeaveVal;
1249 instableEnterId = base.instableEnterId;
1250 instableEnter = base.instableEnter;
1251 instableEnterVal = base.instableEnterVal;
1252 displayLine = base.displayLine;
1253 displayFreq = base.displayFreq;
1254 sparsePricingFactor = base.sparsePricingFactor;
1255 getStartingDecompBasis = base.getStartingDecompBasis;
1256 computeDegeneracy = base.computeDegeneracy;
1257 degenCompIterOffset = base.degenCompIterOffset;
1258 decompIterationLimit = base.decompIterationLimit;
1259 fullPerturbation = base.fullPerturbation;
1260 printBasisMetric = base.printBasisMetric;
1261 unitVecs = base.unitVecs;
1262 primRhs = base.primRhs;
1263 primVec = base.primVec;
1264 dualRhs = base.dualRhs;
1265 dualVec = base.dualVec;
1266 addVec = base.addVec;
1267 theURbound = base.theURbound;
1268 theLRbound = base.theLRbound;
1269 theUCbound = base.theUCbound;
1270 theLCbound = base.theLCbound;
1271 theUBbound = base.theUBbound;
1272 theLBbound = base.theLBbound;
1273 theCoTest = base.theCoTest;
1274 theTest = base.theTest;
1275 primalRay = base.primalRay;
1276 dualFarkas = base.dualFarkas;
1277 leaveCount = base.leaveCount;
1278 enterCount = base.enterCount;
1279 theCumulativeTime = base.theCumulativeTime;
1280 primalCount = base.primalCount;
1281 polishCount = base.polishCount;
1282 boundflips = base.boundflips;
1283 totalboundflips = base.totalboundflips;
1284 enterCycles = base.enterCycles;
1285 leaveCycles = base.leaveCycles;
1286 enterDegenCand = base.enterDegenCand;
1287 leaveDegenCand = base.leaveDegenCand;
1288 primalDegenSum = base.primalDegenSum;
1289 boundrange = base.boundrange;
1290 siderange = base.siderange;
1291 objrange = base.objrange;
1292 infeasibilities = base.infeasibilities;
1293 infeasibilitiesCo = base.infeasibilitiesCo;
1294 isInfeasible = base.isInfeasible;
1295 isInfeasibleCo = base.isInfeasibleCo;
1296 sparsePricingLeave = base.sparsePricingLeave;
1297 sparsePricingEnter = base.sparsePricingEnter;
1298 sparsePricingEnterCo = base.sparsePricingEnterCo;
1299 sparsePricingFactor = base.sparsePricingFactor;
1300 hyperPricingLeave = base.hyperPricingLeave;
1301 hyperPricingEnter = base.hyperPricingEnter;
1302 remainingRoundsLeave = base.remainingRoundsLeave;
1303 remainingRoundsEnter = base.remainingRoundsEnter;
1304 remainingRoundsEnterCo = base.remainingRoundsEnterCo;
1305 weights = base.weights;
1306 coWeights = base.coWeights;
1307 weightsAreSetup = base.weightsAreSetup;
1308 multSparseCalls = base.multSparseCalls;
1309 multFullCalls = base.multFullCalls;
1310 multColwiseCalls = base.multColwiseCalls;
1311 multUnsetupCalls = base.multUnsetupCalls;
1312 spxout = base.spxout;
1313 integerVariables = base.integerVariables;
1314
1315 if(base.theRep == COLUMN)
1316 {
1317 thevectors = this->colSet();
1318 thecovectors = this->rowSet();
1319 theFrhs = &primRhs;
1320 theFvec = &primVec;
1321 theCoPrhs = &dualRhs;
1322 theCoPvec = &dualVec;
1323 thePvec = &addVec;
1324 theRPvec = theCoPvec;
1325 theCPvec = thePvec;
1326 theUbound = &theUCbound;
1327 theLbound = &theLCbound;
1328 theCoUbound = &theURbound;
1329 theCoLbound = &theLRbound;
1330 }
1331 else
1332 {
1333 assert(base.theRep == ROW);
1334
1335 thevectors = this->rowSet();
1336 thecovectors = this->colSet();
1337 theFrhs = &dualRhs;
1338 theFvec = &dualVec;
1339 theCoPrhs = &primRhs;
1340 theCoPvec = &primVec;
1341 thePvec = &addVec;
1342 theRPvec = thePvec;
1343 theCPvec = theCoPvec;
1344 theUbound = &theURbound;
1345 theLbound = &theLRbound;
1346 theCoUbound = &theUCbound;
1347 theCoLbound = &theLCbound;
1348 }
1349
1350 SPxBasisBase<R>::theLP = this;
1351
1352 assert(!freePricer || thepricer != 0);
1353 assert(!freeRatioTester || theratiotester != 0);
1354 assert(!freeStarter || thestarter != 0);
1355
1356 // thepricer
1357 if(freePricer)
1358 {
1359 delete thepricer;
1360 thepricer = 0;
1361 }
1362
1363 if(base.thepricer == 0)
1364 {
1365 thepricer = 0;
1366 freePricer = false;
1367 }
1368 else
1369 {
1370 thepricer = base.thepricer->clone();
1371 freePricer = true;
1372 thepricer->load(this);
1373 }
1374
1375 // theratiotester
1376 if(freeRatioTester)
1377 {
1378 delete theratiotester;
1379 theratiotester = 0;
1380 }
1381
1382 if(base.theratiotester == 0)
1383 {
1384 theratiotester = 0;
1385 freeRatioTester = false;
1386 }
1387 else
1388 {
1389 theratiotester = base.theratiotester->clone();
1390 freeRatioTester = true;
1391 theratiotester->load(this);
1392 }
1393
1394 // thestarter
1395 if(freeStarter)
1396 {
1397 delete thestarter;
1398 thestarter = 0;
1399 }
1400
1401 if(base.thestarter == 0)
1402 {
1403 thestarter = 0;
1404 freeStarter = false;
1405 }
1406 else
1407 {
1408 thestarter = base.thestarter->clone();
1409 freeStarter = true;
1410 }
1411
1412 assert(SPxSolverBase<R>::isConsistent());
1413 }
1414
1415 return *this;
1416 }
1417
1418
1419 template <class R>
1420 SPxSolverBase<R>::SPxSolverBase(const SPxSolverBase<R>& base)
1421 : SPxLPBase<R> (base)
1422 , SPxBasisBase<R>(this->basSe)
1423 , theType(base.theType)
1424 , thePricing(base.thePricing)
1425 , theRep(base.theRep)
1426 , polishObj(base.polishObj)
1427 , timerType(base.timerType)
1428 , theCumulativeTime(base.theCumulativeTime)
1429 , maxIters(base.maxIters)
1430 , maxTime(base.maxTime)
1431 , nClckSkipsLeft(base.nClckSkipsLeft)
1432 , nCallsToTimelim(base.nCallsToTimelim)
1433 , objLimit(base.objLimit)
1434 , m_status(base.m_status)
1435 , m_nonbasicValue(base.m_nonbasicValue)
1436 , m_nonbasicValueUpToDate(base.m_nonbasicValueUpToDate)
1437 , m_pricingViol(base.m_pricingViol)
1438 , m_pricingViolUpToDate(base.m_pricingViolUpToDate)
1439 , m_pricingViolCo(base.m_pricingViolCo)
1440 , m_pricingViolCoUpToDate(base.m_pricingViolCoUpToDate)
1441 , m_numViol(base.m_numViol)
1442 , m_entertol(base.m_entertol)
1443 , m_leavetol(base.m_leavetol)
1444 , theShift(base.theShift)
1445 , lastShift(base.lastShift)
1446 , m_maxCycle(base.m_maxCycle)
1447 , m_numCycle(base.m_numCycle)
1448 , initialized(base.initialized)
1449 , solveVector2(0)
1450 , solveVector2rhs(base.solveVector2rhs)
1451 , solveVector3(0)
1452 , solveVector3rhs(base.solveVector3rhs)
1453 , coSolveVector2(0)
1454 , coSolveVector2rhs(base.coSolveVector2rhs)
1455 , coSolveVector3(0)
1456 , coSolveVector3rhs(base.coSolveVector3rhs)
1457 , instableLeaveNum(base.instableLeaveNum)
1458 , instableLeave(base.instableLeave)
1459 , instableLeaveVal(base.instableLeaveVal)
1460 , instableEnterId(base.instableEnterId)
1461 , instableEnter(base.instableEnter)
1462 , instableEnterVal(base.instableEnterVal)
1463 , displayLine(base.displayLine)
1464 , displayFreq(base.displayFreq)
1465 , sparsePricingFactor(base.sparsePricingFactor)
1466 , getStartingDecompBasis(base.getStartingDecompBasis)
1467 , computeDegeneracy(base.computeDegeneracy)
1468 , degenCompIterOffset(base.degenCompIterOffset)
1469 , decompIterationLimit(base.decompIterationLimit)
1470 , fullPerturbation(base.fullPerturbation)
1471 , printBasisMetric(base.printBasisMetric)
1472 , unitVecs(base.unitVecs)
1473 , primRhs(base.primRhs)
1474 , primVec(base.primVec)
1475 , dualRhs(base.dualRhs)
1476 , dualVec(base.dualVec)
1477 , addVec(base.addVec)
1478 , theURbound(base.theURbound)
1479 , theLRbound(base.theLRbound)
1480 , theUCbound(base.theUCbound)
1481 , theLCbound(base.theLCbound)
1482 , theUBbound(base.theUBbound)
1483 , theLBbound(base.theLBbound)
1484 , theCoTest(base.theCoTest)
1485 , theTest(base.theTest)
1486 , primalRay(base.primalRay)
1487 , dualFarkas(base.dualFarkas)
1488 , leaveCount(base.leaveCount)
1489 , enterCount(base.enterCount)
1490 , primalCount(base.primalCount)
1491 , polishCount(base.polishCount)
1492 , boundflips(base.boundflips)
1493 , totalboundflips(base.totalboundflips)
1494 , enterCycles(base.enterCycles)
1495 , leaveCycles(base.leaveCycles)
1496 , enterDegenCand(base.enterDegenCand)
1497 , leaveDegenCand(base.leaveDegenCand)
1498 , primalDegenSum(base.primalDegenSum)
1499 , dualDegenSum(base.dualDegenSum)
1500 , boundrange(base.boundrange)
1501 , siderange(base.siderange)
1502 , objrange(base.objrange)
1503 , infeasibilities(base.infeasibilities)
1504 , infeasibilitiesCo(base.infeasibilitiesCo)
1505 , isInfeasible(base.isInfeasible)
1506 , isInfeasibleCo(base.isInfeasibleCo)
1507 , sparsePricingLeave(base.sparsePricingLeave)
1508 , sparsePricingEnter(base.sparsePricingEnter)
1509 , sparsePricingEnterCo(base.sparsePricingEnterCo)
1510 , hyperPricingLeave(base.hyperPricingLeave)
1511 , hyperPricingEnter(base.hyperPricingEnter)
1512 , remainingRoundsLeave(base.remainingRoundsLeave)
1513 , remainingRoundsEnter(base.remainingRoundsEnter)
1514 , remainingRoundsEnterCo(base.remainingRoundsEnterCo)
1515 , weights(base.weights)
1516 , coWeights(base.coWeights)
1517 , weightsAreSetup(base.weightsAreSetup)
1518 , multSparseCalls(base.multSparseCalls)
1519 , multFullCalls(base.multFullCalls)
1520 , multColwiseCalls(base.multColwiseCalls)
1521 , multUnsetupCalls(base.multUnsetupCalls)
1522 , spxout(base.spxout)
1523 , integerVariables(base.integerVariables)
1524 {
1525 theTime = TimerFactory::createTimer(timerType);
1526 multTimeSparse = TimerFactory::createTimer(timerType);
1527 multTimeFull = TimerFactory::createTimer(timerType);
1528 multTimeColwise = TimerFactory::createTimer(timerType);
1529 multTimeUnsetup = TimerFactory::createTimer(timerType);
1530
1531 if(base.theRep == COLUMN)
1532 {
1533 thevectors = this->colSet();
1534 thecovectors = this->rowSet();
1535 theFrhs = &primRhs;
1536 theFvec = &primVec;
1537 theCoPrhs = &dualRhs;
1538 theCoPvec = &dualVec;
1539 thePvec = &addVec;
1540 theRPvec = theCoPvec;
1541 theCPvec = thePvec;
1542 theUbound = &theUCbound;
1543 theLbound = &theLCbound;
1544 theCoUbound = &theURbound;
1545 theCoLbound = &theLRbound;
1546 }
1547 else
1548 {
1549 assert(base.theRep == ROW);
1550
1551 thevectors = this->rowSet();
1552 thecovectors = this->colSet();
1553 theFrhs = &dualRhs;
1554 theFvec = &dualVec;
1555 theCoPrhs = &primRhs;
1556 theCoPvec = &primVec;
1557 thePvec = &addVec;
1558 theRPvec = thePvec;
1559 theCPvec = theCoPvec;
1560 theUbound = &theURbound;
1561 theLbound = &theLRbound;
1562 theCoUbound = &theUCbound;
1563 theCoLbound = &theLCbound;
1564 }
1565
1566 SPxBasisBase<R>::theLP = this;
1567
1568 if(base.thepricer == 0)
1569 {
1570 thepricer = 0;
1571 freePricer = false;
1572 }
1573 else
1574 {
1575 thepricer = base.thepricer->clone();
1576 freePricer = true;
1577 thepricer->clear();
1578 thepricer->load(this);
1579 }
1580
1581 if(base.theratiotester == 0)
1582 {
1583 theratiotester = 0;
1584 freeRatioTester = false;
1585 }
1586 else
1587 {
1588 theratiotester = base.theratiotester->clone();
1589 freeRatioTester = true;
1590 theratiotester->clear();
1591 theratiotester->load(this);
1592 }
1593
1594 if(base.thestarter == 0)
1595 {
1596 thestarter = 0;
1597 freeStarter = false;
1598 }
1599 else
1600 {
1601 thestarter = base.thestarter->clone();
1602 freeStarter = true;
1603 }
1604
1605 assert(SPxSolverBase<R>::isConsistent());
1606 }
1607
1608 template <class R>
1609 bool SPxSolverBase<R>::isConsistent() const
1610 {
1611 #ifdef ENABLE_CONSISTENCY_CHECKS
1612
1613 if(epsilon() < 0)
1614 return MSGinconsistent("SPxSolverBase");
1615
1616 if(primVec.delta().getEpsilon() != dualVec.delta().getEpsilon())
1617 return MSGinconsistent("SPxSolverBase");
1618
1619 if(dualVec.delta().getEpsilon() != addVec.delta().getEpsilon())
1620 return MSGinconsistent("SPxSolverBase");
1621
1622 if(unitVecs.size() < SPxLPBase<R>::nCols() || unitVecs.size() < SPxLPBase<R>::nRows())
1623 return MSGinconsistent("SPxSolverBase");
1624
1625 if(initialized)
1626 {
1627 if(theFrhs->dim() != dim())
1628 return MSGinconsistent("SPxSolverBase");
1629
1630 if(theFvec->dim() != dim())
1631 return MSGinconsistent("SPxSolverBase");
1632
1633 if(theCoPrhs->dim() != dim())
1634 return MSGinconsistent("SPxSolverBase");
1635
1636 if(thePvec->dim() != coDim())
1637 return MSGinconsistent("SPxSolverBase");
1638
1639 if(theCoPvec->dim() != dim())
1640 return MSGinconsistent("SPxSolverBase");
1641
1642 if(theTest.dim() != coDim())
1643 return MSGinconsistent("SPxSolverBase");
1644
1645 if(theCoTest.dim() != dim())
1646 return MSGinconsistent("SPxSolverBase");
1647
1648 if(theURbound.dim() != SPxLPBase<R>::nRows())
1649 return MSGinconsistent("SPxSolverBase");
1650
1651 if(theLRbound.dim() != SPxLPBase<R>::nRows())
1652 return MSGinconsistent("SPxSolverBase");
1653
1654 if(theUCbound.dim() != SPxLPBase<R>::nCols())
1655 return MSGinconsistent("SPxSolverBase");
1656
1657 if(theLCbound.dim() != SPxLPBase<R>::nCols())
1658 return MSGinconsistent("SPxSolverBase");
1659
1660 if(theUBbound.dim() != dim())
1661 return MSGinconsistent("SPxSolverBase");
1662
1663 if(theLBbound.dim() != dim())
1664 return MSGinconsistent("SPxSolverBase");
1665 }
1666
1667 if(rep() == COLUMN)
1668 {
1669 if(thecovectors !=
1670 reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPRowSetBase<R>*>(this))
1671 || thevectors !=
1672 reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPColSet*>(this))
1673 || theFrhs != &primRhs ||
1674 theFvec != &primVec ||
1675 theCoPrhs != &dualRhs ||
1676 theCoPvec != &dualVec ||
1677 thePvec != &addVec ||
1678 theRPvec != theCoPvec ||
1679 theCPvec != thePvec ||
1680 theUbound != &theUCbound ||
1681 theLbound != &theLCbound ||
1682 theCoUbound != &theURbound ||
1683 theCoLbound != &theLRbound)
1684 return MSGinconsistent("SPxSolverBase");
1685 }
1686 else
1687 {
1688 if(thecovectors
1689 != reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPColSet*>(this))
1690 || thevectors
1691 != reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPRowSetBase<R>*>(this))
1692 || theFrhs != &dualRhs ||
1693 theFvec != &dualVec ||
1694 theCoPrhs != &primRhs ||
1695 theCoPvec != &primVec ||
1696 thePvec != &addVec ||
1697 theRPvec != thePvec ||
1698 theCPvec != theCoPvec ||
1699 theUbound != &theURbound ||
1700 theLbound != &theLRbound ||
1701 theCoUbound != &theUCbound ||
1702 theCoLbound != &theLCbound)
1703 return MSGinconsistent("SPxSolverBase");
1704 }
1705
1706 return SPxLPBase<R>::isConsistent()
1707 && primRhs.isConsistent()
1708 && primVec.isConsistent()
1709 && dualRhs.isConsistent()
1710 && dualVec.isConsistent()
1711 && addVec.isConsistent()
1712 && theTest.isConsistent()
1713 && theCoTest.isConsistent()
1714 && theURbound.isConsistent()
1715 && theLRbound.isConsistent()
1716 && theUCbound.isConsistent()
1717 && theLCbound.isConsistent()
1718 && SPxBasisBase<R>::isConsistent()
1719 ;
1720 #else
1721 return true;
1722 #endif
1723 }
1724
1725
1726 template <class R>
1727 void SPxSolverBase<R>::setTerminationTime(Real p_time)
1728 {
1729 if(p_time < 0.0)
1730 p_time = 0.0;
1731
1732 maxTime = p_time;
1733 }
1734
1735 template <class R>
1736 Real SPxSolverBase<R>::terminationTime() const
1737 {
1738 return maxTime;
1739 }
1740
1741 template <class R>
1742 void SPxSolverBase<R>::setTerminationIter(int p_iteration)
1743 {
1744 if(p_iteration < 0)
1745 p_iteration = -1;
1746
1747 maxIters = p_iteration;
1748 }
1749
1750 template <class R>
1751 int SPxSolverBase<R>::terminationIter() const
1752 {
1753 return maxIters;
1754 }
1755
1756 // returns whether current time limit is reached; call to time() may be skipped unless \p forceCheck is true
1757 template <class R>
1758 bool SPxSolverBase<R>::isTimeLimitReached(const bool forceCheck)
1759 {
1760 // always update the number of calls, since the user might set a time limit later in the solving process
1761 ++nCallsToTimelim;
1762
1763 // check if a time limit is actually set
1764 if(maxTime >= R(infinity))
1765 return false;
1766
1767 // check if the expensive system call to update the time should be skipped again
1768 if(forceCheck || nCallsToTimelim < NINITCALLS || nClckSkipsLeft <= 0)
1769 {
1770 Real currtime = time();
1771
1772 if(currtime >= maxTime)
1773 return true;
1774
1775 // determine the number of times the clock can be skipped again.
1776 int nClckSkips = MAXNCLCKSKIPS;
1777 Real avgtimeinterval = (currtime + cumulativeTime()) / (Real)(nCallsToTimelim);
1778
1779 // it would not be safe to skip the clock so many times since we are approaching the time limit
1780 if(SAFETYFACTOR * (maxTime - currtime) / (avgtimeinterval + 1e-6) < nClckSkips)
1781 nClckSkips = 0;
1782
1783 nClckSkipsLeft = nClckSkips;
1784 }
1785 else
1786 --nClckSkipsLeft;
1787
1788 return false;
1789 }
1790
1791
1792 /**@todo A first version for the termination value is
1793 * implemented. Currently we check if no bound violations (shifting)
1794 * is present. It might be even possible to use this termination
1795 * value in case of bound violations (shifting) but in this case it
1796 * is quite difficult to determine if we already reached the limit.
1797 */
1798 template <class R>
1799 void SPxSolverBase<R>::setTerminationValue(R p_value)
1800 {
1801 objLimit = p_value;
1802 }
1803
1804 template <class R>
1805 R SPxSolverBase<R>::terminationValue() const
1806 {
1807 return objLimit;
1808 }
1809
1810 template <class R>
1811 typename SPxSolverBase<R>::VarStatus
1812 SPxSolverBase<R>::basisStatusToVarStatus(typename SPxBasisBase<R>::Desc::Status stat) const
1813 {
1814 VarStatus vstat;
1815
1816 switch(stat)
1817 {
1818 case SPxBasisBase<R>::Desc::P_ON_LOWER:
1819 vstat = ON_LOWER;
1820 break;
1821
1822 case SPxBasisBase<R>::Desc::P_ON_UPPER:
1823 vstat = ON_UPPER;
1824 break;
1825
1826 case SPxBasisBase<R>::Desc::P_FIXED:
1827 vstat = FIXED;
1828 break;
1829
1830 case SPxBasisBase<R>::Desc::P_FREE:
1831 vstat = ZERO;
1832 break;
1833
1834 case SPxBasisBase<R>::Desc::D_ON_UPPER:
1835 case SPxBasisBase<R>::Desc::D_ON_LOWER:
1836 case SPxBasisBase<R>::Desc::D_ON_BOTH:
1837 case SPxBasisBase<R>::Desc::D_UNDEFINED:
1838 case SPxBasisBase<R>::Desc::D_FREE:
1839 vstat = BASIC;
1840 break;
1841
1842 default:
1843 MSG_ERROR(std::cerr << "ESOLVE26 ERROR: unknown basis status (" << static_cast<int>(stat) << ")"
1844 << std::endl;)
1845 throw SPxInternalCodeException("XSOLVE22 This should never happen.");
1846 }
1847
1848 return vstat;
1849 }
1850
1851 template <class R>
1852 typename SPxBasisBase<R>::Desc::Status
1853 SPxSolverBase<R>::varStatusToBasisStatusRow(int row,
1854 typename SPxSolverBase<R>::VarStatus stat) const
1855 {
1856 typename SPxBasisBase<R>::Desc::Status rstat;
1857
1858 switch(stat)
1859 {
1860 case FIXED :
1861 assert(EQ(this->rhs(row), this->lhs(row), feastol()));
1862 rstat = SPxBasisBase<R>::Desc::P_FIXED;
1863 break;
1864
1865 case ON_UPPER :
1866 assert(this->rhs(row) < R(infinity));
1867 rstat = this->lhs(row) < this->rhs(row)
1868 ? SPxBasisBase<R>::Desc::P_ON_UPPER
1869 : SPxBasisBase<R>::Desc::P_FIXED;
1870 break;
1871
1872 case ON_LOWER :
1873 assert(this->lhs(row) > R(-infinity));
1874 rstat = this->lhs(row) < this->rhs(row)
1875 ? SPxBasisBase<R>::Desc::P_ON_LOWER
1876 : SPxBasisBase<R>::Desc::P_FIXED;
1877 break;
1878
1879 case ZERO :
1880 /* A 'free' row (i.e., infinite lower & upper bounds) does not really make sense. The user
1881 * might (think to) know better, e.g., when temporarily turning off a row. We therefore apply
1882 * the same adjustment as in the column case in varStatusToBasisStatusCol(). */
1883 rstat = SPxBasisBase<R>::Desc::P_FREE;
1884 break;
1885
1886 case BASIC :
1887 rstat = this->dualRowStatus(row);
1888 break;
1889
1890 default:
1891 MSG_ERROR(std::cerr << "ESOLVE27 ERROR: unknown VarStatus (" << int(stat) << ")"
1892 << std::endl;)
1893 throw SPxInternalCodeException("XSOLVE23 This should never happen.");
1894 }
1895
1896 return rstat;
1897 }
1898
1899 template <class R>
1900 typename SPxBasisBase<R>::Desc::Status
1901 SPxSolverBase<R>::varStatusToBasisStatusCol(int col,
1902 typename SPxSolverBase<R>::VarStatus stat) const
1903 {
1904 typename SPxBasisBase<R>::Desc::Status cstat;
1905
1906 switch(stat)
1907 {
1908 case FIXED :
1909 if(this->upper(col) == this->lower(col))
1910 cstat = SPxBasisBase<R>::Desc::P_FIXED;
1911 else if(this->maxObj(col) > 0.0)
1912 cstat = SPxBasisBase<R>::Desc::P_ON_UPPER;
1913 else
1914 cstat = SPxBasisBase<R>::Desc::P_ON_LOWER;
1915
1916 break;
1917
1918 case ON_UPPER :
1919 assert(this->upper(col) < R(infinity));
1920 cstat = this->lower(col) < this->upper(col)
1921 ? SPxBasisBase<R>::Desc::P_ON_UPPER
1922 : SPxBasisBase<R>::Desc::P_FIXED;
1923 break;
1924
1925 case ON_LOWER :
1926 assert(this->lower(col) > R(-infinity));
1927 cstat = this->lower(col) < this->upper(col)
1928 ? SPxBasisBase<R>::Desc::P_ON_LOWER
1929 : SPxBasisBase<R>::Desc::P_FIXED;
1930 break;
1931
1932 case ZERO :
1933
1934 /* In this case the upper and lower bounds on the variable should be infinite. The bounds
1935 * might, however, have changed and we try to recover from this by changing the status to
1936 * 'resonable' settings. Since the status should be implicit free we still always set it
1937 * to P_FREE to be consistent */
1938 cstat = SPxBasisBase<R>::Desc::P_FREE;
1939 break;
1940
1941 case BASIC :
1942 cstat = this->dualColStatus(col);
1943 break;
1944
1945 default:
1946 MSG_ERROR(std::cerr << "ESOLVE28 ERROR: unknown VarStatus (" << int(stat) << ")"
1947 << std::endl;)
1948 throw SPxInternalCodeException("XSOLVE24 This should never happen.");
1949 }
1950
1951 return cstat;
1952 }
1953
1954 template <class R>
1955 typename SPxSolverBase<R>::VarStatus SPxSolverBase<R>::getBasisRowStatus(int row) const
1956 {
1957 assert(0 <= row && row < this->nRows());
1958 return basisStatusToVarStatus(this->desc().rowStatus(row));
1959 }
1960
1961 template <class R>
1962 typename SPxSolverBase<R>::VarStatus SPxSolverBase<R>::getBasisColStatus(int col) const
1963 {
1964 assert(0 <= col && col < this->nCols());
1965 return basisStatusToVarStatus(this->desc().colStatus(col));
1966 }
1967
1968 template <class R>
1969 typename SPxSolverBase<R>::Status SPxSolverBase<R>::getBasis(VarStatus row[], VarStatus col[],
1970 const int rowsSize, const int colsSize) const
1971 {
1972 const typename SPxBasisBase<R>::Desc& d = this->desc();
1973 int i;
1974
1975 assert(rowsSize < 0 || rowsSize >= this->nRows());
1976 assert(colsSize < 0 || colsSize >= this->nCols());
1977
1978 if(col)
1979 for(i = this->nCols() - 1; i >= 0; --i)
1980 col[i] = basisStatusToVarStatus(d.colStatus(i));
1981
1982 if(row)
1983 for(i = this->nRows() - 1; i >= 0; --i)
1984 row[i] = basisStatusToVarStatus(d.rowStatus(i));
1985
1986 return status();
1987 }
1988
1989 template <class R>
1990 bool SPxSolverBase<R>::isBasisValid(DataArray<VarStatus> p_rows, DataArray<VarStatus> p_cols)
1991 {
1992
1993 int basisdim;
1994
1995 if(p_rows.size() != this->nRows() || p_cols.size() != this->nCols())
1996 return false;
1997
1998 basisdim = 0;
1999
2000 for(int row = this->nRows() - 1; row >= 0; --row)
2001 {
2002 if(p_rows[row] == UNDEFINED)
2003 return false;
2004 // row is basic
2005 else if(p_rows[row] == BASIC)
2006 {
2007 basisdim++;
2008 }
2009 // row is nonbasic
2010 else
2011 {
2012 if((p_rows[row] == FIXED && this->lhs(row) != this->rhs(row))
2013 || (p_rows[row] == ON_UPPER && this->rhs(row) >= R(infinity))
2014 || (p_rows[row] == ON_LOWER && this->lhs(row) <= R(-infinity)))
2015 return false;
2016 }
2017 }
2018
2019 for(int col = this->nCols() - 1; col >= 0; --col)
2020 {
2021 if(p_cols[col] == UNDEFINED)
2022 return false;
2023 // col is basic
2024 else if(p_cols[col] == BASIC)
2025 {
2026 basisdim++;
2027 }
2028 // col is nonbasic
2029 else
2030 {
2031 if((p_cols[col] == FIXED && this->lower(col) != this->upper(col))
2032 || (p_cols[col] == ON_UPPER && this->upper(col) >= R(infinity))
2033 || (p_cols[col] == ON_LOWER && this->lower(col) <= R(-infinity)))
2034 return false;
2035 }
2036 }
2037
2038 if(basisdim != dim())
2039 return false;
2040
2041 // basis valid
2042 return true;
2043 }
2044
2045 template <class R>
2046 void SPxSolverBase<R>::setBasis(const VarStatus p_rows[], const VarStatus p_cols[])
2047 {
2048 if(SPxBasisBase<R>::status() == SPxBasisBase<R>::NO_PROBLEM)
2049 SPxBasisBase<R>::load(this, false);
2050
2051 typename SPxBasisBase<R>::Desc ds = this->desc();
2052 int i;
2053
2054 for(i = 0; i < this->nRows(); i++)
2055 ds.rowStatus(i) = varStatusToBasisStatusRow(i, p_rows[i]);
2056
2057 for(i = 0; i < this->nCols(); i++)
2058 ds.colStatus(i) = varStatusToBasisStatusCol(i, p_cols[i]);
2059
2060 loadBasis(ds);
2061 forceRecompNonbasicValue();
2062 }
2063
2064 // NOTE: This only works for the row representation. Need to update to account for column representation.
2065 // The degenvec differs relative to the algorithm being used.
2066 // For the primal simplex, degenvec is the primal solution values.
2067 // For the dual simplex, the degenvec is the feasvec (ROW) and pVec (COLUMN).
2068 template <class R>
2069 R SPxSolverBase<R>::getDegeneracyLevel(VectorBase<R> degenvec)
2070 {
2071 int numDegenerate = 0;
2072 R degeneracyLevel = 0;
2073
2074 // iterating over all columns in the basis matrix
2075 // this identifies the basis indices and those that have a zero dual multiplier (rows) or zero reduced cost (cols).
2076 if(rep() == ROW)
2077 {
2078 for(int i = 0; i < this->nCols();
2079 ++i) // @todo Check the use of numColsReal for the reduced problem.
2080 {
2081 // degeneracy in the dual simplex exists if there are rows with a zero dual multiplier or columns with a zero
2082 // reduced costs. This requirement is regardless of the objective sense.
2083 if(isZero(degenvec[i], feastol()))
2084 numDegenerate++;
2085 }
2086
2087 if(type() == ENTER) // dual simplex
2088 degeneracyLevel = R(numDegenerate) / this->nCols();
2089 else // primal simplex
2090 {
2091 assert(type() == LEAVE);
2092 R degenVars = (numDegenerate > (this->nCols() - this->nRows())) ? R(numDegenerate -
2093 (this->nCols() - this->nRows())) : 0.0;
2094 degeneracyLevel = degenVars / this->nRows();
2095 }
2096 }
2097 else
2098 {
2099 assert(rep() == COLUMN);
2100
2101 for(int i = 0; i < this->nCols(); i++)
2102 {
2103 if(type() == LEAVE) // dual simplex
2104 {
2105 if(isZero(this->maxObj()[i] - degenvec[i], feastol()))
2106 numDegenerate++;
2107 }
2108 else // primal simplex
2109 {
2110 assert(type() == ENTER);
2111
2112 if(isZero(degenvec[i], feastol()))
2113 numDegenerate++;
2114 }
2115 }
2116
2117
2118 if(type() == LEAVE) // dual simplex
2119 {
2120 R degenVars = this->nRows() > numDegenerate ? R(this->nRows() - numDegenerate) : 0.0;
2121 degeneracyLevel = degenVars / this->nCols();
2122 }
2123 else // primal simplex
2124 {
2125 assert(type() == ENTER);
2126 R degenVars = (numDegenerate > (this->nCols() - this->nRows())) ? R(numDegenerate -
2127 (this->nCols() - this->nRows())) : 0.0;
2128 degeneracyLevel = degenVars / this->nRows();
2129 }
2130 }
2131
2132 return degeneracyLevel;
2133 }
2134
2135 template <class R>
2136 void SPxSolverBase<R>::getNdualNorms(int& nnormsRow, int& nnormsCol) const
2137 {
2138 nnormsRow = 0;
2139 nnormsCol = 0;
2140
2141 if(weightsAreSetup)
2142 {
2143 if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN)
2144 {
2145 nnormsRow = coWeights.dim();
2146 nnormsCol = 0;
2147
2148 assert(nnormsRow == dim());
2149 }
2150 else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW)
2151 {
2152 nnormsRow = weights.dim();
2153 nnormsCol = coWeights.dim();
2154
2155 assert(nnormsRow == coDim());
2156 assert(nnormsCol == dim());
2157 }
2158 }
2159 }
2160
2161 template <class R>
2162 bool SPxSolverBase<R>::getDualNorms(int& nnormsRow, int& nnormsCol, R * norms) const
2163 {
2164 nnormsRow = 0;
2165 nnormsCol = 0;
2166
2167 if(!weightsAreSetup)
2168 return false;
2169
2170 if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN)
2171 {
2172 nnormsCol = 0;
2173 nnormsRow = coWeights.dim();
2174
2175 assert(nnormsRow == dim());
2176
2177 for(int i = 0; i < nnormsRow; ++i)
2178 norms[i] = coWeights[i];
2179 }
2180 else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW)
2181 {
2182 nnormsRow = weights.dim();
2183 nnormsCol = coWeights.dim();
2184
2185 assert(nnormsCol == dim());
2186 assert(nnormsRow == coDim());
2187
2188 for(int i = 0; i < nnormsRow; ++i)
2189 norms[i] = weights[i];
2190
2191 for(int i = 0; i < nnormsCol; ++i)
2192 norms[nnormsRow + i] = coWeights[i];
2193 }
2194 else
2195 return false;
2196
2197 return true;
2198 }
2199
2200 template <class R>
2201 bool SPxSolverBase<R>::setDualNorms(int nnormsRow, int nnormsCol, R * norms)
2202 {
2203 weightsAreSetup = false;
2204
2205 if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN)
2206 {
2207 coWeights.reDim(dim(), false);
2208 assert(coWeights.dim() >= nnormsRow);
2209
2210 for(int i = 0; i < nnormsRow; ++i)
2211 coWeights[i] = norms[i];
2212
2213 weightsAreSetup = true;
2214 }
2215 else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW)
2216 {
2217 weights.reDim(coDim(), false);
2218 coWeights.reDim(dim(), false);
2219 assert(weights.dim() >= nnormsRow);
2220 assert(coWeights.dim() >= nnormsCol);
2221
2222 for(int i = 0; i < nnormsRow; ++i)
2223 weights[i] = norms[i];
2224
2225 for(int i = 0; i < nnormsCol; ++i)
2226 coWeights[i] = norms[nnormsRow + i];
2227
2228 weightsAreSetup = true;
2229 }
2230 else
2231 return false;
2232
2233 return true;
2234 }
2235
2236 template <class R>
2237 void SPxSolverBase<R>::setIntegralityInformation(int ncols, int* intInfo)
2238 {
2239 assert(ncols == this->nCols() || (ncols == 0 && intInfo == NULL));
2240
2241 integerVariables.reSize(ncols);
2242
2243 for(int i = 0; i < ncols; ++i)
2244 {
2245 integerVariables[i] = intInfo[i];
2246 }
2247 }
2248
2249
2250
2251 //
2252 // Auxiliary functions.
2253 //
2254
2255 // Pretty-printing of variable status.
2256 template <class R>
2257 std::ostream& operator<<(std::ostream & os,
2258 const typename SPxSolverBase<R>::VarStatus & status)
2259 {
2260 switch(status)
2261 {
2262 case SPxSolverBase<R>::BASIC:
2263 os << "BASIC";
2264 break;
2265
2266 case SPxSolverBase<R>::FIXED:
2267 os << "FIXED";
2268 break;
2269
2270 case SPxSolverBase<R>::ON_LOWER:
2271 os << "ON_LOWER";
2272 break;
2273
2274 case SPxSolverBase<R>::ON_UPPER:
2275 os << "ON_UPPER";
2276 break;
2277
2278 case SPxSolverBase<R>::ZERO:
2279 os << "ZERO";
2280 break;
2281
2282 case SPxSolverBase<R>::UNDEFINED:
2283 os << "UNDEFINED";
2284 break;
2285
2286 default:
2287 os << "?invalid?";
2288 break;
2289 }
2290
2291 return os;
2292 }
2293
2294 // Pretty-printing of solver status.
2295 template <class R>
2296 std::ostream& operator<<(std::ostream & os,
2297 const typename SPxSolverBase<R>::Status & status)
2298 {
2299 switch(status)
2300 {
2301 case SPxSolverBase<R>::ERROR:
2302 os << "ERROR";
2303 break;
2304
2305 case SPxSolverBase<R>::NO_RATIOTESTER:
2306 os << "NO_RATIOTESTER";
2307 break;
2308
2309 case SPxSolverBase<R>::NO_PRICER:
2310 os << "NO_PRICER";
2311 break;
2312
2313 case SPxSolverBase<R>::NO_SOLVER:
2314 os << "NO_SOLVER";
2315 break;
2316
2317 case SPxSolverBase<R>::NOT_INIT:
2318 os << "NOT_INIT";
2319 break;
2320
2321 case SPxSolverBase<R>::ABORT_CYCLING:
2322 os << "ABORT_CYCLING";
2323 break;
2324
2325 case SPxSolverBase<R>::ABORT_TIME:
2326 os << "ABORT_TIME";
2327 break;
2328
2329 case SPxSolverBase<R>::ABORT_ITER:
2330 os << "ABORT_ITER";
2331 break;
2332
2333 case SPxSolverBase<R>::ABORT_VALUE:
2334 os << "ABORT_VALUE";
2335 break;
2336
2337 case SPxSolverBase<R>::SINGULAR:
2338 os << "SINGULAR";
2339 break;
2340
2341 case SPxSolverBase<R>::NO_PROBLEM:
2342 os << "NO_PROBLEM";
2343 break;
2344
2345 case SPxSolverBase<R>::REGULAR:
2346 os << "REGULAR";
2347 break;
2348
2349 case SPxSolverBase<R>::RUNNING:
2350 os << "RUNNING";
2351 break;
2352
2353 case SPxSolverBase<R>::UNKNOWN:
2354 os << "UNKNOWN";
2355 break;
2356
2357 case SPxSolverBase<R>::OPTIMAL:
2358 os << "OPTIMAL";
2359 break;
2360
2361 case SPxSolverBase<R>::UNBOUNDED:
2362 os << "UNBOUNDED";
2363 break;
2364
2365 case SPxSolverBase<R>::INFEASIBLE:
2366 os << "INFEASIBLE";
2367 break;
2368
2369 default:
2370 os << "?other?";
2371 break;
2372 }
2373
2374 return os;
2375 }
2376
2377 // Pretty-printing of algorithm.
2378 template <class R>
2379 std::ostream& operator<<(std::ostream & os,
2380 const typename SPxSolverBase<R>::Type & status)
2381 {
2382 switch(status)
2383 {
2384 case SPxSolverBase<R>::ENTER:
2385 os << "ENTER";
2386 break;
2387
2388 case SPxSolverBase<R>::LEAVE:
2389 os << "LEAVE";
2390 break;
2391
2392 default:
2393 os << "?other?";
2394 break;
2395 }
2396
2397 return os;
2398 }
2399
2400 // Pretty-printing of representation.
2401 template <class R>
2402 std::ostream& operator<<(std::ostream & os,
2403 const typename SPxSolverBase<R>::Representation & status)
2404 {
2405 switch(status)
2406 {
2407 case SPxSolverBase<R>::ROW:
2408 os << "ROW";
2409 break;
2410
2411 case SPxSolverBase<R>::COLUMN:
2412 os << "COLUMN";
2413 break;
2414
2415 default:
2416 os << "?other?";
2417 break;
2418 }
2419
2420 return os;
2421 }
2422
2423
2424 } // namespace soplex
2425