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
17 #include <assert.h>
18 #include <iostream>
19
20 #include "soplex/spxdefines.h"
(1) Event include_recursion: |
#include file "/sapmnt/home1/d029903/my_work/SCIPSoPlex_coverity/scipoptsuite-8.0.1/soplex/src/soplex/spxweightst.h" includes itself: spxweightst.h -> spxweightst.hpp -> spxweightst.h |
(2) Event caretline: |
^ |
21 #include "soplex/spxweightst.h"
22 #include "soplex/svset.h"
23 #include "soplex/sorter.h"
24
25 namespace soplex
26 {
27 #define EPS 1e-6
28 #define STABLE 1e-3 // the sparsest row/column may only have a pivot of size STABLE*maxEntry
29
30
31 template <class R>
32 bool SPxWeightST<R>::isConsistent() const
33 {
34 #ifdef ENABLE_CONSISTENCY_CHECKS
35 return rowWeight.isConsistent()
36 && colWeight.isConsistent()
37 && rowRight.isConsistent()
38 && colUp.isConsistent();
39 // && SPxStarter::isConsistent(); // not yet implemented
40 #else
41 return true;
42 #endif
43 }
44
45 /* Generating the Starting Basis
46 The generation of a starting basis works as follows: After setting up the
47 preference arrays #weight# and #coWeight#, #Id#s are selected to be dual in
48 a greedy manner. Initially, the first #Id# is taken. Then the next #Id# is
49 checked wheter its vector is linearly dependend of the vectors of the #Id#s
50 allready selected. If not, it is added to them. This is iterated until a
51 full matrix has been constructed.
52
53 Testing for linear independence is done very much along the lines of LU
54 factorization. A vector is taken, and updated with all previous L-vectors.
55 Then the maximal absolut element is selected as pivot element for computing
56 the L-vector. This is stored for further processing.
57 */
58
59 /*
60 The following two functions set the status of |id| to primal or dual,
61 respectively.
62 */
63 template <class R>
64 void SPxWeightST<R>::setPrimalStatus(
65 typename SPxBasisBase<R>::Desc& desc,
66 const SPxSolverBase<R>& base,
67 const SPxId& id)
68 {
69 if(id.isSPxRowId())
70 {
71 int n = base.number(SPxRowId(id));
72
73 if(base.rhs(n) >= R(infinity))
74 {
75 if(base.lhs(n) <= R(-infinity))
76 desc.rowStatus(n) = SPxBasisBase<R>::Desc::P_FREE;
77 else
78 desc.rowStatus(n) = SPxBasisBase<R>::Desc::P_ON_LOWER;
79 }
80 else
81 {
82 if(base.lhs(n) <= R(-infinity))
83 desc.rowStatus(n) = SPxBasisBase<R>::Desc::P_ON_UPPER;
84 else if(base.lhs(n) >= base.rhs(n) - base.epsilon())
85 desc.rowStatus(n) = SPxBasisBase<R>::Desc::P_FIXED;
86 else if(rowRight[n])
87 desc.rowStatus(n) = SPxBasisBase<R>::Desc::P_ON_UPPER;
88 else
89 desc.rowStatus(n) = SPxBasisBase<R>::Desc::P_ON_LOWER;
90 }
91 }
92 else
93 {
94 int n = base.number(SPxColId(id));
95
96 if(base.SPxLPBase<R>::upper(n) >= R(infinity))
97 {
98 if(base.SPxLPBase<R>::lower(n) <= R(-infinity))
99 desc.colStatus(n) = SPxBasisBase<R>::Desc::P_FREE;
100 else
101 desc.colStatus(n) = SPxBasisBase<R>::Desc::P_ON_LOWER;
102 }
103 else
104 {
105 if(base.SPxLPBase<R>::lower(n) <= R(-infinity))
106 desc.colStatus(n) = SPxBasisBase<R>::Desc::P_ON_UPPER;
107 else if(base.SPxLPBase<R>::lower(n) >= base.SPxLPBase<R>::upper(n) - base.epsilon())
108 desc.colStatus(n) = SPxBasisBase<R>::Desc::P_FIXED;
109 else if(colUp[n])
110 desc.colStatus(n) = SPxBasisBase<R>::Desc::P_ON_UPPER;
111 else
112 desc.colStatus(n) = SPxBasisBase<R>::Desc::P_ON_LOWER;
113 }
114 }
115 }
116
117 // ----------------------------------------------------------------
118 template <class R>
119 static void setDualStatus(
120 typename SPxBasisBase<R>::Desc& desc,
121 const SPxSolverBase<R>& base,
122 const SPxId& id)
123 {
124 if(id.isSPxRowId())
125 {
126 int n = base.number(SPxRowId(id));
127 desc.rowStatus(n) = base.basis().dualRowStatus(n);
128 }
129 else
130 {
131 int n = base.number(SPxColId(id));
132 desc.colStatus(n) = base.basis().dualColStatus(n);
133 }
134 }
135 // ----------------------------------------------------------------
136
137 /// Compare class for row weights, used for sorting.
138 template <typename T>
139 struct Compare
140 {
141 public:
142 /// constructor
143 Compare() : weight(0) {}
144 // const SPxSolverBase* base; ///< the solver
145 const T* weight; ///< the weights to compare
146
147 /// compares the weights
148 T operator()(int i1, int i2) const
149 {
150 return weight[i1] - weight[i2];
151 }
152 };
153
154 // ----------------------------------------------------------------
155 /**
156 The following method initializes \p pref such that it contains the
157 set of \ref soplex::SPxId "SPxIds" ordered following \p rowWeight and
158 \p colWeight. For the sorting we take the following approach: first
159 we sort the rows, then the columns. Finally we perform a mergesort
160 of both.
161 */
162 template <class R>
163 static void initPrefs(
164 DataArray < SPxId >& pref,
165 const SPxSolverBase<R>& base,
166 const Array<R>& rowWeight,
167 const Array<R>& colWeight)
168 {
169 DataArray<int> row(base.nRows());
170 DataArray<int> col(base.nCols());
171 int i;
172 int j;
173 int k;
174
175 Compare<R> compare;
176 // compare.base = &base;
177
178 for(i = 0; i < base.nRows(); ++i)
179 row[i] = i;
180
181 compare.weight = rowWeight.get_const_ptr();
182
183 SPxQuicksort(row.get_ptr(), row.size(), compare); // Sort rows
184
185 for(i = 0; i < base.nCols(); ++i)
186 col[i] = i;
187
188 compare.weight = colWeight.get_const_ptr();
189
190 SPxQuicksort(col.get_ptr(), col.size(), compare); // Sort column
191
192 i = 0;
193 j = 0;
194 k = 0;
195
196 while(k < pref.size()) // merge sort
197 {
198 if(rowWeight[row[i]] < colWeight[col[j]])
199 {
200 pref[k++] = base.rId(row[i++]);
201
202 if(i >= base.nRows())
203 while(k < pref.size())
204 pref[k++] = base.cId(col[j++]);
205 }
206 else
207 {
208 pref[k++] = base.cId(col[j++]);
209
210 if(j >= base.nCols())
211 while(k < pref.size())
212 pref[k++] = base.rId(row[i++]);
213 }
214 }
215
216 assert(i == base.nRows());
217 assert(j == base.nCols());
218 }
219
220 // ----------------------------------------------------------------
221 template <class R>
222 void SPxWeightST<R>::generate(SPxSolverBase<R>& base)
223 {
224 SPxId tmpId;
225
226 forbidden.reSize(base.dim());
227 rowWeight.reSize(base.nRows());
228 colWeight.reSize(base.nCols());
229 rowRight.reSize(base.nRows());
230 colUp.reSize(base.nCols());
231
232 if(base.rep() == SPxSolverBase<R>::COLUMN)
233 {
234 weight = &colWeight;
235 coWeight = &rowWeight;
236 }
237 else
238 {
239 weight = &rowWeight;
240 coWeight = &colWeight;
241 }
242
243 assert(weight->size() == base.coDim());
244 assert(coWeight->size() == base.dim());
245
246 setupWeights(base);
247
248 typename SPxBasisBase<R>::Desc desc(base);
249 // desc.reSize(base.nRows(), base.nCols());
250
251 DataArray < SPxId > pref(base.nRows() + base.nCols());
252 initPrefs(pref, base, rowWeight, colWeight);
253
254 int i;
255 int stepi;
256 int j;
257 int sel;
258
259 for(i = 0; i < base.dim(); ++i)
260 forbidden[i] = 0;
261
262 if(base.rep() == SPxSolverBase<R>::COLUMN)
263 {
264 // in COLUMN rep we scan from beginning to end
265 i = 0;
266 stepi = 1;
267 }
268 else
269 {
270 // in ROW rep we scan from end to beginning
271 i = pref.size() - 1;
272 stepi = -1;
273 }
274
275 int dim = base.dim();
276 R maxEntry = 0;
277
278 for(; i >= 0 && i < pref.size(); i += stepi)
279 {
280 tmpId = pref[i];
281 const SVectorBase<R>& vec = base.vector(tmpId);
282 sel = -1;
283
284 // column or row singleton ?
285 if(vec.size() == 1)
286 {
287 int idx = vec.index(0);
288
289 if(forbidden[idx] < 2)
290 {
291 sel = idx;
292 dim += (forbidden[idx] > 0) ? 1 : 0;
293 }
294 }
295 else
296 {
297 maxEntry = vec.maxAbs();
298
299 // initialize the nonzero counter
300 int minRowEntries = base.nRows();
301
302 // find a stable index with a sparse row/column
303 for(j = vec.size(); --j >= 0;)
304 {
305 R x = vec.value(j);
306 int k = vec.index(j);
307 int nRowEntries = base.coVector(k).size();
308
309 if(!forbidden[k] && (spxAbs(x) > STABLE * maxEntry) && (nRowEntries < minRowEntries))
310 {
311 minRowEntries = nRowEntries;
312 sel = k;
313 }
314 }
315 }
316
317 // we found a valid index
318 if(sel >= 0)
319 {
320 MSG_DEBUG(
321
322 if(pref[i].type() == SPxId::ROW_ID)
323 std::cout << "DWEIST01 r" << base.number(pref[i]);
324 else
325 std::cout << "DWEIST02 c" << base.number(pref[i]);
326 )
327
328 forbidden[sel] = 2;
329
330 // put current column/row into basis
331 if(base.rep() == SPxSolverBase<R>::COLUMN)
332 setDualStatus(desc, base, pref[i]);
333 else
334 setPrimalStatus(desc, base, pref[i]);
335
336 for(j = vec.size(); --j >= 0;)
337 {
338 R x = vec.value(j);
339 int k = vec.index(j);
340
341 if(!forbidden[k] && (x > EPS * maxEntry || -x > EPS * maxEntry))
342 {
343 forbidden[k] = 1;
344 --dim;
345 }
346 }
347
348 if(--dim == 0)
349 {
350 //@ for(++i; i < pref.size(); ++i)
351 if(base.rep() == SPxSolverBase<R>::COLUMN)
352 {
353 // set all remaining indeces to nonbasic status
354 for(i += stepi; i >= 0 && i < pref.size(); i += stepi)
355 setPrimalStatus(desc, base, pref[i]);
356
357 // fill up the basis wherever linear independence is assured
358 for(i = forbidden.size(); --i >= 0;)
359 {
360 if(forbidden[i] < 2)
361 setDualStatus(desc, base, base.coId(i));
362 }
363 }
364 else
365 {
366 for(i += stepi; i >= 0 && i < pref.size(); i += stepi)
367 setDualStatus(desc, base, pref[i]);
368
369 for(i = forbidden.size(); --i >= 0;)
370 {
371 if(forbidden[i] < 2)
372 setPrimalStatus(desc, base, base.coId(i));
373 }
374 }
375
376 break;
377 }
378 }
379 // sel == -1
380 else if(base.rep() == SPxSolverBase<R>::COLUMN)
381 setPrimalStatus(desc, base, pref[i]);
382 else
383 setDualStatus(desc, base, pref[i]);
384
385 #ifndef NDEBUG
386 {
387 int n, m;
388
389 for(n = 0, m = forbidden.size(); n < forbidden.size(); ++n)
390 m -= (forbidden[n] != 0) ? 1 : 0;
391
392 assert(m == dim);
393 }
394 #endif // NDEBUG
395 }
396
397 assert(dim == 0);
398
399 base.loadBasis(desc);
400 #ifdef TEST
401 base.init();
402
403 int changed = 0;
404 const VectorBase<R>& pvec = base.pVec();
405
406 for(i = pvec.dim() - 1; i >= 0; --i)
407 {
408 if(desc.colStatus(i) == SPxBasisBase<R>::Desc::P_ON_UPPER
409 && base.lower(i) > R(-infinity) && pvec[i] > base.maxObj(i))
410 {
411 changed = 1;
412 desc.colStatus(i) = SPxBasisBase<R>::Desc::P_ON_LOWER;
413 }
414 else if(desc.colStatus(i) == SPxBasisBase<R>::Desc::P_ON_LOWER
415 && base.upper(i) < R(infinity) && pvec[i] < base.maxObj(i))
416 {
417 changed = 1;
418 desc.colStatus(i) = SPxBasisBase<R>::Desc::P_ON_UPPER;
419 }
420 }
421
422 if(changed)
423 {
424 std::cout << "changed basis\n";
425 base.loadBasis(desc);
426 }
427 else
428 std::cout << "nothing changed\n";
429
430 #endif // TEST
431 }
432
433 // ----------------------------------------------------------------
434
435 /* Computation of Weights
436 */
437 template <class R>
438 void SPxWeightST<R>::setupWeights(SPxSolverBase<R>& base)
439 {
440 const VectorBase<R>& obj = base.maxObj();
441 const VectorBase<R>& low = base.lower();
442 const VectorBase<R>& up = base.upper();
443 const VectorBase<R>& rhs = base.rhs();
444 const VectorBase<R>& lhs = base.lhs();
445 int i;
446
447 R eps = base.epsilon();
448 R maxabs = 1.0;
449
450 // find absolut biggest entry in bounds and left-/right hand side
451 for(i = 0; i < base.nCols(); i++)
452 {
453 if((up[i] < R(infinity)) && (spxAbs(up[i]) > maxabs))
454 maxabs = spxAbs(up[i]);
455
456 if((low[i] > R(-infinity)) && (spxAbs(low[i]) > maxabs))
457 maxabs = spxAbs(low[i]);
458 }
459
460 for(i = 0; i < base.nRows(); i++)
461 {
462 if((rhs[i] < R(infinity)) && (spxAbs(rhs[i]) > maxabs))
463 maxabs = spxAbs(rhs[i]);
464
465 if((lhs[i] > R(-infinity)) && (spxAbs(lhs[i]) > maxabs))
466 maxabs = spxAbs(lhs[i]);
467 }
468
469 /**@todo The comments are wrong. The first is for dual simplex and
470 * the secound for primal one. Is anything else wrong?
471 * Also the values are nearly the same for both cases.
472 * Should this be ? Changed the values for
473 * r_fixed to 0 because of maros-r7. It is not clear why
474 * this makes a difference because all constraints in that
475 * instance are of equality type.
476 * Why is rowRight sometimes not set?
477 */
478 if(base.rep() * base.type() > 0) // primal simplex
479 {
480 const R ax = 1e-3 / obj.maxAbs();
481 const R bx = 1.0 / maxabs;
482 const R nne = ax / base.nRows(); // 1e-4 * ax;
483 const R c_fixed = 1e+5;
484 const R r_fixed = 0; // TK20010103: was 1e+4 (maros-r7)
485 const R c_dbl_bounded = 1e+1;
486 const R r_dbl_bounded = 0;
487 const R c_bounded = 1e+1;
488 const R r_bounded = 0;
489 const R c_free = -1e+4;
490 const R r_free = -1e+5;
491
492 for(i = base.nCols() - 1; i >= 0; i--)
493 {
494 R n = nne * (base.colVector(i).size() - 1); // very small value that is zero for col singletons
495 R x = ax * obj[i]; // this is at most 1e-3, probably a lot smaller
496 R u = bx * up [i]; // this is at most 1, probably a lot smaller
497 R l = bx * low[i]; // this is at most 1, probably a lot smaller
498
499 if(up[i] < R(infinity))
500 {
501 if(spxAbs(low[i] - up[i]) < eps)
502 colWeight[i] = c_fixed + n + spxAbs(x);
503 else if(low[i] > R(-infinity))
504 {
505 colWeight[i] = c_dbl_bounded + l - u + n;
506
507 l = spxAbs(l);
508 u = spxAbs(u);
509
510 if(u < l)
511 {
512 colUp[i] = true;
513 colWeight[i] += x;
514 }
515 else
516 {
517 colUp[i] = false;
518 colWeight[i] -= x;
519 }
520 }
521 else
522 {
523 colWeight[i] = c_bounded - u + x + n;
524 colUp[i] = true;
525 }
526 }
527 else
528 {
529 if(low[i] > R(-infinity))
530 {
531 colWeight[i] = c_bounded + l + n - x;
532 colUp[i] = false;
533 }
534 else
535 {
536 colWeight[i] = c_free + n - spxAbs(x);
537 }
538 }
539 }
540
541 for(i = base.nRows() - 1; i >= 0; i--)
542 {
543 if(rhs[i] < R(infinity))
544 {
545 if(spxAbs(lhs[i] - rhs[i]) < eps)
546 {
547 rowWeight[i] = r_fixed;
548 }
549 else if(lhs[i] > R(-infinity))
550 {
551 R u = bx * rhs[i];
552 R l = bx * lhs[i];
553
554 rowWeight[i] = r_dbl_bounded + l - u;
555 rowRight[i] = spxAbs(u) < spxAbs(l);
556 }
557 else
558 {
559 rowWeight[i] = r_bounded - bx * rhs[i];
560 rowRight[i] = true;
561 }
562 }
563 else
564 {
565 if(lhs[i] > R(-infinity))
566 {
567 rowWeight[i] = r_bounded + bx * lhs[i];
568 rowRight[i] = false;
569 }
570 else
571 {
572 rowWeight[i] = r_free;
573 }
574 }
575 }
576 }
577 else
578 {
579 assert(base.rep() * base.type() < 0); // dual simplex
580
581 const R ax = 1.0 / obj.maxAbs();
582 const R bx = 1e-2 / maxabs;
583 const R nne = 1e-4 * bx;
584 const R c_fixed = 1e+5;
585 const R r_fixed = 1e+4;
586 const R c_dbl_bounded = 1;
587 const R r_dbl_bounded = 0;
588 const R c_bounded = 0;
589 const R r_bounded = 0;
590 const R c_free = -1e+4;
591 const R r_free = -1e+5;
592
593 for(i = base.nCols() - 1; i >= 0; i--)
594 {
595 R n = nne * (base.colVector(i).size() - 1);
596 R x = ax * obj[i];
597 R u = bx * up [i];
598 R l = bx * low[i];
599
600 if(up[i] < R(infinity))
601 {
602 if(spxAbs(low[i] - up[i]) < eps)
603 colWeight[i] = c_fixed + n + spxAbs(x);
604 else if(low[i] > R(-infinity))
605 {
606 if(x > 0)
607 {
608 colWeight[i] = c_dbl_bounded + x - u + n;
609 colUp[i] = true;
610 }
611 else
612 {
613 colWeight[i] = c_dbl_bounded - x + l + n;
614 colUp[i] = false;
615 }
616 }
617 else
618 {
619 colWeight[i] = c_bounded - u + x + n;
620 colUp[i] = true;
621 }
622 }
623 else
624 {
625 if(low[i] > R(-infinity))
626 {
627 colWeight[i] = c_bounded - x + l + n;
628 colUp[i] = false;
629 }
630 else
631 colWeight[i] = c_free + n - spxAbs(x);
632 }
633 }
634
635 for(i = base.nRows() - 1; i >= 0; i--)
636 {
637 const R len1 = 1; // (base.rowVector(i).length() + base.epsilon());
638 R n = 0; // nne * (base.rowVector(i).size() - 1);
639 R u = bx * len1 * rhs[i];
640 R l = bx * len1 * lhs[i];
641 R x = ax * len1 * (obj * base.rowVector(i));
642
643 if(rhs[i] < R(infinity))
644 {
645 if(spxAbs(lhs[i] - rhs[i]) < eps)
646 rowWeight[i] = r_fixed + n + spxAbs(x);
647 else if(lhs[i] > R(-infinity))
648 {
649 if(x > 0)
650 {
651 rowWeight[i] = r_dbl_bounded + x - u + n;
652 rowRight[i] = true;
653 }
654 else
655 {
656 rowWeight[i] = r_dbl_bounded - x + l + n;
657 rowRight[i] = false;
658 }
659 }
660 else
661 {
662 rowWeight[i] = r_bounded - u + n + x;
663 rowRight[i] = true;
664 }
665 }
666 else
667 {
668 if(lhs[i] > R(-infinity))
669 {
670 rowWeight[i] = r_bounded + l + n - x;
671 rowRight[i] = false;
672 }
673 else
674 {
675 rowWeight[i] = r_free + n - spxAbs(x);
676 }
677 }
678 }
679 }
680
681 MSG_DEBUG(
682 {
683 for(i = 0; i < base.nCols(); i++)
684 std::cout << "C i= " << i
685 << " up= " << colUp[i]
686 << " w= " << colWeight[i]
687 << std::endl;
688 for(i = 0; i < base.nRows(); i++)
689 std::cout << "R i= " << i
690 << " rr= " << rowRight[i]
691 << " w= " << rowWeight[i]
692 << std::endl;
693 })
694 }
695 } // namespace soplex
696