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