Scippy

SoPlex

Sequential object-oriented simPlex

changesoplex.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2015 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 
19 #include "spxdefines.h"
20 #include "spxsolver.h"
21 #include "spxpricer.h"
22 #include "spxratiotester.h"
23 #include "exceptions.h"
24 
25 namespace soplex
26 {
27 
28 #if 0
29 void SPxSolver::localAddRows(int start)
30 {
31  assert( start <= SPxLP::nRows() );
32 
33  /**@todo This method seems to be called, to update
34  * theFvec, theFrhs, ..., but a resolve after
35  * adding a row results in a failure.
36  * To fix this, we call unInit() so that init() is called before solving
37  * in spxsolve.cpp:solve(). In init(), the
38  * vectors are set up, so there is no need
39  * to update them here.
40  */
41  if( start == SPxLP::nRows() )
42  return;
43 
44  const SPxBasis::Desc& ds = desc();
45 
46  if (type() == ENTER)
47  {
48  if (rep() == COLUMN)
49  {
50  int i;
51  for (i = start; i < SPxLP::nRows(); ++i)
52  {
53  theURbound[i] = -lhs(i);
54  theLRbound[i] = -rhs(i);
55  setEnterBound4Row(i, i);
57  // init #theFrhs[i]#:
58  Real& v_rhs = (*theFrhs)[i];
59  const SVector& row = rowVector(i);
60  v_rhs = 0;
61  for (int j = row.size() - 1; j >= 0; --j)
62  {
63  int idx = row.index(j);
64  switch (ds.colStatus(idx))
65  {
66  case Desc::P_ON_UPPER:
67  v_rhs += row.value(j) * theUCbound[idx];
68  break;
69  case Desc::P_ON_LOWER:
70  case Desc::P_FIXED:
71  v_rhs += row.value(j) * theLCbound[idx];
72  break;
73  default:
74  break;
75  }
76  }
77  }
80  for (i = start; i < SPxLP::nRows(); ++i)
81  {
82  /* we need to compare with tolerance (rep() == COLUMN) ? feastol() : opttol() because theFvec is the primal
83  * vector in COLUMN and the dual vector in ROW representation; this is equivalent to entertol(); this also
84  * fits because we are within the "type() == ENTER" case
85  */
86  if (theUBbound[i] + entertol() < (*theFvec)[i])
87  shiftUBbound(i, (*theFvec)[i]);
88  else if ((*theFvec)[i] < theLBbound[i] - entertol())
89  shiftLBbound(i, (*theFvec)[i]);
90  }
91  computePvec();
92  computeCoTest();
93  computeTest();
94  }
95  else
96  {
97  assert(rep() == ROW);
98  for (int i = start; i < SPxLP::nRows(); ++i)
99  {
100  theURbound[i] = theLRbound[i] = maxRowObj(i);
102  theURbound[i], theLRbound[i]);
103  (*thePvec)[i] = vector(i) * (*theCoPvec);
104  theTest[i] = test(i, ds.status(i));
105  }
106  }
107  }
108  else
109  {
110  assert(type() == LEAVE);
111  if (rep() == ROW)
112  {
113  for (int i = start; i < SPxLP::nRows(); ++i)
114  {
115  theURbound[i] = rhs(i);
116  theLRbound[i] = lhs(i);
117  (*thePvec)[i] = vector(i) * (*theCoPvec);
118 
119  /* we need to compare with tolerance (rep() == ROW) ? feastol() : opttol() because thePvec is the primal
120  * vector in ROW and the dual vector in COLUMN representation; this is equivalent to leavetol(); this also
121  * fits because we are within the "type() == LEAVE" case
122  */
123  if (theURbound[i] + leavetol() < (*thePvec)[i])
124  shiftUPbound(i, (*thePvec)[i]);
125  else if ((*thePvec)[i] < theLRbound[i] - leavetol())
126  shiftLPbound(i, (*thePvec)[i]);
127  }
128  }
129  else
130  {
131  assert(rep() == COLUMN);
132  int i;
133  for (i = start; i < SPxLP::nRows(); ++i)
134  {
135  theURbound[i] = theLRbound[i] = maxRowObj(i);
136  clearDualBounds(ds.rowStatus(i),
137  theURbound[i], theLRbound[i]);
138  setLeaveBound4Row(i, i);
140  // init #theFrhs[i]#
141  Real& v_rhs = (*theFrhs)[i];
142  const SVector& row = rowVector(i);
143  v_rhs = 0;
144  for (int j = row.size() - 1; j >= 0; --j)
145  {
146  int idx = row.index(j);
147  switch (ds.colStatus(idx))
148  {
149  case Desc::P_ON_UPPER:
150  v_rhs += row.value(j) * SPxLP::upper(idx);
151  break;
152  case Desc::P_ON_LOWER:
153  case Desc::P_FIXED:
154  v_rhs += row.value(j) * SPxLP::lower(idx);
155  break;
156  default:
157  break;
158  }
159  }
160  }
163  for (i = start; i < SPxLP::nRows(); ++i)
164  {
165  if ((*theFvec)[i] > theUBbound[i])
166  theCoTest[i] = theUBbound[i] - (*theFvec)[i];
167  else
168  theCoTest[i] = (*theFvec)[i] - theLBbound[i];
169  }
170  }
171  }
172 }
173 
174 void SPxSolver::addedRows(int n)
175 {
176 
177  SPxLP::addedRows(n);
178 
179  if( n > 0 )
180  {
181  reDim();
182 
184  {
186 
187  if (isInitialized())
188  {
189  localAddRows(nRows() - n);
190 
191  assert(thepricer != 0);
192 
193  if (rep() == ROW)
194  thepricer->addedVecs(n);
195  else
196  thepricer->addedCoVecs(n);
197  }
198  }
199  }
200 
201  /* we must not assert consistency here, since addedCols() might be still necessary to obtain a consistent basis */
202 }
203 #endif //0
204 
206 {
207 
208  if( n > 0 )
209  {
210  SPxLP::addedRows(n);
211 
212  unInit();
213  reDim();
214 
217  }
218 
219  /* we must not assert consistency here, since addedCols() might be still necessary to obtain a consistent basis */
220 }
221 
222 #if 0
223 void SPxSolver::localAddCols(int start)
224 {
225  assert( start <= SPxLP::nCols() );
226 
227  /**@todo This method seems to be called, to update
228  * theFvec, theFrhs, ..., but a resolve after
229  * adding a row results in a failure.
230  * To fix this, we call unIinit() so that init() is called before solving
231  * in spxsolve.cpp:solve(). In init(), the
232  * vectors are set up, so there is no need
233  * to update them here.
234  */
235  if( start == SPxLP::nCols() )
236  return;
237 
238  const SPxBasis::Desc& ds = desc();
239 
240  if (type() == ENTER)
241  {
242  if (rep() == COLUMN)
243  {
244  int reSolve = 0;
245  int i;
246  Real x;
247  for (i = start; i < SPxLP::nCols(); ++i)
248  {
249  (*thePvec)[i] = vector(i) * (*theCoPvec);
250  theTest[i] = test(i, ds.colStatus(i));
251  theUCbound[i] = SPxLP::upper(i);
252  theLCbound[i] = SPxLP::lower(i);
253  switch (ds.colStatus(i))
254  {
256  assert(SPxLP::lower(i) == SPxLP::upper(i));
257  /*FALLTHROUGH*/
259  x = SPxLP::upper(i);
260  break;
262  x = SPxLP::lower(i);
263  break;
264  default:
265  x = 0;
266  break;
267  }
268  if (x)
269  {
270  theFrhs->multAdd(-x, vector(i));
271  reSolve = 1;
272  }
273  }
274  if (reSolve)
275  {
277  shiftFvec();
278  }
279  }
280  else
281  {
282  int i;
283  for (i = start; i < SPxLP::nCols(); ++i)
284  {
285  theUCbound[i] = theLCbound[i] = 0;
286  (*theFrhs)[i] = SPxLP::spxSense() * SPxLP::obj(i);
288  theUCbound[i], theLCbound[i]);
289  setEnterBound4Col(i, i);
291  }
293  computePvec();
294  computeCoTest();
295  computeTest();
297  for (i = start; i < SPxLP::nCols(); ++i)
298  {
299  /* we need to compare with tolerance (rep() == COLUMN) ? feastol() : opttol() because theFvec is the primal
300  * vector in COLUMN and the dual vector in ROW representation; this is equivalent to entertol(); this also
301  * fits because we are within the "type() == ENTER" case
302  */
303  if (theUBbound[i] + entertol() < (*theFvec)[i])
304  shiftUBbound(i, (*theFvec)[i]);
305  if ((*theFvec)[i] < theLBbound[i] - entertol())
306  shiftLBbound(i, (*theFvec)[i]);
307  }
308  }
309  }
310  else
311  {
312  if (rep() == ROW)
313  {
314  int i;
315  for (i = start; i < SPxLP::nCols(); ++i)
316  {
317  theUCbound[i] = SPxLP::upper(i);
318  theLCbound[i] = SPxLP::lower(i);
319  (*theFrhs)[i] = SPxLP::spxSense() * SPxLP::obj(i);
320  setLeaveBound4Col(i, i);
322  }
324  computePvec();
325  // shiftPvec();
327  for (i = start; i < SPxLP::nCols(); ++i)
328  {
329  if ((*theFvec)[i] > theUBbound[i])
330  theCoTest[i] = theUBbound[i] - (*theFvec)[i];
331  else
332  theCoTest[i] = (*theFvec)[i] - theLBbound[i];
333  }
334  }
335  else
336  {
337  Real x;
338  int i;
339  int reSolve = 0;
340  for (i = start; i < SPxLP::nCols(); ++i)
341  {
342  theUCbound[i] = theLCbound[i] = -maxObj(i);
344  theLCbound[i], theUCbound[i]);
345  theUCbound[i] *= -1;
346  theLCbound[i] *= -1;
347 
348  (*thePvec)[i] = vector(i) * (*theCoPvec);
349 
350  /* we need to compare with tolerance (rep() == ROW) ? feastol() : opttol() because thePvec is the primal
351  * vector in ROW and the dual vector in COLUMN representation; this is equivalent to leavetol(); this also
352  * fits because we are within the "type() == LEAVE" case
353  */
354  if (theUCbound[i] + leavetol() < (*thePvec)[i])
355  shiftUPbound(i, (*thePvec)[i]);
356  if (theLCbound[i] - leavetol() > (*thePvec)[i])
357  shiftLPbound(i, (*thePvec)[i]);
358 
359  switch (ds.colStatus(i))
360  {
362  assert(SPxLP::lower(i) == SPxLP::upper(i));
363  /*FALLTHROUGH*/
365  x = SPxLP::upper(i);
366  break;
368  x = SPxLP::lower(i);
369  break;
370  default:
371  x = 0;
372  break;
373  }
374  if (x)
375  {
376  theFrhs->multAdd(-x, vector(i));
377  reSolve = 1;
378  }
379  }
380  if (reSolve)
381  {
383  computeFtest();
384  }
385  }
386  }
387 }
388 
389 void SPxSolver::addedCols(int n)
390 {
391  SPxLP::addedCols(n);
392 
393  if( n > 0 )
394  {
395  reDim();
396 
398  {
400  if (isInitialized())
401  {
402  localAddCols(nCols() - n);
403  assert(thepricer != 0);
404  if (rep() == COLUMN)
405  thepricer->addedVecs(n);
406  else
408  }
409  }
410  }
411 
412  /* we must not assert consistency here, since addedRows() might be still necessary to obtain a consistent basis */
413 }
414 #endif //0
415 
417 {
418 
419  if( n > 0 )
420  {
421  SPxLP::addedCols(n);
422 
423  unInit();
424  reDim();
425 
428  }
429 
430  /* we must not assert consistency here, since addedRows() might be still necessary to obtain a consistent basis */
431 }
432 
434 {
435 
437 
438  unInit();
439 
441  {
442  removedRow(i);
443 
444 #if 0
445  if (isInitialized())
446  {
447  int n = SPxLP::nRows();
448 
449  theURbound[i] = theURbound[n];
450  theLRbound[i] = theLRbound[n];
451 
452  if (rep() == ROW)
453  {
454  (*thePvec)[i] = (*thePvec)[n];
455  if (type() == ENTER)
456  theTest[i] = theTest[n];
457  reDim();
458  assert(thepricer != 0);
459  thepricer->removedVec(i);
460  }
461  else
462  {
463  unInit();
464  }
465  }
466 #endif // 0
467 
468  switch (SPxBasis::status())
469  {
470  case SPxBasis::DUAL:
473  break;
474  case SPxBasis::OPTIMAL:
476  break;
477  default:
478  break;
479  }
480  }
481 }
482 
483 void SPxSolver::doRemoveRows(int perm[])
484 {
485 
486  SPxLP::doRemoveRows(perm);
487 
488  unInit();
489 
491  {
492  removedRows(perm);
493 #if 0
494  if (isInitialized())
495  {
496  int n = SPxLP::nRows();
497 
498  if (rep() == ROW)
499  {
500  if (type() == ENTER)
501  {
502  for (int i = 0; i < n; ++i)
503  if (perm[i] >= 0)
504  {
505  theURbound[perm[i]] = theURbound[i];
506  theLRbound[perm[i]] = theLRbound[i];
507  (*thePvec)[perm[i]] = (*thePvec)[i];
508  theTest[perm[i]] = theTest[i];
509  }
510  }
511  else
512  {
513  for (int i = 0; i < n; ++i)
514  if (perm[i] >= 0)
515  {
516  theURbound[perm[i]] = theURbound[i];
517  theLRbound[perm[i]] = theLRbound[i];
518  (*thePvec)[perm[i]] = (*thePvec)[i];
519  }
520  }
521  assert(thepricer != 0);
522  thepricer->removedVecs(perm);
523  reDim();
524  }
525  else
526  {
527  unInit();
528  }
529  }
530 #endif
531  switch (SPxBasis::status())
532  {
533  case SPxBasis::DUAL:
536  break;
537  case SPxBasis::OPTIMAL:
539  break;
540  default:
541  break;
542  }
543  }
544 }
545 
547 {
549 
551 
552  unInit();
553 
555  {
556  removedCol(i);
557 
558 #if 0
559  if (isInitialized())
560  {
561  int n = SPxLP::nCols();
562 
563  theUCbound[i] = theUCbound[n];
564  theLCbound[i] = theLCbound[n];
565  if (rep() == COLUMN)
566  {
567  (*thePvec)[i] = (*thePvec)[n];
568  if (type() == ENTER)
569  theTest[i] = theTest[n];
570  assert(thepricer != 0);
571  thepricer->removedVec(i);
572  reDim();
573  }
574  else
575  {
576  unInit();
577  }
578  }
579 #endif //0
580  switch (SPxBasis::status())
581  {
582  case SPxBasis::PRIMAL:
583  case SPxBasis::UNBOUNDED:
585  break;
586  case SPxBasis::OPTIMAL:
588  break;
589  default:
590  break;
591  }
592  }
593 }
594 
595 void SPxSolver::doRemoveCols(int perm[])
596 {
598 
599  SPxLP::doRemoveCols(perm);
600 
601  unInit();
602 
604  {
605  removedCols(perm);
606 
607 #if 0
608  if (isInitialized())
609  {
610  int n = SPxLP::nCols();
611 
612  if (rep() == COLUMN)
613  {
614  if (type() == ENTER)
615  {
616  for (int i = 0; i < n; ++i)
617  if (perm[i] >= 0)
618  {
619  theUCbound[perm[i]] = theUCbound[i];
620  theLCbound[perm[i]] = theLCbound[i];
621  (*thePvec)[perm[i]] = (*thePvec)[i];
622  theTest[perm[i]] = theTest[i];
623  }
624  }
625  else
626  {
627  for (int i = 0; i < n; ++i)
628  if (perm[i] >= 0)
629  {
630  theUCbound[perm[i]] = theUCbound[i];
631  theLCbound[perm[i]] = theLCbound[i];
632  (*thePvec)[perm[i]] = (*thePvec)[i];
633  }
634  }
635  assert(thepricer != 0);
636  thepricer->removedVecs(perm);
637  reDim();
638  }
639  else
640  {
641  unInit();
642  }
643  }
644 #endif //0
645  switch (SPxBasis::status())
646  {
647  case SPxBasis::PRIMAL:
648  case SPxBasis::UNBOUNDED:
650  break;
651  case SPxBasis::OPTIMAL:
653  break;
654  default:
655  break;
656  }
657  }
658 }
659 
660 void SPxSolver::changeObj(const Vector& newObj)
661 {
663 
664  SPxLP::changeObj(newObj);
665 
666  /**@todo Factorization remains valid, we do not need a reDim()
667  * pricing vectors should be recomputed.
668  */
669  unInit();
670 }
671 
672 void SPxSolver::changeObj(int i, const Real& newVal)
673 {
675 
676  SPxLP::changeObj(i, newVal);
677 
678 
679  /**@todo Factorization remains valid, we do not need a reDim()
680  * pricing vectors should be recomputed.
681  */
682  unInit();
683 }
684 
685 void SPxSolver::changeMaxObj(const Vector& newObj)
686 {
688 
689  SPxLP::changeMaxObj(newObj);
690 
691  /**@todo Factorization remains valid, we do not need a reDim()
692  * pricing vectors should be recomputed.
693  */
694  unInit();
695 }
696 
697 void SPxSolver::changeMaxObj(int i, const Real& newVal)
698 {
700 
701  SPxLP::changeMaxObj(i, newVal);
702 
703  /**@todo Factorization remains valid, we do not need a reDim()
704  * pricing vectors should be recomputed.
705  */
706  unInit();
707 }
708 
709 void SPxSolver::changeRowObj(const Vector& newObj)
710 {
712 
713  SPxLP::changeRowObj(newObj);
714 
715  /**@todo Factorization remains valid, we do not need a reDim()
716  * pricing vectors should be recomputed.
717  */
718  unInit();
719 }
720 
721 void SPxSolver::changeRowObj(int i, const Real& newVal)
722 {
724 
725  SPxLP::changeRowObj(i, newVal);
726 
727  /**@todo Factorization remains valid, we do not need a reDim()
728  * pricing vectors should be recomputed.
729  */
730  unInit();
731 }
732 
733 void SPxSolver::changeLowerStatus(int i, Real newLower, Real oldLower )
734 {
736  Real currUpper = upper(i);
737  Real objChange = 0.0;
738 
739  MSG_DEBUG( std::cout << "DCHANG01 changeLowerStatus(): col " << i
740  << "[" << newLower << ":" << currUpper << "] " << stat; )
741 
742  switch (stat)
743  {
745  if (newLower <= -infinity)
746  {
747  if (currUpper >= infinity)
748  {
749  stat = SPxBasis::Desc::P_FREE;
750  if( m_nonbasicValueUpToDate && rep() == COLUMN )
751  objChange = -theLCbound[i] * oldLower;
752  }
753  else
754  {
756  if( m_nonbasicValueUpToDate && rep() == COLUMN )
757  objChange = (theUCbound[i] * currUpper) - (theLCbound[i] * oldLower);
758  }
759  }
760  else if (newLower == currUpper)
761  {
763  if( m_nonbasicValueUpToDate && rep() == COLUMN )
764  objChange = maxObj(i) * (newLower - oldLower);
765  }
766  else if( m_nonbasicValueUpToDate && rep() == COLUMN )
767  objChange = theLCbound[i] * (newLower - oldLower);
768  break;
770  if (newLower == currUpper)
772  break;
774  if (newLower > -infinity)
775  {
777  if( m_nonbasicValueUpToDate && rep() == COLUMN )
778  objChange = theLCbound[i] * newLower;
779  }
780  break;
782  if (newLower != currUpper)
784  break;
790  if( rep() == ROW && theShift > 0.0 )
792  stat = dualColStatus(i);
793  break;
794  default:
795  throw SPxInternalCodeException("XCHANG01 This should never happen.");
796  }
797 
798  MSG_DEBUG( std::cout << " -> " << stat << std::endl; )
799 
800  // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation)
801  if( rep() == COLUMN )
802  updateNonbasicValue(objChange);
803 }
804 
805 void SPxSolver::changeLower(const Vector& newLower)
806 {
807  // we better recompute the nonbasic value when changing all lower bounds
809 
810  SPxLP::changeLower(newLower);
811 
813  {
814  for (int i = 0; i < newLower.dim(); ++i)
815  changeLowerStatus(i, newLower[i]);
816 
817  unInit();
818  }
819 }
820 
821 void SPxSolver::changeLower(int i, const Real& newLower)
822 {
823  Real oldLower = lower(i);
824 
825  if (newLower != oldLower)
826  {
827  // This has to be done before calling changeLowerStatus() because that is calling
828  // basis.dualColStatus() which calls lower() and needs the changed value.
829  SPxLP::changeLower(i, newLower);
830 
832  {
833  changeLowerStatus(i, newLower, oldLower);
834  unInit();
835  }
836  }
837 }
838 
839 void SPxSolver::changeUpperStatus(int i, Real newUpper, Real oldUpper)
840 {
842  Real currLower = lower(i);
843  Real objChange = 0.0;
844 
845  MSG_DEBUG( std::cout << "DCHANG02 changeUpperStatus(): col " << i
846  << "[" << currLower << ":" << newUpper << "] " << stat; )
847 
848  switch (stat)
849  {
851  if (newUpper == currLower)
853  break;
855  if (newUpper >= infinity)
856  {
857  if (currLower <= infinity)
858  {
859  stat = SPxBasis::Desc::P_FREE;
860  if( m_nonbasicValueUpToDate && rep() == COLUMN )
861  objChange = -theUCbound[i] * oldUpper;
862  }
863  else
864  {
866  if( m_nonbasicValueUpToDate && rep() == COLUMN )
867  objChange = (theLCbound[i] * currLower) - (theUCbound[i] * oldUpper);
868  }
869  }
870  else if (newUpper == currLower)
871  {
873  if( m_nonbasicValueUpToDate && rep() == COLUMN )
874  objChange = maxObj(i) * (newUpper - oldUpper);
875  }
876  else if( m_nonbasicValueUpToDate && rep() == COLUMN )
877  objChange = theUCbound[i] * (newUpper - oldUpper);
878  break;
880  if (newUpper < infinity)
881  {
883  if( m_nonbasicValueUpToDate && rep() == COLUMN )
884  objChange = theUCbound[i] * newUpper;
885  }
886  break;
888  if (newUpper != currLower)
890  break;
896  if( rep() == ROW && theShift > 0.0 )
898  stat = dualColStatus(i);
899  break;
900  default:
901  throw SPxInternalCodeException("XCHANG02 This should never happen.");
902  }
903  MSG_DEBUG( std::cout << " -> " << stat << std::endl; );
904 
905  // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation)
906  if( rep() == COLUMN )
907  updateNonbasicValue(objChange);
908 }
909 
910 void SPxSolver::changeUpper(const Vector& newUpper)
911 {
912  // we better recompute the nonbasic value when changing all upper bounds
914 
915  SPxLP::changeUpper(newUpper);
916 
918  {
919  for (int i = 0; i < newUpper.dim(); ++i)
920  changeUpperStatus(i, newUpper[i]);
921 
922  unInit();
923  }
924 }
925 
926 void SPxSolver::changeUpper(int i, const Real& newUpper)
927 {
928  Real oldUpper = upper(i);
929 
930  if (newUpper != oldUpper)
931  {
932  SPxLP::changeUpper(i, newUpper);
933 
935  {
936  changeUpperStatus(i, newUpper, oldUpper);
937  unInit();
938  }
939  }
940 }
941 
942 void SPxSolver::changeBounds(const Vector& newLower, const Vector& newUpper)
943 {
944 
945  changeLower(newLower);
946  changeUpper(newUpper);
947 }
948 
949 void SPxSolver::changeBounds(int i, const Real& newLower, const Real& newUpper)
950 {
951 
952  changeLower(i, newLower);
953  changeUpper(i, newUpper);
954 }
955 
956 void SPxSolver::changeLhsStatus(int i, Real newLhs, Real oldLhs)
957 {
959  Real currRhs = rhs(i);
960  Real objChange = 0.0;
961 
962  MSG_DEBUG( std::cout << "DCHANG03 changeLhsStatus() : row " << i
963  << ": " << stat; )
964  switch (stat)
965  {
967  if (newLhs <= -infinity)
968  {
969  if (currRhs >= infinity)
970  {
971  stat = SPxBasis::Desc::P_FREE;
972  if( m_nonbasicValueUpToDate && rep() == COLUMN )
973  objChange = -theURbound[i] * oldLhs;
974  }
975  else
976  {
978  if( m_nonbasicValueUpToDate && rep() == COLUMN )
979  objChange = (theLRbound[i] * currRhs) - (theURbound[i] * oldLhs);
980  }
981  }
982  else if (newLhs == currRhs)
983  {
985  if( m_nonbasicValueUpToDate && rep() == COLUMN )
986  objChange = maxRowObj(i) * (newLhs - oldLhs);
987  }
988  else if( m_nonbasicValueUpToDate && rep() == COLUMN )
989  objChange = theURbound[i] * (newLhs - oldLhs);
990  break;
992  if (newLhs == currRhs)
994  break;
996  if (newLhs > -infinity)
997  {
999  if( m_nonbasicValueUpToDate && rep() == COLUMN )
1000  objChange = theURbound[i] * newLhs;
1001  }
1002  break;
1004  if (newLhs != currRhs)
1006  break;
1012  if( rep() == ROW && theShift > 0.0 )
1014  stat = dualRowStatus(i);
1015  break;
1016  default:
1017  throw SPxInternalCodeException("XCHANG03 This should never happen.");
1018  }
1019  MSG_DEBUG( std::cout << " -> " << stat << std::endl; )
1020 
1021  // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation)
1022  if( rep() == COLUMN )
1023  updateNonbasicValue(objChange);
1024 }
1025 
1026 void SPxSolver::changeLhs(const Vector& newLhs)
1027 {
1028  // we better recompute the nonbasic value when changing all lhs
1030 
1031  SPxLP::changeLhs(newLhs);
1032 
1034  {
1035  for (int i = 0; i < nRows(); ++i)
1036  changeLhsStatus(i, newLhs[i]);
1037 
1038  unInit();
1039  }
1040 }
1041 
1042 void SPxSolver::changeLhs(int i, const Real& newLhs)
1043 {
1044  Real oldLhs = lhs(i);
1045 
1046  if (newLhs != oldLhs)
1047  {
1048  SPxLP::changeLhs(i, newLhs);
1049 
1051  {
1052  changeLhsStatus(i, newLhs, oldLhs);
1053  unInit();
1054  }
1055  }
1056 }
1057 
1058 void SPxSolver::changeRhsStatus(int i, Real newRhs, Real oldRhs)
1059 {
1060  SPxBasis::Desc::Status& stat = desc().rowStatus(i);
1061  Real currLhs = lhs(i);
1062  Real objChange = 0.0;
1063 
1064  MSG_DEBUG( std::cout << "DCHANG04 changeRhsStatus() : row " << i
1065  << ": " << stat; )
1066  switch (stat)
1067  {
1069  if (newRhs >= infinity)
1070  {
1071  if (currLhs <= -infinity)
1072  {
1073  stat = SPxBasis::Desc::P_FREE;
1074  if( m_nonbasicValueUpToDate && rep() == COLUMN )
1075  objChange = -theLRbound[i] * oldRhs;
1076  }
1077  else
1078  {
1080  if( m_nonbasicValueUpToDate && rep() == COLUMN )
1081  objChange = (theURbound[i] * currLhs) - (theLRbound[i] * oldRhs);
1082  }
1083  }
1084  else if (newRhs == currLhs)
1085  {
1086  stat = SPxBasis::Desc::P_FIXED;
1087  if( m_nonbasicValueUpToDate && rep() == COLUMN )
1088  objChange = maxRowObj(i) * (newRhs - oldRhs);
1089  }
1090  else if( m_nonbasicValueUpToDate && rep() == COLUMN )
1091  objChange = theLRbound[i] * (newRhs - oldRhs);
1092  break;
1094  if (newRhs == currLhs)
1095  stat = SPxBasis::Desc::P_FIXED;
1096  break;
1098  if (newRhs < infinity)
1099  {
1101  if( m_nonbasicValueUpToDate && rep() == COLUMN )
1102  objChange = theLRbound[i] * newRhs;
1103  }
1104  break;
1106  if (newRhs != currLhs)
1108  break;
1114  if( rep() == ROW && theShift > 0.0 )
1116  stat = dualRowStatus(i);
1117  break;
1118  default:
1119  throw SPxInternalCodeException("XCHANG04 This should never happen.");
1120  }
1121  MSG_DEBUG( std::cout << " -> " << stat << std::endl; )
1122 
1123  // we only need to update the nonbasic value in column representation (see nonbasicValue() for comparison/explanation)
1124  if( rep() == COLUMN )
1125  updateNonbasicValue(objChange);
1126 }
1127 
1128 
1129 void SPxSolver::changeRhs(const Vector& newRhs)
1130 {
1131  // we better recompute the nonbasic value when changing all rhs
1133 
1134  SPxLP::changeRhs(newRhs);
1135 
1137  {
1138  for (int i = 0; i < nRows(); ++i)
1139  changeRhsStatus(i, newRhs[i]);
1140  unInit();
1141  }
1142 }
1143 
1144 void SPxSolver::changeRhs(int i, const Real& newRhs)
1145 {
1146  Real oldRhs = rhs(i);
1147 
1148  if (newRhs != oldRhs)
1149  {
1150  SPxLP::changeRhs(i, newRhs);
1151 
1153  {
1154  changeRhsStatus(i, newRhs, oldRhs);
1155  unInit();
1156  }
1157  }
1158 }
1159 
1160 void SPxSolver::changeRange(const Vector& newLhs, const Vector& newRhs)
1161 {
1162  // we better recompute the nonbasic value when changing all ranges
1164 
1165  SPxLP::changeLhs(newLhs);
1166  SPxLP::changeRhs(newRhs);
1168  {
1169  for (int i = nRows() - 1; i >= 0; --i)
1170  {
1171  changeLhsStatus(i, newLhs[i]);
1172  changeRhsStatus(i, newRhs[i]);
1173  }
1174  unInit();
1175  }
1176 }
1177 
1178 void SPxSolver::changeRange(int i, const Real& newLhs, const Real& newRhs)
1179 {
1180  Real oldLhs = lhs(i);
1181  Real oldRhs = rhs(i);
1182 
1183  SPxLP::changeLhs(i, newLhs);
1184  SPxLP::changeRhs(i, newRhs);
1185 
1187  {
1188  changeLhsStatus(i, newLhs, oldLhs);
1189  changeRhsStatus(i, newRhs, oldRhs);
1190  unInit();
1191  }
1192 }
1193 
1194 void SPxSolver::changeRow(int i, const LPRow& newRow)
1195 {
1197 
1198  SPxLP::changeRow(i, newRow);
1200  SPxBasis::changedRow( i );
1201  unInit();
1202 }
1203 
1204 void SPxSolver::changeCol(int i, const LPCol& newCol)
1205 {
1206  if( i < 0 )
1207  return;
1208 
1210 
1211  SPxLP::changeCol(i, newCol);
1213  SPxBasis::changedCol( i );
1214  unInit();
1215 }
1216 
1217 void SPxSolver::changeElement(int i, int j, const Real& val)
1218 {
1219  if( i < 0 || j < 0 )
1220  return;
1221 
1223 
1224  SPxLP::changeElement(i, j, val);
1226  SPxBasis::changedElement( i, j );
1227  unInit();
1228 }
1229 
1231 {
1232 
1233  SPxLP::changeSense(sns);
1234  unInit();
1235 }
1236 } // namespace soplex