clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CglProbing.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D HAVE_CONFIG_H -I . -I . -I .. -I ./.. -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/CoinUtils/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/Osi/src/Osi -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/CoinUtils/src -D NDEBUG -D CGL_BUILD -D PIC -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wwrite-strings -Wno-unknown-pragmas -Wno-long-long -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/Cgl/src/CglProbing -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ CglProbing.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | #include <cstdlib> |
7 | #include <cstdio> |
8 | #include <cmath> |
9 | #include <cfloat> |
10 | #include <cassert> |
11 | #include <iostream> |
12 | #define PROBING100 0 |
13 | |
14 | |
15 | |
16 | #include "CoinPragma.hpp" |
17 | #include "CoinHelperFunctions.hpp" |
18 | #include "CoinPackedVector.hpp" |
19 | #include "CoinPackedMatrix.hpp" |
20 | #include "CoinFinite.hpp" |
21 | #include "OsiRowCutDebugger.hpp" |
22 | #include "CglProbing.hpp" |
23 | |
24 | #define PROBING_EXTRA_STUFF false |
25 | #define FIXED_ALLOWANCE 10 |
26 | #define SIZE_ROW_MULT 4 |
27 | #define SIZE_ROW_ADD 2000 |
28 | typedef struct {double infeasibility;int sequence;} double_int_pair; |
29 | class double_int_pair_compare { |
30 | public: |
31 | bool operator() (double_int_pair x , double_int_pair y) const |
32 | { |
33 | return ( x.infeasibility < y.infeasibility); |
34 | } |
35 | }; |
36 | |
37 | typedef struct { |
38 | int index, next; |
39 | } CoinHashLink; |
40 | static double multiplier[] = {1.23456789e2,-9.87654321}; |
41 | static int hashCut (const OsiRowCut2 & x, int size) |
42 | { |
43 | int xN =x.row().getNumElements(); |
44 | double xLb = x.lb(); |
45 | double xUb = x.ub(); |
46 | const int * xIndices = x.row().getIndices(); |
47 | const double * xElements = x.row().getElements(); |
48 | unsigned int hashValue; |
49 | double value=1.0; |
50 | if (xLb>-1.0e10) |
51 | value += xLb*multiplier[0]; |
52 | if (xUb<1.0e10) |
53 | value += xUb*multiplier[1]; |
54 | for( int j=0;j<xN;j++) { |
55 | int xColumn = xIndices[j]; |
56 | double xValue = xElements[j]; |
57 | int k=(j&1); |
58 | value += (j+1)*multiplier[k]*(xColumn+1)*xValue; |
59 | } |
60 | |
61 | if (sizeof(value)>sizeof(hashValue)) { |
62 | assert (sizeof(value)==2*sizeof(hashValue)); |
63 | union { double d; int i[2]; } xx; |
64 | xx.d = value; |
65 | hashValue = (xx.i[0] + xx.i[1]); |
66 | } else { |
67 | assert (sizeof(value)==sizeof(hashValue)); |
68 | union { double d; unsigned int i[2]; } xx; |
69 | xx.d = value; |
70 | hashValue = xx.i[0]; |
71 | } |
72 | return hashValue%(size); |
73 | } |
74 | static bool same (const OsiRowCut2 & x, const OsiRowCut2 & y) |
75 | { |
76 | int xN =x.row().getNumElements(); |
77 | int yN =y.row().getNumElements(); |
78 | bool identical=false; |
79 | if (xN==yN) { |
80 | double xLb = x.lb(); |
81 | double xUb = x.ub(); |
82 | double yLb = y.lb(); |
83 | double yUb = y.ub(); |
84 | if (fabs(xLb-yLb)<1.0e-8&&fabs(xUb-yUb)<1.0e-8) { |
85 | const int * xIndices = x.row().getIndices(); |
86 | const double * xElements = x.row().getElements(); |
87 | const int * yIndices = y.row().getIndices(); |
88 | const double * yElements = y.row().getElements(); |
89 | int j; |
90 | for( j=0;j<xN;j++) { |
91 | if (xIndices[j]!=yIndices[j]) |
92 | break; |
93 | if (fabs(xElements[j]-yElements[j])>1.0e-12) |
94 | break; |
95 | } |
96 | identical = (j==xN); |
97 | } |
98 | } |
99 | return identical; |
100 | } |
101 | class row_cut { |
102 | public: |
103 | |
104 | row_cut(int nRows, bool initialPass ) |
105 | { |
106 | numberCuts_=0; |
107 | if (nRows<500) { |
108 | maxSize_ = SIZE_ROW_MULT*nRows + SIZE_ROW_ADD; |
109 | } else if (nRows<5000) { |
110 | maxSize_ = (SIZE_ROW_MULT*nRows + SIZE_ROW_ADD)>>1; |
111 | } else if (nRows<10000) { |
112 | maxSize_ = (SIZE_ROW_MULT*(nRows>>1) + SIZE_ROW_ADD)>>1; |
113 | } else { |
114 | maxSize_ = (SIZE_ROW_MULT*CoinMin(nRows,100000) + SIZE_ROW_ADD)>>2; |
115 | } |
116 | size_ = (maxSize_>>3)+10; |
117 | if (initialPass) |
118 | size_ = size_>>1; |
119 | if (size_<1000) |
120 | hashSize_=4*size_; |
121 | else |
122 | hashSize_=2*size_; |
123 | nRows_ = nRows; |
124 | rowCut_ = new OsiRowCut2 * [size_]; |
125 | hash_ = new CoinHashLink[hashSize_]; |
126 | for (int i=0;i<hashSize_;i++) { |
127 | hash_[i].index=-1; |
128 | hash_[i].next=-1; |
129 | } |
130 | numberCuts_=0; |
131 | lastHash_=-1; |
132 | } |
133 | ~row_cut() |
134 | { |
135 | for (int i=0;i<numberCuts_;i++) |
136 | delete rowCut_[i]; |
137 | delete [] rowCut_; |
138 | delete [] hash_; |
139 | } |
140 | OsiRowCut2 * cut(int i) const |
141 | { return rowCut_[i];} |
142 | int numberCuts() const |
143 | { return numberCuts_;} |
144 | inline bool outOfSpace() const |
145 | { return maxSize_==numberCuts_;} |
146 | OsiRowCut2 ** rowCut_; |
147 | |
148 | CoinHashLink *hash_; |
149 | int size_; |
150 | int maxSize_; |
151 | int hashSize_; |
152 | int nRows_; |
153 | int numberCuts_; |
154 | int lastHash_; |
155 | |
156 | int addCutIfNotDuplicate(OsiRowCut & cut,int whichRow=-1) |
157 | { |
158 | if (numberCuts_==size_&&numberCuts_<maxSize_) { |
159 | size_ = CoinMin(2*size_+100,maxSize_); |
160 | if (size_<1000) |
161 | hashSize_=4*size_; |
162 | else |
163 | hashSize_=2*size_; |
164 | #ifdef COIN_DEVELOP |
165 | printf("increaing size from %d to %d (hash size %d, maxsize %d)\n", |
166 | numberCuts_,size_,hashSize_,maxSize_); |
167 | #endif |
168 | OsiRowCut2 ** temp = new OsiRowCut2 * [size_]; |
169 | delete [] hash_; |
170 | hash_ = new CoinHashLink[hashSize_]; |
171 | for (int i=0;i<hashSize_;i++) { |
172 | hash_[i].index=-1; |
173 | hash_[i].next=-1; |
174 | } |
175 | for (int i=0;i<numberCuts_;i++) { |
176 | temp[i]=rowCut_[i]; |
177 | int ipos = hashCut(*temp[i],hashSize_); |
178 | int found = -1; |
179 | int jpos=ipos; |
180 | while ( true ) { |
181 | int j1 = hash_[ipos].index; |
182 | |
183 | if ( j1 >= 0 ) { |
184 | if ( !same(*temp[i],*temp[j1]) ) { |
185 | int k = hash_[ipos].next; |
186 | if ( k != -1 ) |
187 | ipos = k; |
188 | else |
189 | break; |
190 | } else { |
191 | found = j1; |
192 | break; |
193 | } |
194 | } else { |
195 | break; |
196 | } |
197 | } |
198 | if (found<0) { |
199 | assert (hash_[ipos].next==-1); |
200 | if (ipos==jpos) { |
201 | |
202 | hash_[ipos].index=i; |
203 | } else { |
204 | |
205 | while ( true ) { |
206 | ++lastHash_; |
207 | assert (lastHash_<hashSize_); |
208 | if ( hash_[lastHash_].index == -1 ) |
209 | break; |
210 | } |
211 | hash_[ipos].next = lastHash_; |
212 | hash_[lastHash_].index = i; |
213 | } |
214 | } |
215 | } |
216 | delete [] rowCut_; |
217 | rowCut_ = temp; |
218 | } |
219 | if (numberCuts_<size_) { |
220 | double newLb = cut.lb(); |
221 | double newUb = cut.ub(); |
222 | CoinPackedVector vector = cut.row(); |
223 | int numberElements =vector.getNumElements(); |
224 | int * newIndices = vector.getIndices(); |
225 | double * newElements = vector.getElements(); |
226 | CoinSort_2(newIndices,newIndices+numberElements,newElements); |
227 | int i; |
228 | bool bad=false; |
229 | for (i=0;i<numberElements;i++) { |
230 | double value = fabs(newElements[i]); |
231 | if (value<1.0e-12||value>1.0e12) |
232 | bad=true; |
233 | } |
234 | if (bad) |
235 | return 1; |
236 | OsiRowCut2 newCut(whichRow); |
237 | newCut.setLb(newLb); |
238 | newCut.setUb(newUb); |
239 | newCut.setRow(vector); |
240 | int ipos = hashCut(newCut,hashSize_); |
241 | int found = -1; |
242 | int jpos=ipos; |
243 | while ( true ) { |
244 | int j1 = hash_[ipos].index; |
245 | |
246 | if ( j1 >= 0 ) { |
247 | if ( !same(newCut,*rowCut_[j1]) ) { |
248 | int k = hash_[ipos].next; |
249 | if ( k != -1 ) |
250 | ipos = k; |
251 | else |
252 | break; |
253 | } else { |
254 | found = j1; |
255 | break; |
256 | } |
257 | } else { |
258 | break; |
259 | } |
260 | } |
261 | if (found<0) { |
262 | assert (hash_[ipos].next==-1); |
263 | if (ipos==jpos) { |
264 | |
265 | hash_[ipos].index=numberCuts_; |
266 | } else { |
267 | |
268 | while ( true ) { |
269 | ++lastHash_; |
270 | assert (lastHash_<hashSize_); |
271 | if ( hash_[lastHash_].index == -1 ) |
272 | break; |
273 | } |
274 | hash_[ipos].next = lastHash_; |
275 | hash_[lastHash_].index = numberCuts_; |
276 | } |
277 | OsiRowCut2 * newCutPtr = new OsiRowCut2(whichRow); |
278 | newCutPtr->setLb(newLb); |
279 | newCutPtr->setUb(newUb); |
280 | newCutPtr->setRow(vector); |
281 | rowCut_[numberCuts_++]=newCutPtr; |
282 | return 0; |
283 | } else { |
284 | return 1; |
285 | } |
286 | } else { |
287 | return -1; |
288 | } |
289 | } |
290 | void addCuts(OsiCuts & cs, OsiRowCut ** whichRow,int iPass) |
291 | { |
292 | int numberCuts=cs.sizeRowCuts(); |
293 | int i ; |
294 | if (numberCuts_<nRows_) { |
295 | if ((iPass&1)==1) { |
296 | for (i=0;i<numberCuts_;i++) { |
297 | cs.insert(*rowCut_[i]); |
298 | if (whichRow) { |
299 | int iRow= rowCut_[i]->whichRow(); |
300 | if (iRow>=0&&!whichRow[iRow]) |
301 | whichRow[iRow]=cs.rowCutPtr(numberCuts);; |
302 | } |
303 | numberCuts++; |
304 | } |
305 | } else { |
306 | for (i=numberCuts_-1;i>=0;i--) { |
307 | cs.insert(*rowCut_[i]); |
308 | if (whichRow) { |
309 | int iRow= rowCut_[i]->whichRow(); |
310 | if (iRow>=0&&!whichRow[iRow]) |
311 | whichRow[iRow]=cs.rowCutPtr(numberCuts);; |
312 | } |
313 | numberCuts++; |
314 | } |
315 | } |
316 | } else { |
317 | |
318 | double * effectiveness = new double[numberCuts_]; |
319 | int iCut=0; |
320 | for (i=0;i<numberCuts_;i++) { |
321 | double value = -rowCut_[i]->effectiveness(); |
322 | if (whichRow) { |
323 | int iRow= rowCut_[i]->whichRow(); |
324 | if (iRow>=0) |
325 | value -= 1.0e10; |
326 | } |
327 | effectiveness[iCut++]=value; |
328 | } |
329 | std::sort(effectiveness,effectiveness+numberCuts_); |
330 | double threshold = -1.0e20; |
331 | if (iCut>nRows_) |
332 | threshold = effectiveness[nRows_]; |
333 | for ( i=0;i<numberCuts_;i++) { |
334 | if (rowCut_[i]->effectiveness()>threshold) { |
335 | cs.insert(*rowCut_[i]); |
336 | if (whichRow) { |
337 | int iRow= rowCut_[i]->whichRow(); |
338 | if (iRow>=0&&!whichRow[iRow]) |
339 | whichRow[iRow]=cs.rowCutPtr(numberCuts);; |
340 | } |
341 | numberCuts++; |
342 | } |
343 | } |
344 | delete[] effectiveness ; |
345 | } |
346 | for (i = 0 ; i < numberCuts_ ; i++) |
347 | { delete rowCut_[i] ; |
348 | rowCut_[i] = 0 ; } |
349 | numberCuts_=0; |
350 | } |
351 | }; |
352 | |
353 | #ifdef CGL_DEBUG |
354 | |
355 | static void checkBounds(const OsiRowCutDebugger * debugger,OsiColCut & cut) |
356 | { |
357 | if (debugger) { |
358 | |
359 | const double * optimal = debugger->optimalSolution(); |
360 | int i; |
361 | int nIndex; |
362 | const double * values; |
363 | const int * index; |
364 | const CoinPackedVector & lbs = cut.lbs(); |
365 | values = lbs.getElements(); |
366 | nIndex = lbs.getNumElements(); |
367 | index = lbs.getIndices(); |
368 | for (i=0;i<nIndex;i++) { |
369 | double value=values[i]; |
370 | int iColumn = index[i]; |
371 | printf("%d optimal %g lower %g\n",iColumn,optimal[iColumn],value); |
372 | assert(value<=optimal[iColumn]+1.0e-5); |
373 | } |
374 | const CoinPackedVector & ubs = cut.ubs(); |
375 | values = ubs.getElements(); |
376 | nIndex = ubs.getNumElements(); |
377 | index = ubs.getIndices(); |
378 | for (i=0;i<nIndex;i++) { |
379 | double value=values[i]; |
380 | int iColumn = index[i]; |
381 | printf("%d optimal %g upper %g\n",iColumn,optimal[iColumn],value); |
382 | assert(value>=optimal[iColumn]-1.0e-5); |
383 | } |
384 | } |
385 | } |
386 | #endif |
387 | #define CGL_REASONABLE_INTEGER_BOUND 1.23456789e10 |
388 | |
389 | |
390 | int |
391 | CglProbing::tighten(double *colLower, double * colUpper, |
392 | const int *column, const double *rowElements, |
393 | const CoinBigIndex *rowStart, |
394 | const CoinBigIndex * rowStartPos,const int * rowLength, |
395 | double *rowLower, double *rowUpper, |
396 | int nRows,int nCols,char * intVar,int maxpass, |
397 | double tolerance) |
398 | { |
399 | int i, j, k, kre; |
400 | int krs; |
401 | int dolrows; |
402 | int iflagu, iflagl; |
403 | int ntotal=0,nchange=1,jpass=0; |
404 | double dmaxup, dmaxdown, dbound; |
405 | int ninfeas=0; |
406 | |
407 | double * cliqueMin=NULL; |
408 | double * cliqueMax=NULL; |
409 | |
410 | double * cliqueMin2 = NULL; |
411 | double * cliqueMax2 = NULL; |
412 | if (cliqueRowStart_&&numberRows_&&cliqueRowStart_[numberRows_]) { |
413 | cliqueMin = new double[nCols]; |
414 | cliqueMax = new double[nCols]; |
415 | cliqueMin2 = new double[nCols]; |
416 | cliqueMax2 = new double[nCols]; |
417 | } else { |
418 | |
419 | assert (rowStartPos); |
420 | while(nchange) { |
421 | nchange = 0; |
422 | if (jpass==maxpass) break; |
423 | jpass++; |
424 | dolrows = (jpass & 1) == 1; |
425 | |
426 | for (i = 0; i < nRows; ++i) { |
427 | if (rowLower[i]>-1.0e20||rowUpper[i]<1.0e20) { |
428 | int iflagu = 0; |
429 | int iflagl = 0; |
430 | double dmaxup = 0.0; |
431 | double dmaxdown = 0.0; |
432 | int krs = rowStart[i]; |
433 | int krs2 = rowStartPos[i]; |
434 | int kre = rowStart[i]+rowLength[i]; |
435 | |
436 | |
437 | |
438 | |
439 | for (k = krs; k < krs2; ++k) { |
440 | double value=rowElements[k]; |
441 | int j = column[k]; |
442 | if (colUpper[j] < 1.0e12) |
443 | dmaxdown += colUpper[j] * value; |
444 | else |
445 | ++iflagl; |
446 | if (colLower[j] > -1.0e12) |
447 | dmaxup += colLower[j] * value; |
448 | else |
449 | ++iflagu; |
450 | } |
451 | for (k = krs2; k < kre; ++k) { |
452 | double value=rowElements[k]; |
453 | int j = column[k]; |
454 | if (colUpper[j] < 1.0e12) |
455 | dmaxup += colUpper[j] * value; |
456 | else |
457 | ++iflagu; |
458 | if (colLower[j] > -1.0e12) |
459 | dmaxdown += colLower[j] * value; |
460 | else |
461 | ++iflagl; |
462 | } |
463 | if (iflagu) |
464 | dmaxup=1.0e31; |
465 | if (iflagl) |
466 | dmaxdown=-1.0e31; |
467 | if (dmaxup <= rowUpper[i] + tolerance && dmaxdown >= rowLower[i] - tolerance) { |
468 | |
469 | |
470 | |
471 | |
472 | |
473 | |
474 | |
475 | |
476 | ++nchange; |
477 | rowLower[i]=-COIN_DBL_MAX; |
478 | rowUpper[i]=COIN_DBL_MAX; |
479 | } else { |
480 | if (dmaxup < rowLower[i] -tolerance || dmaxdown > rowUpper[i]+tolerance) { |
481 | ninfeas++; |
482 | break; |
483 | } |
484 | |
485 | |
486 | |
487 | |
488 | if (iflagu == 0 && rowLower[i] > 0.0 && iflagl == 0 && rowUpper[i] < 1e15) { |
489 | if (dolrows) { |
490 | iflagu = 1; |
491 | } else { |
492 | iflagl = 1; |
493 | } |
494 | } |
495 | if (iflagu == 0 && rowLower[i] > -1e15) { |
496 | for (k = krs; k < kre; ++k) { |
497 | double value=rowElements[k]; |
498 | j = column[k]; |
499 | if (value > 0.0) { |
500 | if (colUpper[j] < 1.0e12) { |
501 | dbound = colUpper[j] + (rowLower[i] - dmaxup) / value; |
502 | if (dbound > colLower[j] + 1.0e-8) { |
503 | |
504 | |
505 | colLower[j] = dbound; |
506 | ++nchange; |
507 | |
508 | |
509 | |
510 | |
511 | |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | |
518 | |
519 | |
520 | |
521 | if (colUpper[j] - colLower[j] <= tolerance) { |
522 | |
523 | |
524 | |
525 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
526 | ninfeas++; |
527 | } |
528 | } |
529 | } |
530 | } |
531 | } else { |
532 | if (colLower[j] > -1.0e12) { |
533 | dbound = colLower[j] + (rowLower[i] - dmaxup) / value; |
534 | if (dbound < colUpper[j] - 1.0e-8) { |
535 | colUpper[j] = dbound; |
536 | ++nchange; |
537 | if (colUpper[j] - colLower[j] <= tolerance) { |
538 | |
539 | |
540 | |
541 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
542 | ninfeas++; |
543 | } |
544 | } |
545 | } |
546 | } |
547 | } |
548 | } |
549 | } |
550 | |
551 | |
552 | |
553 | |
554 | if (iflagl == 0 && rowUpper[i] < 1e15) { |
555 | for (k = krs; k < kre; ++k) { |
556 | double value=rowElements[k]; |
557 | j = column[k]; |
558 | if (value < 0.0) { |
559 | if (colUpper[j] < 1.0e12) { |
560 | dbound = colUpper[j] + (rowUpper[i] - dmaxdown) / value; |
561 | if (dbound > colLower[j] + 1.0e-8) { |
562 | colLower[j] = dbound; |
563 | ++nchange; |
564 | if (! (colUpper[j] - colLower[j] > tolerance)) { |
565 | |
566 | |
567 | |
568 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
569 | ninfeas++; |
570 | } |
571 | } |
572 | } |
573 | } |
574 | } else { |
575 | if (colLower[j] > -1.0e12) { |
576 | dbound = colLower[j] + (rowUpper[i] - dmaxdown) / value; |
577 | if (dbound < colUpper[j] - 1.0e-8) { |
578 | colUpper[j] = dbound; |
579 | ++nchange; |
580 | if (! (colUpper[j] - colLower[j] > tolerance)) { |
581 | |
582 | |
583 | |
584 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
585 | ninfeas++; |
586 | } |
587 | } |
588 | } |
589 | } |
590 | } |
591 | } |
592 | } |
593 | } |
594 | } |
595 | } |
596 | for (j = 0; j < nCols; ++j) { |
597 | if (intVar[j]) { |
598 | if (colUpper[j]-colLower[j]>1.0e-8) { |
599 | if (floor(colUpper[j]+1.0e-4)<colUpper[j]) |
600 | nchange++; |
601 | |
602 | colUpper[j]=floor(colUpper[j]+1.0e-4); |
603 | if (ceil(colLower[j]-1.0e-4)>colLower[j]) |
604 | nchange++; |
605 | |
606 | colLower[j]=ceil(colLower[j]-1.0e-4); |
607 | if (colUpper[j]<colLower[j]) { |
608 | |
609 | ninfeas++; |
610 | } |
611 | } |
612 | } |
613 | } |
614 | if (ninfeas) break; |
615 | } |
616 | return (ninfeas); |
617 | } |
618 | |
619 | while(nchange) { |
620 | int ilbred = 0; |
621 | int iubred = 0; |
622 | int nrwdrp = 0; |
623 | if (jpass==maxpass) break; |
624 | jpass++; |
625 | dolrows = (jpass & 1) == 1; |
626 | |
627 | for (i = 0; i < nRows; ++i) { |
628 | bool cliqueChanges=false; |
629 | if (rowLower[i]>-1.0e20||rowUpper[i]<1.0e20) { |
630 | iflagu = 0; |
631 | iflagl = 0; |
632 | dmaxup = 0.0; |
633 | dmaxdown = 0.0; |
634 | krs = rowStart[i]; |
635 | kre = rowStart[i]+rowLength[i]; |
636 | |
637 | |
638 | |
639 | |
640 | if (!cliqueMin||i>=numberRows_||cliqueRowStart_[i]==cliqueRowStart_[i+1]) { |
641 | |
642 | for (k = krs; k < kre; ++k) { |
643 | double value=rowElements[k]; |
644 | j = column[k]; |
645 | if (value > 0.0) { |
646 | if (colUpper[j] < 1.0e12) |
647 | dmaxup += colUpper[j] * value; |
648 | else |
649 | ++iflagu; |
650 | if (colLower[j] > -1.0e12) |
651 | dmaxdown += colLower[j] * value; |
652 | else |
653 | ++iflagl; |
654 | } else if (value<0.0) { |
655 | if (colUpper[j] < 1.0e12) |
656 | dmaxdown += colUpper[j] * value; |
657 | else |
658 | ++iflagl; |
659 | if (colLower[j] > -1.0e12) |
660 | dmaxup += colLower[j] * value; |
661 | else |
662 | ++iflagu; |
663 | } |
664 | } |
665 | if (iflagu) |
666 | dmaxup=1.0e31; |
667 | if (iflagl) |
668 | dmaxdown=-1.0e31; |
669 | } else { |
670 | |
671 | int nClique=0; |
672 | int bias = cliqueRowStart_[i]-krs; |
673 | double dmaxup2=0.0; |
674 | double dmaxdown2=0.0; |
675 | double sumZeroFixes=0.0; |
676 | for (k = krs; k < kre; ++k) { |
677 | double value=rowElements[k]; |
678 | j = column[k]; |
679 | int iClique = sequenceInCliqueEntry(cliqueRow_[k+bias]); |
680 | bool oneFixes = oneFixesInCliqueEntry(cliqueRow_[k+bias]); |
681 | if (iClique>=numberColumns_||colUpper[j]==colLower[j]) { |
682 | if (value > 0.0) { |
683 | if (colUpper[j] >= 1.0e12) { |
684 | dmaxup = 1e31; |
685 | ++iflagu; |
686 | } else { |
687 | dmaxup += colUpper[j] * value; |
688 | } |
689 | if (colLower[j] <= -1.0e12) { |
690 | dmaxdown = -1e31; |
691 | ++iflagl; |
692 | } else { |
693 | dmaxdown += colLower[j] * value; |
694 | } |
695 | } else if (value<0.0) { |
696 | if (colUpper[j] >= 1.0e12) { |
697 | dmaxdown = -1e31; |
698 | ++iflagl; |
699 | } else { |
700 | dmaxdown += colUpper[j] * value; |
701 | } |
702 | if (colLower[j] <= -1.0e12) { |
703 | dmaxup = 1e31; |
704 | ++iflagu; |
705 | } else { |
706 | dmaxup += colLower[j] * value; |
707 | } |
708 | } |
709 | } else { |
710 | |
711 | if (iClique>=nClique) { |
712 | |
713 | for (int j=nClique;j<=iClique;j++) { |
714 | cliqueMin[j]=0.0; |
715 | cliqueMax[j]=0.0; |
716 | cliqueMin2[j]=0.0; |
717 | cliqueMax2[j]=0.0; |
718 | } |
719 | nClique=iClique+1; |
720 | } |
721 | |
722 | if (oneFixes) { |
723 | if (value > 0.0) { |
724 | dmaxup2 += value; |
725 | cliqueMax2[iClique] = cliqueMax[iClique]; |
726 | cliqueMax[iClique] = CoinMax(cliqueMax[iClique],value); |
727 | } else if (value<0.0) { |
728 | dmaxdown2 += value; |
729 | cliqueMin2[iClique] = cliqueMin[iClique]; |
730 | cliqueMin[iClique] = CoinMin(cliqueMin[iClique],value); |
731 | } |
732 | } else { |
733 | sumZeroFixes += value; |
734 | if (value > 0.0) { |
735 | dmaxup2 += value; |
736 | cliqueMin2[iClique] = cliqueMin[iClique]; |
737 | cliqueMin[iClique] = CoinMin(cliqueMin[iClique],-value); |
738 | } else if (value<0.0) { |
739 | dmaxdown2 += value; |
740 | cliqueMax2[iClique] = cliqueMax[iClique]; |
741 | cliqueMax[iClique] = CoinMax(cliqueMax[iClique],-value); |
742 | } |
743 | } |
744 | } |
745 | } |
746 | double dmaxup3 = dmaxup + sumZeroFixes; |
747 | double dmaxdown3 = dmaxdown + sumZeroFixes; |
748 | for (int iClique=0;iClique<nClique;iClique++) { |
749 | dmaxup3 += cliqueMax[iClique]; |
750 | dmaxdown3 += cliqueMin[iClique]; |
751 | } |
752 | dmaxup += dmaxup2; |
753 | dmaxdown += dmaxdown2; |
754 | assert (dmaxup3<=dmaxup+1.0e-8); |
755 | assert (dmaxdown3>=dmaxdown-1.0e-8); |
756 | if (dmaxup3<dmaxup-1.0e-8||dmaxdown3>dmaxdown+1.0e-8) { |
757 | cliqueChanges=true; |
758 | |
759 | |
760 | dmaxdown=dmaxdown3; |
761 | dmaxup=dmaxup3; |
762 | } |
763 | } |
764 | if (dmaxup <= rowUpper[i] + tolerance && dmaxdown >= rowLower[i] - tolerance) { |
765 | |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | |
772 | |
773 | ++nrwdrp; |
774 | rowLower[i]=-COIN_DBL_MAX; |
775 | rowUpper[i]=COIN_DBL_MAX; |
776 | } else { |
777 | if (dmaxup < rowLower[i] -tolerance || dmaxdown > rowUpper[i]+tolerance) { |
778 | ninfeas++; |
779 | assert (!cliqueChanges); |
780 | break; |
781 | } |
782 | |
783 | |
784 | |
785 | |
786 | if (iflagu == 0 && rowLower[i] > 0.0 && iflagl == 0 && rowUpper[i] < 1e15) { |
787 | if (dolrows) { |
788 | iflagu = 1; |
789 | } else { |
790 | iflagl = 1; |
791 | } |
792 | } |
793 | if (!cliqueChanges) { |
794 | |
795 | if (iflagu == 0 && rowLower[i] > -1e15) { |
796 | for (k = krs; k < kre; ++k) { |
797 | double value=rowElements[k]; |
798 | j = column[k]; |
799 | if (value > 0.0) { |
800 | if (colUpper[j] < 1.0e12) { |
801 | dbound = colUpper[j] + (rowLower[i] - dmaxup) / value; |
802 | if (dbound > colLower[j] + 1.0e-8) { |
803 | |
804 | |
805 | colLower[j] = dbound; |
806 | ++ilbred; |
807 | |
808 | |
809 | |
810 | |
811 | |
812 | |
813 | |
814 | |
815 | |
816 | |
817 | |
818 | |
819 | |
820 | |
821 | if (colUpper[j] - colLower[j] <= tolerance) { |
822 | |
823 | |
824 | |
825 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
826 | ninfeas++; |
827 | } |
828 | } |
829 | } |
830 | } |
831 | } else { |
832 | if (colLower[j] > -1.0e12) { |
833 | dbound = colLower[j] + (rowLower[i] - dmaxup) / value; |
834 | if (dbound < colUpper[j] - 1.0e-8) { |
835 | colUpper[j] = dbound; |
836 | ++iubred; |
837 | if (colUpper[j] - colLower[j] <= tolerance) { |
838 | |
839 | |
840 | |
841 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
842 | ninfeas++; |
843 | } |
844 | } |
845 | } |
846 | } |
847 | } |
848 | } |
849 | } |
850 | |
851 | |
852 | |
853 | |
854 | if (iflagl == 0 && rowUpper[i] < 1e15) { |
855 | for (k = krs; k < kre; ++k) { |
856 | double value=rowElements[k]; |
857 | j = column[k]; |
858 | if (value < 0.0) { |
859 | if (colUpper[j] < 1.0e12) { |
860 | dbound = colUpper[j] + (rowUpper[i] - dmaxdown) / value; |
861 | if (dbound > colLower[j] + 1.0e-8) { |
862 | colLower[j] = dbound; |
863 | ++ilbred; |
864 | if (! (colUpper[j] - colLower[j] > tolerance)) { |
865 | |
866 | |
867 | |
868 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
869 | ninfeas++; |
870 | } |
871 | } |
872 | } |
873 | } |
874 | } else { |
875 | if (colLower[j] > -1.0e12) { |
876 | dbound = colLower[j] + (rowUpper[i] - dmaxdown) / value; |
877 | if (dbound < colUpper[j] - 1.0e-8) { |
878 | colUpper[j] = dbound; |
879 | ++iubred; |
880 | if (! (colUpper[j] - colLower[j] > tolerance)) { |
881 | |
882 | |
883 | |
884 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
885 | ninfeas++; |
886 | } |
887 | } |
888 | } |
889 | } |
890 | } |
891 | } |
892 | } |
893 | } else { |
894 | |
895 | int bias = cliqueRowStart_[i]-krs; |
896 | if (iflagu == 0 && rowLower[i] > -1e15) { |
897 | for (k = krs; k < kre; ++k) { |
898 | double value=rowElements[k]; |
899 | j = column[k]; |
900 | int iClique = sequenceInCliqueEntry(cliqueRow_[k+bias]); |
901 | |
902 | if (iClique>=numberColumns_) { |
903 | if (value > 0.0) { |
904 | if (colUpper[j] < 1.0e12) { |
905 | dbound = colUpper[j] + (rowLower[i] - dmaxup) / value; |
906 | if (dbound > colLower[j] + 1.0e-8) { |
907 | |
908 | |
909 | colLower[j] = dbound; |
910 | ++ilbred; |
911 | |
912 | |
913 | |
914 | |
915 | |
916 | |
917 | |
918 | |
919 | |
920 | |
921 | |
922 | |
923 | |
924 | |
925 | if (colUpper[j] - colLower[j] <= tolerance) { |
926 | |
927 | |
928 | |
929 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
930 | ninfeas++; |
931 | } |
932 | } |
933 | #if 0 |
934 | } else if (intVar[j]==1 && rowUpper[i]>1.0e20) { |
935 | |
936 | if (dmaxdown+value>rowLower[i]+1.0e-8) { |
937 | assert (dmaxdown<rowLower[i]+1.0e-8); |
938 | double change = dmaxdown+value - rowLower[i]; |
939 | double newValue = value - change; |
940 | if (newValue<1.0e-12) |
941 | newValue=0.0; |
942 | printf("Could change value from %g to %g\n", |
943 | value,newValue); |
944 | |
945 | } |
946 | #endif |
947 | } |
948 | } |
949 | } else { |
950 | if (colLower[j] > -1.0e12) { |
951 | dbound = colLower[j] + (rowLower[i] - dmaxup) / value; |
952 | if (dbound < colUpper[j] - 1.0e-8) { |
953 | colUpper[j] = dbound; |
954 | ++iubred; |
955 | if (colUpper[j] - colLower[j] <= tolerance) { |
956 | |
957 | |
958 | |
959 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
960 | ninfeas++; |
961 | } |
962 | } |
963 | #if 0 |
964 | } else if (intVar[j]==1 && rowUpper[i]>1.0e20) { |
965 | |
966 | if (dmaxdown-value>rowLower[i]+1.0e-8) { |
967 | assert (dmaxdown<rowLower[i]+1.0e-8); |
968 | double change = dmaxdown-value-rowLower[i]; |
969 | double newValue = value+change; |
970 | double newLower = rowLower[i]+change; |
971 | if (newValue<1.0e-12) |
972 | newValue=0.0; |
973 | printf("Could change value from %g to %g and lorow from %g to %g\n", |
974 | value,newValue,rowLower[i],newLower); |
975 | |
976 | } |
977 | #endif |
978 | } |
979 | } |
980 | } |
981 | } else if (colUpper[j]>colLower[j]) { |
982 | |
983 | |
984 | double dmaxup2=dmaxup; |
985 | assert (cliqueMax[iClique]>=0); |
986 | assert (cliqueMax2[iClique]>=0); |
987 | |
988 | |
989 | if (fabs(value)==fabs(cliqueMax[iClique])) |
990 | dmaxup2 -= cliqueMax[iClique]-cliqueMax2[iClique]; |
991 | if (dmaxup2<rowLower[i]-1.0e-8) { |
992 | |
993 | |
994 | |
995 | if ( dmaxup<rowLower[i]-1.0e-8) { |
996 | ninfeas++; |
997 | } else { |
998 | if (value > 0.0) { |
999 | colLower[j] = 1.0; |
1000 | ++ilbred; |
1001 | } else { |
1002 | colUpper[j] = 0.0; |
1003 | ++iubred; |
1004 | } |
1005 | } |
1006 | } |
1007 | } |
1008 | } |
1009 | } |
1010 | |
1011 | |
1012 | |
1013 | |
1014 | if (iflagl == 0 && rowUpper[i] < 1e15) { |
1015 | for (k = krs; k < kre; ++k) { |
1016 | double value=rowElements[k]; |
1017 | j = column[k]; |
1018 | int iClique = sequenceInCliqueEntry(cliqueRow_[k+bias]); |
1019 | |
1020 | if (iClique>=numberColumns_) { |
1021 | if (value < 0.0) { |
1022 | if (colUpper[j] < 1.0e12) { |
1023 | dbound = colUpper[j] + (rowUpper[i] - dmaxdown) / value; |
1024 | if (dbound > colLower[j] + 1.0e-8) { |
1025 | colLower[j] = dbound; |
1026 | ++ilbred; |
1027 | if (! (colUpper[j] - colLower[j] > tolerance)) { |
1028 | |
1029 | |
1030 | |
1031 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
1032 | ninfeas++; |
1033 | } |
1034 | } |
1035 | #if 0 |
1036 | } else if (intVar[j]==1 && rowLower[i]<-1.0e20) { |
1037 | |
1038 | if (dmaxup+value<rowUpper[i]-1.0e-8) { |
1039 | assert (dmaxup>rowUpper[i]-1.0e-8); |
1040 | double change = dmaxup+value - rowUpper[i]; |
1041 | double newValue = value - change; |
1042 | if (newValue<1.0e-12) |
1043 | newValue=0.0; |
1044 | printf("Could change value from %g to %g b\n", |
1045 | value,newValue); |
1046 | |
1047 | } |
1048 | #endif |
1049 | } |
1050 | } |
1051 | } else { |
1052 | if (colLower[j] > -1.0e12) { |
1053 | dbound = colLower[j] + (rowUpper[i] - dmaxdown) / value; |
1054 | if (dbound < colUpper[j] - 1.0e-8) { |
1055 | colUpper[j] = dbound; |
1056 | ++iubred; |
1057 | if (! (colUpper[j] - colLower[j] > tolerance)) { |
1058 | |
1059 | |
1060 | |
1061 | if (colUpper[j] - colLower[j] < -100.0*tolerance) { |
1062 | ninfeas++; |
1063 | } |
1064 | } |
1065 | #if 0 |
1066 | } else if (intVar[j]==1 && rowLower[i]<-1.0e20) { |
1067 | |
1068 | if (dmaxup-value<rowUpper[i]-1.0e-8) { |
1069 | assert (dmaxup>rowUpper[i]-1.0e-8); |
1070 | double change = dmaxup-value-rowUpper[i]; |
1071 | double newValue = value+change; |
1072 | double newUpper = rowUpper[i]+change; |
1073 | if (newValue<1.0e-12) |
1074 | newValue=0.0; |
1075 | printf("Could change value from %g to %g and uprow from %g to %g b\n", |
1076 | value,newValue,rowLower[i],newUpper); |
1077 | |
1078 | } |
1079 | #endif |
1080 | } |
1081 | } |
1082 | } |
1083 | } else if (colUpper[j]>colLower[j]) { |
1084 | |
1085 | |
1086 | double dmaxdown2=dmaxdown; |
1087 | assert (cliqueMin[iClique]<=0); |
1088 | assert (cliqueMin2[iClique]<=0); |
1089 | |
1090 | |
1091 | if (fabs(value)==fabs(cliqueMin[iClique])) |
1092 | dmaxdown2 -= cliqueMin[iClique]-cliqueMin2[iClique]; |
1093 | if (dmaxdown2>rowUpper[i]+1.0e-8) { |
1094 | |
1095 | |
1096 | |
1097 | if ( dmaxdown>rowUpper[i]+1.0e-8) { |
1098 | ninfeas++; |
1099 | } else { |
1100 | if (value < 0.0) { |
1101 | colLower[j] = 1.0; |
1102 | ++ilbred; |
1103 | } else { |
1104 | colUpper[j] = 0.0; |
1105 | ++iubred; |
1106 | } |
1107 | } |
1108 | } |
1109 | } |
1110 | } |
1111 | } |
1112 | } |
1113 | } |
1114 | } |
1115 | } |
1116 | for (j = 0; j < nCols; ++j) { |
1117 | if (intVar[j]) { |
1118 | if (colUpper[j]-colLower[j]>1.0e-8) { |
1119 | if (floor(colUpper[j]+1.0e-4)<colUpper[j]) |
1120 | nchange++; |
1121 | |
1122 | colUpper[j]=floor(colUpper[j]+1.0e-4); |
1123 | if (ceil(colLower[j]-1.0e-4)>colLower[j]) |
1124 | nchange++; |
1125 | |
1126 | colLower[j]=ceil(colLower[j]-1.0e-4); |
1127 | if (colUpper[j]<colLower[j]) { |
1128 | |
1129 | ninfeas++; |
1130 | } |
1131 | } |
1132 | } |
1133 | } |
1134 | nchange=ilbred+iubred+nrwdrp; |
1135 | ntotal += nchange; |
1136 | if (ninfeas) break; |
1137 | } |
1138 | delete [] cliqueMin; |
1139 | delete [] cliqueMax; |
1140 | delete [] cliqueMin2; |
1141 | delete [] cliqueMax2; |
1142 | return (ninfeas); |
1143 | } |
1144 | |
1145 | void |
1146 | CglProbing::tighten2(double *colLower, double * colUpper, |
1147 | const int *column, const double *rowElements, |
1148 | const CoinBigIndex *rowStart, |
1149 | const int * rowLength, |
1150 | double *rowLower, double *rowUpper, |
1151 | double * minR, double * maxR, int * markR, |
1152 | int nRows) |
1153 | { |
1154 | int i, j, k, kre; |
1155 | int krs; |
1156 | int iflagu, iflagl; |
1157 | double dmaxup, dmaxdown; |
1158 | |
1159 | for (i = 0; i < nRows; ++i) { |
1160 | if (rowLower[i]>-1.0e20||rowUpper[i]<1.0e20) { |
1161 | iflagu = 0; |
1162 | iflagl = 0; |
1163 | dmaxup = 0.0; |
1164 | dmaxdown = 0.0; |
1165 | krs = rowStart[i]; |
1166 | kre = rowStart[i]+rowLength[i]; |
1167 | |
1168 | |
1169 | |
1170 | |
1171 | for (k = krs; k < kre; ++k) { |
1172 | double value=rowElements[k]; |
1173 | j = column[k]; |
1174 | if (value > 0.0) { |
1175 | if (colUpper[j] < 1.0e12) |
1176 | dmaxup += colUpper[j] * value; |
1177 | else |
1178 | ++iflagu; |
1179 | if (colLower[j] > -1.0e12) |
1180 | dmaxdown += colLower[j] * value; |
1181 | else |
1182 | ++iflagl; |
1183 | } else if (value<0.0) { |
1184 | if (colUpper[j] < 1.0e12) |
1185 | dmaxdown += colUpper[j] * value; |
1186 | else |
1187 | ++iflagl; |
1188 | if (colLower[j] > -1.0e12) |
1189 | dmaxup += colLower[j] * value; |
1190 | else |
1191 | ++iflagu; |
1192 | } |
1193 | } |
1194 | if (iflagu) |
1195 | maxR[i]=1.0e60; |
1196 | else |
1197 | maxR[i]=dmaxup; |
1198 | if (iflagl) |
1199 | minR[i]=-1.0e60; |
1200 | else |
1201 | minR[i]=dmaxdown; |
1202 | #if 0 |
1203 | if (minR[i]<-1.0e10&&maxR[i]>1.0e10) { |
1204 | markR[i]=-2; |
1205 | } else { |
1206 | #endif |
1207 | markR[i]=-1; |
1208 | #if 0 |
1209 | } |
1210 | #endif |
1211 | } else { |
1212 | minR[i]=-1.0e60; |
1213 | maxR[i]=1.0e60; |
1214 | #if 0 |
1215 | markR[i]=-2; |
1216 | abort(); |
1217 | #else |
1218 | markR[i]=-1; |
1219 | #endif |
1220 | } |
1221 | } |
1222 | } |
1223 | #ifdef CGL_DEBUG |
1224 | static int nPath=0; |
1225 | #endif |
1226 | |
1227 | |
1228 | |
1229 | void CglProbing::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, |
1230 | const CglTreeInfo info2) |
1231 | { |
1232 | |
1233 | #ifdef CGL_DEBUG |
1234 | const OsiRowCutDebugger * debugger = si.getRowCutDebugger(); |
1235 | if (debugger&&debugger->onOptimalPath(si)) { |
1236 | printf("On optimal path %d\n",nPath); |
1237 | nPath++; |
1238 | int nCols=si.getNumCols(); |
1239 | int i; |
1240 | const double * solution = si.getColSolution(); |
1241 | const double * lower = si.getColLower(); |
1242 | const double * upper = si.getColUpper(); |
1243 | const double * optimal = debugger->optimalSolution(); |
1244 | const double * objective = si.getObjCoefficients(); |
1245 | double objval1=0.0,objval2=0.0; |
1246 | for (i=0;i<nCols;i++) { |
1247 | #if CGL_DEBUG>1 |
1248 | printf("%d %g %g %g %g\n",i,lower[i],solution[i],upper[i],optimal[i]); |
1249 | #endif |
1250 | objval1 += solution[i]*objective[i]; |
1251 | objval2 += optimal[i]*objective[i]; |
1252 | assert(optimal[i]>=lower[i]&&optimal[i]<=upper[i]); |
1253 | } |
1254 | printf("current obj %g, integer %g\n",objval1,objval2); |
1255 | } |
1256 | #endif |
1257 | int saveRowCuts=rowCuts_; |
1258 | if (rowCuts_<0) { |
1259 | if (info2.inTree) |
1260 | rowCuts_=4; |
1261 | else |
1262 | rowCuts_=-rowCuts_; |
1263 | } |
1264 | int nRows=si.getNumRows(); |
1265 | double * rowLower = new double[nRows+1]; |
1266 | double * rowUpper = new double[nRows+1]; |
1267 | |
1268 | int nCols=si.getNumCols(); |
1269 | |
1270 | if (!rowCopy_) { |
1271 | numberRows_=nRows; |
1272 | numberColumns_=nCols; |
1273 | } |
1274 | double * colLower = new double[nCols]; |
1275 | double * colUpper = new double[nCols]; |
1276 | |
1277 | CglTreeInfo info = info2; |
1278 | int ninfeas=gutsOfGenerateCuts(si,cs,rowLower,rowUpper,colLower,colUpper,&info); |
1279 | if (ninfeas) { |
1280 | |
1281 | OsiRowCut rc; |
1282 | rc.setLb(COIN_DBL_MAX); |
1283 | rc.setUb(0.0); |
1284 | cs.insert(rc); |
1285 | #ifdef CGL_DEBUG |
1286 | const OsiRowCutDebugger * debugger = si.getRowCutDebugger(); |
1287 | if (debugger&&debugger->onOptimalPath(si)) |
1288 | assert(!debugger->invalidCut(rc)); |
1289 | #endif |
1290 | } |
1291 | delete [] rowLower; |
1292 | delete [] rowUpper; |
1293 | delete [] colLower; |
1294 | delete [] colUpper; |
1295 | delete [] colLower_; |
1296 | delete [] colUpper_; |
1297 | colLower_ = NULL; |
1298 | colUpper_ = NULL; |
1299 | rowCuts_=saveRowCuts; |
1300 | } |
1301 | int CglProbing::generateCutsAndModify(const OsiSolverInterface & si, |
1302 | OsiCuts & cs, |
1303 | CglTreeInfo * info) |
1304 | { |
1305 | #ifdef CGL_DEBUG |
1306 | const OsiRowCutDebugger * debugger = si.getRowCutDebugger(); |
1307 | if (debugger&&debugger->onOptimalPath(si)) { |
1308 | printf("On optimal path %d\n",nPath); |
1309 | nPath++; |
1310 | int nCols=si.getNumCols(); |
1311 | int i; |
1312 | const double * solution = si.getColSolution(); |
1313 | const double * lower = si.getColLower(); |
1314 | const double * upper = si.getColUpper(); |
1315 | const double * optimal = debugger->optimalSolution(); |
1316 | const double * objective = si.getObjCoefficients(); |
1317 | double objval1=0.0,objval2=0.0; |
1318 | for (i=0;i<nCols;i++) { |
1319 | #if CGL_DEBUG>1 |
1320 | printf("%d %g %g %g %g\n",i,lower[i],solution[i],upper[i],optimal[i]); |
1321 | #endif |
1322 | objval1 += solution[i]*objective[i]; |
1323 | objval2 += optimal[i]*objective[i]; |
1324 | assert(optimal[i]>=lower[i]-1.0e-5&&optimal[i]<=upper[i]+1.0e-5); |
1325 | } |
1326 | printf("current obj %g, integer %g\n",objval1,objval2); |
1327 | } |
1328 | #endif |
1329 | int saveRowCuts=rowCuts_; |
1330 | if (rowCuts_<0) { |
1331 | if (info->inTree) |
1332 | rowCuts_=4; |
1333 | else |
1334 | rowCuts_=-rowCuts_; |
1335 | } |
1336 | int saveMode = mode_; |
1337 | bool rowCliques=false; |
1338 | if (!mode_) { |
1339 | if (info->pass!=4||info->inTree) { |
1340 | mode_=1; |
1341 | } else { |
1342 | saveMode=1; |
1343 | rowCliques=true; |
1344 | } |
1345 | } |
1346 | int nRows=si.getNumRows(); |
1347 | double * rowLower = new double[nRows+1]; |
1348 | double * rowUpper = new double[nRows+1]; |
1349 | |
1350 | int nCols=si.getNumCols(); |
1351 | double * colLower = new double[nCols]; |
1352 | double * colUpper = new double[nCols]; |
1353 | |
1354 | int ninfeas=gutsOfGenerateCuts(si,cs,rowLower,rowUpper,colLower,colUpper,info); |
1355 | if (ninfeas) { |
1356 | |
1357 | OsiRowCut rc; |
1358 | rc.setLb(COIN_DBL_MAX); |
1359 | rc.setUb(0.0); |
1360 | cs.insert(rc); |
1361 | #ifdef CGL_DEBUG |
1362 | const OsiRowCutDebugger * debugger = si.getRowCutDebugger(); |
1363 | if (debugger&&debugger->onOptimalPath(si)) |
1364 | assert(!debugger->invalidCut(rc)); |
1365 | #endif |
1366 | } |
1367 | rowCuts_=saveRowCuts; |
1368 | mode_=saveMode; |
1369 | |
1370 | if (mode_==3) { |
1371 | delete [] rowLower_; |
1372 | delete [] rowUpper_; |
1373 | rowLower_ = rowLower; |
1374 | rowUpper_ = rowUpper; |
1375 | } else { |
1376 | delete [] rowLower; |
1377 | delete [] rowUpper; |
1378 | } |
1379 | delete [] colLower_; |
1380 | delete [] colUpper_; |
1381 | colLower_ = colLower; |
1382 | colUpper_ = colUpper; |
1383 | |
1384 | if (rowCliques&&numberRows_&&numberColumns_) |
1385 | setupRowCliqueInformation(si); |
1386 | return ninfeas; |
1387 | } |
1388 | bool analyze(const OsiSolverInterface * solverX, char * intVar, |
1389 | double * lower, double * upper) |
1390 | { |
1391 | OsiSolverInterface * solver = solverX->clone(); |
1392 | const double *objective = solver->getObjCoefficients() ; |
1393 | int numberColumns = solver->getNumCols() ; |
1394 | int numberRows = solver->getNumRows(); |
1395 | double direction = solver->getObjSense(); |
1396 | int iRow,iColumn; |
1397 | |
1398 | |
1399 | CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); |
1400 | const double * elementByRow = matrixByRow.getElements(); |
1401 | const int * column = matrixByRow.getIndices(); |
1402 | const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); |
1403 | const int * rowLength = matrixByRow.getVectorLengths(); |
1404 | |
1405 | |
1406 | CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); |
1407 | const double * element = matrixByCol.getElements(); |
1408 | const int * row = matrixByCol.getIndices(); |
1409 | const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); |
1410 | const int * columnLength = matrixByCol.getVectorLengths(); |
1411 | |
1412 | const double * rowLower = solver->getRowLower(); |
1413 | const double * rowUpper = solver->getRowUpper(); |
1414 | |
1415 | char * ignore = new char [numberRows]; |
1416 | int * which = new int[numberRows]; |
1417 | double * changeRhs = new double[numberRows]; |
1418 | memset(changeRhs,0,numberRows*sizeof(double)); |
1419 | memset(ignore,0,numberRows); |
1420 | int numberChanged=0; |
1421 | bool finished=false; |
1422 | while (!finished) { |
1423 | int saveNumberChanged = numberChanged; |
1424 | for (iRow=0;iRow<numberRows;iRow++) { |
1425 | int numberContinuous=0; |
1426 | double value1=0.0,value2=0.0; |
1427 | bool allIntegerCoeff=true; |
1428 | double sumFixed=0.0; |
1429 | int jColumn1=-1,jColumn2=-1; |
1430 | for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { |
1431 | int jColumn = column[j]; |
1432 | double value = elementByRow[j]; |
1433 | if (upper[jColumn] > lower[jColumn]+1.0e-8) { |
1434 | if (!intVar[jColumn]) { |
1435 | if (numberContinuous==0) { |
1436 | jColumn1=jColumn; |
1437 | value1=value; |
1438 | } else { |
1439 | jColumn2=jColumn; |
1440 | value2=value; |
1441 | } |
1442 | numberContinuous++; |
1443 | } else { |
1444 | if (fabs(value-floor(value+0.5))>1.0e-12) |
1445 | allIntegerCoeff=false; |
1446 | } |
1447 | } else { |
1448 | sumFixed += lower[jColumn]*value; |
1449 | } |
1450 | } |
1451 | double low = rowLower[iRow]; |
1452 | if (low>-1.0e20) { |
1453 | low -= sumFixed; |
1454 | if (fabs(low-floor(low+0.5))>1.0e-12) |
1455 | allIntegerCoeff=false; |
1456 | } |
1457 | double up = rowUpper[iRow]; |
1458 | if (up<1.0e20) { |
1459 | up -= sumFixed; |
1460 | if (fabs(up-floor(up+0.5))>1.0e-12) |
1461 | allIntegerCoeff=false; |
1462 | } |
1463 | if (!allIntegerCoeff) |
1464 | continue; |
1465 | if (numberContinuous==1) { |
1466 | |
1467 | |
1468 | if (low==up) { |
1469 | if (fabs(value1)>1.0e-3) { |
1470 | value1 = 1.0/value1; |
1471 | if (fabs(value1-floor(value1+0.5))<1.0e-12) { |
1472 | |
1473 | numberChanged++; |
1474 | intVar[jColumn1]=77; |
1475 | } |
1476 | } |
1477 | } else { |
1478 | if (fabs(value1)>1.0e-3) { |
1479 | value1 = 1.0/value1; |
1480 | if (fabs(value1-floor(value1+0.5))<1.0e-12) { |
1481 | |
1482 | ignore[iRow]=1; |
1483 | } |
1484 | } |
1485 | } |
1486 | } else if (numberContinuous==2) { |
1487 | if (low==up) { |
1488 | |
1489 | |
1490 | |
1491 | |
1492 | |
1493 | if (fabs(value1)==1.0&&value1*value2==-1.0&&!lower[jColumn1] |
1494 | &&!lower[jColumn2]&&columnLength[jColumn1]==1&&columnLength[jColumn2]==1) { |
1495 | int n=0; |
1496 | int i; |
1497 | double objChange=direction*(objective[jColumn1]+objective[jColumn2]); |
1498 | double bound = CoinMin(upper[jColumn1],upper[jColumn2]); |
1499 | bound = CoinMin(bound,1.0e20); |
1500 | for ( i=columnStart[jColumn1];i<columnStart[jColumn1]+columnLength[jColumn1];i++) { |
1501 | int jRow = row[i]; |
1502 | double value = element[i]; |
1503 | if (jRow!=iRow) { |
1504 | which[n++]=jRow; |
1505 | changeRhs[jRow]=value; |
1506 | } |
1507 | } |
1508 | for ( i=columnStart[jColumn2];i<columnStart[jColumn2]+columnLength[jColumn2];i++) { |
1509 | int jRow = row[i]; |
1510 | double value = element[i]; |
1511 | if (jRow!=iRow) { |
1512 | if (!changeRhs[jRow]) { |
1513 | which[n++]=jRow; |
1514 | changeRhs[jRow]=value; |
1515 | } else { |
1516 | changeRhs[jRow]+=value; |
1517 | } |
1518 | } |
1519 | } |
1520 | if (objChange>=0.0) { |
1521 | |
1522 | bool good=true; |
1523 | for (i=0;i<n;i++) { |
1524 | int jRow = which[i]; |
1525 | double value = changeRhs[jRow]; |
1526 | if (value) { |
1527 | value *= bound; |
1528 | if (rowLength[jRow]==1) { |
1529 | if (value>0.0) { |
1530 | double rhs = rowLower[jRow]; |
1531 | if (rhs>0.0) { |
1532 | double ratio =rhs/value; |
1533 | if (fabs(ratio-floor(ratio+0.5))>1.0e-12) |
1534 | good=false; |
1535 | } |
1536 | } else { |
1537 | double rhs = rowUpper[jRow]; |
1538 | if (rhs<0.0) { |
1539 | double ratio =rhs/value; |
1540 | if (fabs(ratio-floor(ratio+0.5))>1.0e-12) |
1541 | good=false; |
1542 | } |
1543 | } |
1544 | } else if (rowLength[jRow]==2) { |
1545 | if (value>0.0) { |
1546 | if (rowLower[jRow]>-1.0e20) |
1547 | good=false; |
1548 | } else { |
1549 | if (rowUpper[jRow]<1.0e20) |
1550 | good=false; |
1551 | } |
1552 | } else { |
1553 | good=false; |
1554 | } |
1555 | } |
1556 | } |
1557 | if (good) { |
1558 | |
1559 | numberChanged++; |
1560 | intVar[jColumn1]=77; |
1561 | numberChanged++; |
1562 | intVar[jColumn2]=77; |
1563 | } |
1564 | } |
1565 | |
1566 | for (i=0;i<n;i++) { |
1567 | changeRhs[which[i]]=0.0; |
1568 | } |
1569 | } |
1570 | } |
1571 | } |
1572 | } |
1573 | for (iColumn=0;iColumn<numberColumns;iColumn++) { |
1574 | if (upper[iColumn] > lower[iColumn]+1.0e-8&&!intVar[iColumn]) { |
1575 | double value; |
1576 | value = upper[iColumn]; |
1577 | if (value<1.0e20&&fabs(value-floor(value+0.5))>1.0e-12) |
1578 | continue; |
1579 | value = lower[iColumn]; |
1580 | if (value>-1.0e20&&fabs(value-floor(value+0.5))>1.0e-12) |
1581 | continue; |
1582 | bool integer=true; |
1583 | for (CoinBigIndex j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) { |
1584 | int iRow = row[j]; |
1585 | if (!ignore[iRow]) { |
1586 | integer=false; |
1587 | break; |
1588 | } |
1589 | } |
1590 | if (integer) { |
1591 | |
1592 | numberChanged++; |
1593 | intVar[iColumn]=77; |
1594 | } |
1595 | } |
1596 | } |
1597 | finished = numberChanged==saveNumberChanged; |
1598 | } |
1599 | bool feasible=true; |
1600 | for (iColumn=0;iColumn<numberColumns;iColumn++) { |
1601 | if (intVar[iColumn]==77) { |
1602 | if (upper[iColumn]>1.0e20) { |
1603 | upper[iColumn] = 1.0e20; |
1604 | } else { |
1605 | upper[iColumn] = floor(upper[iColumn]+1.0e-5); |
1606 | } |
1607 | if (lower[iColumn]<-1.0e20) { |
1608 | lower[iColumn] = -1.0e20; |
1609 | } else { |
1610 | lower[iColumn] = ceil(lower[iColumn]-1.0e-5); |
1611 | if (lower[iColumn]>upper[iColumn]) |
1612 | feasible=false; |
1613 | } |
1614 | if (lower[iColumn]==0.0&&upper[iColumn]==1.0) |
1615 | intVar[iColumn]=1; |
1616 | else if (lower[iColumn]==upper[iColumn]) |
1617 | intVar[iColumn]=0; |
1618 | else |
1619 | intVar[iColumn]=2; |
1620 | } |
1621 | } |
1622 | delete [] which; |
1623 | delete [] changeRhs; |
1624 | delete [] ignore; |
1625 | |
1626 | |
1627 | delete solver; |
1628 | return feasible; |
1629 | } |
1630 | int CglProbing::gutsOfGenerateCuts(const OsiSolverInterface & si, |
1631 | OsiCuts & cs , |
1632 | double * rowLower, double * rowUpper, |
1633 | double * colLower, double * colUpper, |
1634 | CglTreeInfo * info) |
1635 | { |
1636 | |
1637 | |
1638 | int nRows; |
1639 | |
1640 | CoinPackedMatrix * rowCopy=NULL; |
1641 | int numberRowCutsBefore = cs.sizeRowCuts(); |
1642 | |
1643 | |
1644 | double cutoff; |
1645 | bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff); |
1646 | if (!cutoff_available||usingObjective_<0) { |
| 1 | Assuming 'cutoff_available' is true | |
|
| 2 | | Assuming field 'usingObjective_' is >= 0 | |
|
| |
1647 | cutoff = si.getInfinity(); |
1648 | } |
1649 | cutoff *= si.getObjSense(); |
1650 | if (fabs(cutoff)>1.0e30) |
| 4 | | Assuming the condition is false | |
|
| |
1651 | assert (cutoff>1.0e30); |
1652 | int mode=mode_; |
1653 | |
1654 | int nCols=si.getNumCols(); |
1655 | |
1656 | |
1657 | const char * intVarOriginal = si.getColType(true); |
1658 | char * intVar = CoinCopyOfArray(intVarOriginal,nCols); |
1659 | int i; |
1660 | int numberIntegers=0; |
1661 | CoinMemcpyN(si.getColLower(),nCols,colLower); |
1662 | CoinMemcpyN(si.getColUpper(),nCols,colUpper); |
1663 | const double * colsol =si.getColSolution(); |
1664 | |
1665 | for (i=0;i<nCols;i++) { |
| 6 | | Assuming 'i' is >= 'nCols' | |
|
| 7 | | Loop condition is false. Execution continues on line 1677 | |
|
1666 | if (intVar[i]) { |
1667 | numberIntegers++; |
1668 | if (intVar[i]==2) { |
1669 | |
1670 | if (colsol[i]<1.0e10&&colUpper[i]>1.0e12) |
1671 | colUpper[i] = CGL_REASONABLE_INTEGER_BOUND; |
1672 | if (colsol[i]>-1.0e10&&colLower[i]<-1.0e12) |
1673 | colLower[i] = -CGL_REASONABLE_INTEGER_BOUND; |
1674 | } |
1675 | } |
1676 | } |
1677 | bool feasible=true; |
1678 | if (!info->inTree&&!info->pass) { |
| 8 | | Assuming field 'inTree' is true | |
|
1679 | |
1680 | feasible = analyze(&si,intVar,colLower,colUpper); |
1681 | } |
1682 | if (feasible&&PROBING_EXTRA_STUFF) { |
| |
1683 | |
1684 | |
1685 | const double * djs =si.getReducedCost(); |
1686 | const double * colsol =si.getColSolution(); |
1687 | double direction = si.getObjSense(); |
1688 | double cutoff; |
1689 | bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff); |
1690 | if (!cutoff_available||usingObjective_<0) { |
1691 | cutoff = si.getInfinity(); |
1692 | } |
1693 | cutoff *= direction; |
1694 | if (fabs(cutoff)>1.0e30) |
1695 | assert (cutoff>1.0e30); |
1696 | double current = si.getObjValue(); |
1697 | current *= direction; |
1698 | double gap=CoinMax(cutoff-current,1.0e-1); |
1699 | for (int i = 0; i < nCols; ++i) { |
1700 | double djValue = djs[i]*direction; |
1701 | if (colUpper[i]-colLower[i]>1.0e-8) { |
1702 | if (colsol[i]<colLower[i]+primalTolerance_) { |
1703 | if (djValue>gap) { |
1704 | if (si.isInteger(i)) { |
1705 | printf("why int %d not fixed at lb\n",i); |
1706 | colUpper[i]= colLower[i]; |
1707 | } else { |
1708 | double newUpper = colLower[i] + gap/djValue; |
1709 | if (newUpper<colUpper[i]) { |
1710 | |
1711 | colUpper[i]= CoinMax(newUpper,colLower[i]+1.0e-5); |
1712 | } |
1713 | } |
1714 | } |
1715 | } else if (colsol[i]>colUpper[i]-primalTolerance_) { |
1716 | if (-djValue>gap) { |
1717 | if (si.isInteger(i)) { |
1718 | printf("why int %d not fixed at ub\n",i); |
1719 | colLower[i]= colUpper[i]; |
1720 | } else { |
1721 | double newLower = colUpper[i] + gap/djValue; |
1722 | if (newLower>colLower[i]) { |
1723 | |
1724 | colLower[i]= CoinMin(newLower,colUpper[i]-1.0e-5); |
1725 | } |
1726 | } |
1727 | } |
1728 | } |
1729 | } |
1730 | } |
1731 | } |
1732 | int ninfeas=0; |
1733 | |
1734 | int maxProbe = info->inTree ? maxProbe_ : maxProbeRoot_; |
| |
1735 | int maxElements = info->inTree ? maxElements_ : maxElementsRoot_; |
| |
1736 | |
1737 | |
1738 | |
1739 | double offset; |
1740 | si.getDblParam(OsiObjOffset,offset); |
1741 | #ifdef COIN_DEVELOP |
1742 | if (offset&&!info->inTree&&!info->pass) |
1743 | printf("CglProbing obj offset %g\n",offset); |
1744 | #endif |
1745 | |
1746 | if (!rowCopy_) { |
| 12 | | Assuming field 'rowCopy_' is non-null | |
|
| |
1747 | |
1748 | nRows=si.getNumRows(); |
1749 | |
1750 | |
1751 | if (mode==0) |
1752 | mode=1; |
1753 | |
1754 | if (cutoff<1.0e30&&usingObjective_>0) { |
1755 | rowCopy = new CoinPackedMatrix(*si.getMatrixByRow(),1,nCols,false); |
1756 | } else { |
1757 | rowCopy = new CoinPackedMatrix(*si.getMatrixByRow()); |
1758 | } |
1759 | |
1760 | if (cutoff<1.0e30&&usingObjective_>0) { |
1761 | int * columns = new int[nCols]; |
1762 | double * elements = new double[nCols]; |
1763 | int n=0; |
1764 | const double * objective = si.getObjCoefficients(); |
1765 | bool maximize = (si.getObjSense()==-1); |
1766 | for (i=0;i<nCols;i++) { |
1767 | if (objective[i]) { |
1768 | elements[n]= (maximize) ? -objective[i] : objective[i]; |
1769 | columns[n++]=i; |
1770 | } |
1771 | } |
1772 | rowCopy->appendRow(n,columns,elements); |
1773 | delete [] columns; |
1774 | delete [] elements; |
1775 | CoinMemcpyN(si.getRowLower(),nRows,rowLower); |
1776 | CoinMemcpyN(si.getRowUpper(),nRows,rowUpper); |
1777 | rowLower[nRows]=-COIN_DBL_MAX; |
1778 | rowUpper[nRows]=cutoff+offset; |
1779 | nRows++; |
1780 | } else { |
1781 | CoinMemcpyN(si.getRowLower(),nRows,rowLower); |
1782 | CoinMemcpyN(si.getRowUpper(),nRows,rowUpper); |
1783 | } |
1784 | } else { |
1785 | |
1786 | nRows=numberRows_; |
1787 | assert(nCols==numberColumns_); |
1788 | |
1789 | rowCopy = new CoinPackedMatrix(*rowCopy_); |
1790 | assert (rowCopy_->getNumRows()==numberRows_); |
1791 | rowLower = new double[nRows]; |
1792 | rowUpper = new double[nRows]; |
1793 | CoinMemcpyN(rowLower_,nRows,rowLower); |
1794 | CoinMemcpyN(rowUpper_,nRows,rowUpper); |
1795 | if (usingObjective_>0) { |
| 14 | | Assuming field 'usingObjective_' is <= 0 | |
|
| |
1796 | rowLower[nRows-1]=-COIN_DBL_MAX; |
1797 | rowUpper[nRows-1]=cutoff+offset; |
1798 | } |
1799 | } |
1800 | CoinBigIndex * rowStartPos = NULL; |
1801 | int * realRows = NULL; |
1802 | { |
1803 | |
1804 | int * rowLength = rowCopy->getMutableVectorLengths(); |
1805 | |
1806 | double * elements = rowCopy->getMutableElements(); |
1807 | int * column = rowCopy->getMutableIndices(); |
1808 | CoinBigIndex * rowStart = rowCopy->getMutableVectorStarts(); |
1809 | #ifdef OUTRUBBISH |
1810 | double large=1.0e3; |
1811 | #endif |
1812 | int nDelete = 0; |
1813 | int nKeep=0; |
1814 | int * which = new int[nRows]; |
1815 | int nElements=rowCopy->getNumElements(); |
1816 | int nTotalOut=0; |
1817 | int nRealRows = si.getNumRows(); |
1818 | for (i=0;i<nRows;i++) { |
| 16 | | Assuming 'i' is >= 'nRows' | |
|
| 17 | | Loop condition is false. Execution continues on line 1826 | |
|
1819 | if (rowLength[i]>maxElements||(rowLower[i]<-1.0e20&&rowUpper[i]>1.0e20)) { |
1820 | |
1821 | if (i<nRealRows) |
1822 | nTotalOut+=rowLength[i]; |
1823 | } |
1824 | } |
1825 | |
1826 | if (nTotalOut*10<nElements) |
| 18 | | Assuming the condition is false | |
|
| |
1827 | maxElements=nCols; |
1828 | #ifdef OUTRUBBISH |
1829 | int nExtraDel=0; |
1830 | #endif |
1831 | for (i=0;i<nRows;i++) { |
| 20 | | Loop condition is false. Execution continues on line 1946 | |
|
1832 | if ((rowLength[i]>maxElements&&i<nRealRows)|| |
1833 | (rowLower[i]<-1.0e20&&rowUpper[i]>1.0e20)) { |
1834 | which[nDelete++]=i; |
1835 | } else { |
1836 | #ifdef OUTRUBBISH |
1837 | |
1838 | int nPlus=rowUpper[i]>-large ? 0 : 1; |
1839 | int nMinus=rowLower[i]<large ? 0 : 1; |
1840 | CoinBigIndex start = rowStart[i]; |
1841 | CoinBigIndex end = start + rowLength[i]; |
1842 | for (CoinBigIndex j=start; j<end ; j++) { |
1843 | int iColumn = column[j]; |
1844 | if (colUpper[iColumn]>large) { |
1845 | if (elements[j]>0.0) |
1846 | nPlus++; |
1847 | else |
1848 | nMinus++; |
1849 | } |
1850 | if (colLower[iColumn]<-large) { |
1851 | if (elements[j]<0.0) |
1852 | nPlus++; |
1853 | else |
1854 | nMinus++; |
1855 | } |
1856 | } |
1857 | if (!nPlus||!nMinus) { |
1858 | rowLower[nKeep]=rowLower[i]; |
1859 | rowUpper[nKeep]=rowUpper[i]; |
1860 | nKeep++; |
1861 | } else { |
1862 | nExtraDel++; |
1863 | which[nDelete++]=i; |
1864 | } |
1865 | #else |
1866 | if (info->strengthenRow&&!info->pass&&(rowLower[i]<-1.0e20||rowUpper[i]>1.0e20)) { |
1867 | int nPlus=0; |
1868 | int nMinus=0; |
1869 | for (CoinBigIndex j=rowStart[i];j<rowStart[i+1];j++) { |
1870 | int jColumn=column[j]; |
1871 | if (intVar[jColumn]&&colLower[jColumn]==0.0&&colUpper[jColumn]==1.0) { |
1872 | double value=elements[j]; |
1873 | if (value>0.0) { |
1874 | nPlus++; |
1875 | } else { |
1876 | nMinus++; |
1877 | } |
1878 | } else { |
1879 | nPlus=2; |
1880 | nMinus=2; |
1881 | break; |
1882 | } |
1883 | } |
1884 | double effectiveness=0.0; |
1885 | if (nPlus==1&&rowUpper[i]>0.0&&rowUpper[i]<1.0e10) { |
1886 | |
1887 | for (CoinBigIndex j=rowStart[i];j<rowStart[i+1];j++) { |
1888 | double value=elements[j]; |
1889 | if (value>0.0) { |
1890 | elements[j] -= rowUpper[i]; |
1891 | |
1892 | |
1893 | } |
1894 | effectiveness += fabs(elements[j]); |
1895 | } |
1896 | rowUpper[i]=0.0; |
1897 | } else if (nMinus==1&&rowLower[i]<0.0&&rowLower[i]>-1.0e10) { |
1898 | |
1899 | for (CoinBigIndex j=rowStart[i];j<rowStart[i+1];j++) { |
1900 | double value=elements[j]; |
1901 | if (value<0.0) { |
1902 | elements[j] -= rowLower[i]; |
1903 | |
1904 | |
1905 | } |
1906 | effectiveness += fabs(elements[j]); |
1907 | } |
1908 | rowLower[i]=0.0; |
1909 | } |
1910 | if (effectiveness) { |
1911 | OsiRowCut rc; |
1912 | rc.setLb(rowLower[i]); |
1913 | rc.setUb(rowUpper[i]); |
1914 | int start = rowStart[i]; |
1915 | int n = rowLength[i]; |
1916 | rc.setRow(rowLength[i],column+start,elements+start,false); |
1917 | |
1918 | CoinPackedVector & row = rc.mutableRow(); |
1919 | double * elements = row.getElements(); |
1920 | int n2=0; |
1921 | for (n2=0;n2<n;n2++) { |
1922 | if (fabs(elements[n2])<1.0e-12) |
1923 | break; |
1924 | } |
1925 | if (n2<n) { |
1926 | int * columns = row.getIndices(); |
1927 | for (int i=n2+1;i<n;i++) { |
1928 | if (fabs(elements[i])>1.0e-12) { |
1929 | elements[n2]=elements[i]; |
1930 | columns[n2++]=columns[i]; |
1931 | } |
1932 | } |
1933 | row.truncate(n2); |
1934 | } |
1935 | rc.setEffectiveness(effectiveness); |
1936 | assert (!info->strengthenRow[i]); |
1937 | info->strengthenRow[i]=rc.clone(); |
1938 | } |
1939 | } |
1940 | rowLower[nKeep]=rowLower[i]; |
1941 | rowUpper[nKeep]=rowUpper[i]; |
1942 | nKeep++; |
1943 | #endif |
1944 | } |
1945 | } |
1946 | if (nDelete) { |
| |
1947 | #ifdef OUTRUBBISH |
1948 | if (nExtraDel) { |
1949 | printf("%d rows deleted (extra %d)\n",nDelete,nExtraDel); |
1950 | } |
1951 | #else |
1952 | #endif |
1953 | if (info->strengthenRow) { |
1954 | |
1955 | realRows = new int [nRows]; |
1956 | CoinZeroN(realRows,nRows); |
1957 | for (i=0;i<nDelete;i++) |
1958 | realRows[which[i]]=-1; |
1959 | int k=0; |
1960 | for (i=0;i<nRows;i++) { |
1961 | if (!realRows[i]) { |
1962 | if (i<nRealRows) |
1963 | realRows[k++]=i; |
1964 | else |
1965 | realRows[k++]=-1; |
1966 | } |
1967 | } |
1968 | } |
1969 | rowCopy->deleteRows(nDelete,which); |
1970 | nRows=nKeep; |
1971 | } |
1972 | delete [] which; |
1973 | if (!nRows) { |
| |
1974 | #ifdef COIN_DEVELOP |
1975 | printf("All rows too long for probing\n"); |
1976 | #endif |
1977 | |
1978 | |
1979 | delete rowCopy; |
1980 | if (rowCopy_) { |
1981 | delete [] rowLower; |
1982 | delete [] rowUpper; |
1983 | } |
1984 | delete [] intVar; |
1985 | |
1986 | const double * trueLower = si.getColLower(); |
1987 | const double * trueUpper = si.getColUpper(); |
1988 | for (i=0;i<nCols;i++) { |
1989 | if (intVarOriginal[i]==2) { |
1990 | if (colUpper[i] == CGL_REASONABLE_INTEGER_BOUND) |
1991 | colUpper[i] = trueUpper[i]; |
1992 | if (colLower[i] == -CGL_REASONABLE_INTEGER_BOUND) |
1993 | colLower[i] = trueLower[i]; |
1994 | } |
1995 | } |
1996 | delete [] realRows; |
1997 | return 0; |
1998 | } |
1999 | |
2000 | elements = rowCopy->getMutableElements(); |
2001 | column = rowCopy->getMutableIndices(); |
2002 | rowStart = rowCopy->getMutableVectorStarts(); |
2003 | rowLength = rowCopy->getMutableVectorLengths(); |
2004 | #if 0 |
2005 | int nFixed=0; |
2006 | for (i=0;i<nCols;i++) { |
2007 | if (colUpper[i]==colLower[i]) |
2008 | nFixed++; |
2009 | } |
2010 | printf("%d columns fixed\n",nFixed); |
2011 | #endif |
2012 | CoinBigIndex newSize=0; |
2013 | int * column2 = new int[nCols]; |
2014 | double * elements2 = new double[nCols]; |
2015 | rowStartPos = new CoinBigIndex [nRows]; |
2016 | for (i=0;i<nRows;i++) { |
| 23 | | Loop condition is false. Execution continues on line 2051 | |
|
2017 | double offset = 0.0; |
2018 | CoinBigIndex start = rowStart[i]; |
2019 | rowStart[i]=newSize; |
2020 | CoinBigIndex save=newSize; |
2021 | CoinBigIndex end = start + rowLength[i]; |
2022 | int nOther=0; |
2023 | for (CoinBigIndex j=start; j<end ; j++) { |
2024 | int iColumn = column[j]; |
2025 | if (colUpper[iColumn]>colLower[iColumn]) { |
2026 | double value = elements[j]; |
2027 | if (value<0.0) { |
2028 | elements[newSize]=value; |
2029 | column[newSize++]=iColumn; |
2030 | } else if (value>0.0) { |
2031 | elements2[nOther]=value; |
2032 | column2[nOther++]=iColumn; |
2033 | } |
2034 | } else { |
2035 | offset += colUpper[iColumn]*elements[j]; |
2036 | } |
2037 | } |
2038 | rowStartPos[i] = newSize; |
2039 | for (int k=0;k<nOther;k++) { |
2040 | elements[newSize]=elements2[k]; |
2041 | column[newSize++]=column2[k]; |
2042 | } |
2043 | rowLength[i]=newSize-save; |
2044 | if (offset) { |
2045 | if (rowLower[i]>-1.0e20) |
2046 | rowLower[i] -= offset; |
2047 | if (rowUpper[i]<1.0e20) |
2048 | rowUpper[i] -= offset; |
2049 | } |
2050 | } |
2051 | delete [] column2; |
2052 | delete [] elements2; |
2053 | rowStart[nRows]=newSize; |
2054 | rowCopy->setNumElements(newSize); |
2055 | } |
2056 | CoinPackedMatrix * columnCopy=new CoinPackedMatrix(*rowCopy,0,0,true); |
2057 | int nRowsSafe=CoinMin(nRows,si.getNumRows()); |
2058 | #ifdef CGL_DEBUG |
2059 | const OsiRowCutDebugger * debugger = si.getRowCutDebugger(); |
2060 | if (debugger&&!debugger->onOptimalPath(si)) |
2061 | debugger = NULL; |
2062 | #else |
2063 | const OsiRowCutDebugger * debugger = NULL; |
2064 | #endif |
2065 | |
2066 | const int * column = rowCopy->getIndices(); |
2067 | const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); |
2068 | const int * rowLength = rowCopy->getVectorLengths(); |
2069 | const double * rowElements = rowCopy->getElements(); |
2070 | |
2071 | if (!lookedAt_) { |
| 24 | | Assuming field 'lookedAt_' is non-null | |
|
| |
2072 | lookedAt_ = new int[nCols]; |
2073 | } |
2074 | numberThisTime_=0; |
2075 | |
2076 | |
2077 | int nRowsFake = info->inTree ? nRowsSafe/3 : nRowsSafe; |
| |
2078 | if (!info->inTree&&!info->pass) |
2079 | nRowsFake *= 5; |
2080 | row_cut rowCut(nRowsFake,!info->inTree); |
2081 | int * markR = new int [nRows]; |
2082 | double * minR = new double [nRows]; |
2083 | double * maxR = new double [nRows]; |
2084 | if (mode) { |
| |
| |
2085 | ninfeas= tighten(colLower, colUpper, column, rowElements, |
2086 | rowStart, rowStartPos ,rowLength, rowLower, rowUpper, |
2087 | nRows, nCols, intVar, 2, primalTolerance_); |
2088 | if (!feasible) |
2089 | ninfeas=1; |
2090 | if (!ninfeas) { |
2091 | |
2092 | { |
2093 | const double * lower = si.getColLower(); |
2094 | const double * upper = si.getColUpper(); |
2095 | const double * colsol = si.getColSolution(); |
2096 | int numberChanged=0,ifCut=0; |
2097 | CoinPackedVector lbs; |
2098 | CoinPackedVector ubs; |
2099 | for (i = 0; i < nCols; ++i) { |
2100 | if (intVar[i]) { |
2101 | colUpper[i] = CoinMin(upper[i],floor(colUpper[i]+1.0e-4)); |
2102 | if (colUpper[i]<upper[i]-1.0e-8) { |
2103 | if (colUpper[i]<colsol[i]-1.0e-8) |
2104 | ifCut=1; |
2105 | ubs.insert(i,colUpper[i]); |
2106 | numberChanged++; |
2107 | } |
2108 | colLower[i] = CoinMax(lower[i],ceil(colLower[i]-1.0e-4)); |
2109 | if (colLower[i]>lower[i]+1.0e-8) { |
2110 | if (colLower[i]>colsol[i]+1.0e-8) |
2111 | ifCut=1; |
2112 | lbs.insert(i,colLower[i]); |
2113 | numberChanged++; |
2114 | } |
2115 | } |
2116 | } |
2117 | if (numberChanged) { |
2118 | OsiColCut cc; |
2119 | cc.setUbs(ubs); |
2120 | cc.setLbs(lbs); |
2121 | if (ifCut) { |
2122 | cc.setEffectiveness(100.0); |
2123 | } else { |
2124 | cc.setEffectiveness(1.0e-5); |
2125 | } |
2126 | #ifdef CGL_DEBUG |
2127 | checkBounds(debugger,cc); |
2128 | #endif |
2129 | cs.insert(cc); |
2130 | } |
2131 | } |
2132 | if (maxProbe>0) { |
2133 | numberThisTime_=0; |
2134 | |
2135 | tighten2(colLower, colUpper, column, rowElements, |
2136 | rowStart, rowLength, rowLower, rowUpper, |
2137 | minR , maxR , markR, nRows); |
2138 | |
2139 | if (mode==1) { |
2140 | const double * colsol = si.getColSolution(); |
2141 | double_int_pair * array = new double_int_pair [nCols]; |
2142 | # ifdef ZEROFAULT |
2143 | std::memset(array,0,sizeof(double_int_pair)*nCols) ; |
2144 | # endif |
2145 | double multiplier = -1.0; |
2146 | if (info->inTree||(info->pass&1)!=0) |
2147 | multiplier=1.0; |
2148 | |
2149 | for (i=0;i<nCols;i++) { |
2150 | if (intVar[i]&&colUpper[i]-colLower[i]>1.0e-8) { |
2151 | double away = fabs(0.5-(colsol[i]-floor(colsol[i]))); |
2152 | if (away<0.49999||!info->inTree) { |
2153 | |
2154 | array[numberThisTime_].infeasibility=away*multiplier; |
2155 | |
2156 | array[numberThisTime_++].sequence=i; |
2157 | } |
2158 | } |
2159 | } |
2160 | |
2161 | std::sort(array,array+numberThisTime_,double_int_pair_compare()); |
2162 | |
2163 | for (i=0;i<numberThisTime_;i++) { |
2164 | lookedAt_[i]=array[i].sequence; |
2165 | } |
2166 | delete [] array; |
2167 | } else { |
2168 | for (i=0;i<nCols;i++) { |
2169 | if (intVar[i]&&colUpper[i]-colLower[i]>1.0e-8) { |
2170 | lookedAt_[numberThisTime_++]=i; |
2171 | } |
2172 | } |
2173 | } |
2174 | #if 0 |
2175 | |
2176 | for (i=0;i<nRows;i++) { |
2177 | if (rowLength[i]>maxElements) |
2178 | abort(); |
2179 | } |
2180 | #endif |
2181 | |
2182 | |
2183 | if (!numberCliques_) { |
2184 | ninfeas= probe(si, debugger, cs, colLower, colUpper, rowCopy,columnCopy, |
2185 | rowStartPos, realRows, rowLower, rowUpper, |
2186 | intVar, minR, maxR, markR, |
2187 | info); |
2188 | } else { |
2189 | ninfeas= probeCliques(si, debugger, cs, colLower, colUpper, rowCopy,columnCopy, |
2190 | realRows,rowLower, rowUpper, |
2191 | intVar, minR, maxR, markR, |
2192 | info); |
2193 | } |
2194 | } |
2195 | } |
2196 | } else if (maxProbe>0) { |
| 29 | | Assuming 'maxProbe' is > 0 | |
|
| |
2197 | |
2198 | |
2199 | assert(numberIntegers==numberIntegers_); |
2200 | |
2201 | numberThisTime_=0; |
2202 | const double * colsol = si.getColSolution(); |
2203 | double_int_pair * array = new double_int_pair [nCols]; |
2204 | # ifdef ZEROFAULT |
2205 | std::memset(array,0,sizeof(double_int_pair)*nCols) ; |
2206 | # endif |
2207 | for (i=0;i<number01Integers_;i++) { |
| 31 | | Assuming 'i' is >= field 'number01Integers_' | |
|
| 32 | | Loop condition is false. Execution continues on line 2215 | |
|
2208 | int j=cutVector_[i].sequence; |
2209 | if (!cutVector_[i].index&&colUpper[j]-colLower[j]>1.0e-8) { |
2210 | double away = fabs(0.5-(colsol[j]-floor(colsol[j]))); |
2211 | array[numberThisTime_].infeasibility=away; |
2212 | array[numberThisTime_++].sequence=i; |
2213 | } |
2214 | } |
2215 | std::sort(array,array+numberThisTime_,double_int_pair_compare()); |
2216 | numberThisTime_=CoinMin(numberThisTime_,maxProbe); |
2217 | for (i=0;i<numberThisTime_;i++) { |
| 33 | | Loop condition is false. Execution continues on line 2222 | |
|
2218 | lookedAt_[i]=array[i].sequence; |
2219 | } |
2220 | |
2221 | |
2222 | delete [] array; |
2223 | |
2224 | tighten2(colLower, colUpper, column, rowElements, |
2225 | rowStart, rowLength, rowLower, rowUpper, |
2226 | minR , maxR , markR, nRows); |
2227 | OsiCuts csNew; |
2228 | |
2229 | if (rowCuts_) { |
| 34 | | Assuming field 'rowCuts_' is not equal to 0 | |
|
| |
2230 | #if 0 |
2231 | |
2232 | for (i=0;i<nRows;i++) { |
2233 | if (rowLength[i]>maxElements) |
2234 | abort(); |
2235 | } |
2236 | #endif |
2237 | ninfeas= probeCliques(si, debugger, csNew, colLower, colUpper, rowCopy,columnCopy, |
2238 | realRows, rowLower, rowUpper, |
2239 | intVar, minR, maxR, markR, |
2240 | info); |
2241 | } |
2242 | if (!ninfeas) { |
| 36 | | Assuming 'ninfeas' is 0 | |
|
| |
2243 | |
2244 | int nCuts = csNew.sizeRowCuts(); |
2245 | int iCut; |
2246 | |
2247 | |
2248 | int * backward = new int [2*nCols]; |
2249 | int * onList = backward + nCols; |
2250 | for (i=0;i<nCols;i++) { |
| 38 | | Loop condition is false. Execution continues on line 2254 | |
|
2251 | backward[i]=-1; |
2252 | onList[i]=0; |
2253 | } |
2254 | for (i=0;i<number01Integers_;i++) { |
| 39 | | Assuming 'i' is < field 'number01Integers_' | |
|
| 40 | | Loop condition is true. Entering loop body | |
|
| 41 | | Assuming 'i' is >= field 'number01Integers_' | |
|
| 42 | | Loop condition is false. Execution continues on line 2261 | |
|
2255 | int j=cutVector_[i].sequence; |
2256 | backward[j]=i; |
2257 | onList[j]=1; |
2258 | } |
2259 | |
2260 | |
2261 | for (iCut=0;iCut<nCuts;iCut++) { |
| 43 | | Assuming 'iCut' is >= 'nCuts' | |
|
| 44 | | Loop condition is false. Execution continues on line 2353 | |
|
2262 | OsiRowCut rcut; |
2263 | CoinPackedVector rpv; |
2264 | rcut = csNew.rowCut(iCut); |
2265 | rpv = rcut.row(); |
2266 | assert(rpv.getNumElements()==2); |
2267 | const int * indices = rpv.getIndices(); |
2268 | double* elements = rpv.getElements(); |
2269 | double lb=rcut.lb(); |
2270 | |
2271 | int which=0; |
2272 | i=backward[indices[0]]; |
2273 | if (i<0||!onList[indices[0]]) { |
2274 | which=1; |
2275 | i=backward[indices[1]]; |
2276 | |
2277 | if (!onList[indices[which]]) |
2278 | continue; |
2279 | } |
2280 | int other = indices[1-which]; |
2281 | if (lb==-COIN_DBL_MAX) { |
2282 | if (!rcut.ub()) { |
2283 | |
2284 | if (elements[which]<0.0) { |
2285 | |
2286 | |
2287 | cutVector_[i].length++; |
2288 | } else { |
2289 | if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]- |
2290 | colUpper[other])<1.0e-5) { |
2291 | |
2292 | cutVector_[i].length++; |
2293 | } else { |
2294 | if (onList[other]) { |
2295 | double value0 = elements[0]; |
2296 | double value1 = elements[1]; |
2297 | if (value0*value1==-1.0) { |
2298 | |
2299 | int j=backward[other]; |
2300 | cutVector_[i].length++; |
2301 | cutVector_[j].length++; |
2302 | } else { |
2303 | continue; |
2304 | } |
2305 | } |
2306 | } |
2307 | } |
2308 | } else { |
2309 | if (onList[other]) { |
2310 | if (elements[0]==1.0&&elements[1]==1.0&&rcut.ub()==1.0) { |
2311 | |
2312 | int j=backward[other]; |
2313 | cutVector_[i].length++; |
2314 | cutVector_[j].length++; |
2315 | } else { |
2316 | continue; |
2317 | } |
2318 | } |
2319 | } |
2320 | } else { |
2321 | assert(rcut.ub()==DBL_MAX); |
2322 | if (!lb) { |
2323 | |
2324 | if (elements[which]>0.0) { |
2325 | |
2326 | |
2327 | |
2328 | cutVector_[i].length++; |
2329 | } else { |
2330 | if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]- |
2331 | colUpper[other])<1.0e-5) { |
2332 | |
2333 | cutVector_[i].length++; |
2334 | } else { |
2335 | if (onList[other]) { |
2336 | double value0 = elements[0]; |
2337 | double value1 = elements[1]; |
2338 | if (value0*value1==-1.0) { |
2339 | |
2340 | int j=backward[other]; |
2341 | cutVector_[i].length++; |
2342 | cutVector_[j].length++; |
2343 | } else { |
2344 | continue; |
2345 | } |
2346 | } |
2347 | } |
2348 | } |
2349 | } |
2350 | } |
2351 | } |
2352 | |
2353 | for (i=0;i<number01Integers_;i++) { |
| 45 | | Loop condition is true. Entering loop body | |
|
| 47 | | Loop condition is false. Execution continues on line 2362 | |
|
2354 | int j=cutVector_[i].sequence; |
2355 | if (onList[j]&&!cutVector_[i].index) { |
| 46 | | Assuming the condition is false | |
|
2356 | disaggregation thisOne=cutVector_[i]; |
2357 | cutVector_[i].index=new disaggregationAction [thisOne.length]; |
2358 | cutVector_[i].length=0; |
2359 | } |
2360 | } |
2361 | |
2362 | for (iCut=0;iCut<nCuts;iCut++) { |
| 48 | | Loop condition is false. Execution continues on line 2532 | |
|
2363 | OsiRowCut rcut; |
2364 | CoinPackedVector rpv; |
2365 | int iput; |
2366 | rcut = csNew.rowCut(iCut); |
2367 | rpv = rcut.row(); |
2368 | assert(rpv.getNumElements()==2); |
2369 | const int * indices = rpv.getIndices(); |
2370 | double* elements = rpv.getElements(); |
2371 | double lb=rcut.lb(); |
2372 | |
2373 | |
2374 | int which=0; |
2375 | i=backward[indices[0]]; |
2376 | if (i<0||!onList[indices[0]]) { |
2377 | which=1; |
2378 | i=backward[indices[1]]; |
2379 | |
2380 | if (!onList[indices[which]]) |
2381 | continue; |
2382 | } |
2383 | int other = indices[1-which]; |
2384 | int j = other ? backward[other] : -1; |
2385 | if (lb==-COIN_DBL_MAX) { |
2386 | if (!rcut.ub()) { |
2387 | |
2388 | if (elements[which]<0.0) { |
2389 | iput=cutVector_[i].length; |
2390 | if (j>=0) |
2391 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2392 | else |
2393 | setAffectedInDisaggregation(cutVector_[i].index[iput],other); |
2394 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],false); |
2395 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],false); |
2396 | setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0); |
2397 | cutVector_[i].length++; |
2398 | } else { |
2399 | if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]- |
2400 | colUpper[other])<1.0e-5) { |
2401 | |
2402 | iput=cutVector_[i].length; |
2403 | if (j>=0) |
2404 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2405 | else |
2406 | setAffectedInDisaggregation(cutVector_[i].index[iput],other); |
2407 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true); |
2408 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true); |
2409 | setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0); |
2410 | cutVector_[i].length++; |
2411 | } else { |
2412 | if (onList[other]) { |
2413 | double value0 = elements[0]; |
2414 | double value1 = elements[1]; |
2415 | if (value0*value1==-1.0) { |
2416 | |
2417 | int j=backward[other]; |
2418 | assert (j>=0); |
2419 | |
2420 | if (value1==1.0) { |
2421 | j=i; |
2422 | i=backward[other]; |
2423 | value1=value0; |
2424 | value0=1.0; |
2425 | } |
2426 | assert (value0==1.0); |
2427 | assert (value1==-1.0); |
2428 | iput=cutVector_[i].length; |
2429 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2430 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true); |
2431 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true); |
2432 | setZeroOneInDisaggregation(cutVector_[i].index[iput],true); |
2433 | cutVector_[i].length++; |
2434 | iput=cutVector_[j].length; |
2435 | setAffectedInDisaggregation(cutVector_[j].index[iput],i); |
2436 | setWhenAtUBInDisaggregation(cutVector_[j].index[iput],false); |
2437 | setAffectedToUBInDisaggregation(cutVector_[j].index[iput],false); |
2438 | setZeroOneInDisaggregation(cutVector_[j].index[iput],true); |
2439 | cutVector_[j].length++; |
2440 | } |
2441 | } |
2442 | } |
2443 | } |
2444 | } else { |
2445 | if (onList[other]) { |
2446 | if (elements[0]==1.0&&elements[1]==1.0&&rcut.ub()==1.0) { |
2447 | |
2448 | int j=backward[other]; |
2449 | assert (j>=0); |
2450 | iput=cutVector_[i].length; |
2451 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2452 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true); |
2453 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],false); |
2454 | setZeroOneInDisaggregation(cutVector_[i].index[iput],true); |
2455 | cutVector_[i].length++; |
2456 | iput=cutVector_[j].length; |
2457 | setAffectedInDisaggregation(cutVector_[j].index[iput],i); |
2458 | setWhenAtUBInDisaggregation(cutVector_[j].index[iput],true); |
2459 | setAffectedToUBInDisaggregation(cutVector_[j].index[iput],false); |
2460 | setZeroOneInDisaggregation(cutVector_[j].index[iput],true); |
2461 | cutVector_[j].length++; |
2462 | } else { |
2463 | #ifdef COIN_DEVELOP |
2464 | abort(); |
2465 | #endif |
2466 | continue; |
2467 | } |
2468 | } |
2469 | } |
2470 | } else { |
2471 | assert(rcut.ub()==DBL_MAX); |
2472 | if (!lb) { |
2473 | |
2474 | if (elements[which]>0.0) { |
2475 | iput=cutVector_[i].length; |
2476 | if (j>=0) |
2477 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2478 | else |
2479 | setAffectedInDisaggregation(cutVector_[i].index[iput],other); |
2480 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],false); |
2481 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],false); |
2482 | setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0); |
2483 | cutVector_[i].length++; |
2484 | } else { |
2485 | if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]- |
2486 | colUpper[other])<1.0e-5) { |
2487 | iput=cutVector_[i].length; |
2488 | if (j>=0) |
2489 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2490 | else |
2491 | setAffectedInDisaggregation(cutVector_[i].index[iput],other); |
2492 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true); |
2493 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true); |
2494 | setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0); |
2495 | cutVector_[i].length++; |
2496 | } else { |
2497 | if (onList[other]) { |
2498 | double value0 = elements[0]; |
2499 | double value1 = elements[1]; |
2500 | if (value0*value1==-1.0) { |
2501 | |
2502 | int j=backward[other]; |
2503 | assert (j>=0); |
2504 | |
2505 | if (value1==-1.0) { |
2506 | j=i; |
2507 | i=backward[other]; |
2508 | value1=value0; |
2509 | value0=-1.0; |
2510 | } |
2511 | assert (value0==-1.0); |
2512 | assert (value1==1.0); |
2513 | iput=cutVector_[i].length; |
2514 | setAffectedInDisaggregation(cutVector_[i].index[iput],j); |
2515 | setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true); |
2516 | setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true); |
2517 | setZeroOneInDisaggregation(cutVector_[i].index[iput],true); |
2518 | cutVector_[i].length++; |
2519 | iput=cutVector_[j].length; |
2520 | setAffectedInDisaggregation(cutVector_[j].index[iput],i); |
2521 | setWhenAtUBInDisaggregation(cutVector_[j].index[iput],false); |
2522 | setAffectedToUBInDisaggregation(cutVector_[j].index[iput],false); |
2523 | setZeroOneInDisaggregation(cutVector_[j].index[iput],true); |
2524 | cutVector_[j].length++; |
2525 | } |
2526 | } |
2527 | } |
2528 | } |
2529 | } |
2530 | } |
2531 | } |
2532 | delete [] backward; |
2533 | |
2534 | |
2535 | int longest=0; |
2536 | for (i=0;i<number01Integers_;i++) |
| 49 | | Loop condition is true. Entering loop body | |
|
| 50 | | Loop condition is false. Execution continues on line 2538 | |
|
2537 | longest = CoinMax(longest, cutVector_[i].length); |
2538 | unsigned int * sortit = new unsigned int[longest]; |
| |
2539 | for (i=0;i<number01Integers_;i++) { |
| 52 | | Loop condition is true. Entering loop body | |
|
2540 | disaggregation & thisOne=cutVector_[i]; |
2541 | int k; |
2542 | int number = thisOne.length; |
2543 | for (k=0;k<number;k++) { |
| 53 | | Loop condition is false. Execution continues on line 2550 | |
|
2544 | int affected = affectedInDisaggregation(thisOne.index[k]); |
2545 | int zeroOne = zeroOneInDisaggregation(thisOne.index[k]) ? 1 : 0; |
2546 | int whenAtUB = whenAtUBInDisaggregation(thisOne.index[k]) ? 1 : 0; |
2547 | int affectedToUB = affectedToUBInDisaggregation(thisOne.index[k]) ? 1: 0; |
2548 | sortit[k]=(affected<<3)|(zeroOne<<2)|(whenAtUB<<1)|affectedToUB; |
2549 | } |
2550 | std::sort(sortit,sortit+number); |
| 54 | | Calling 'sort<unsigned int *>' | |
|
2551 | int affectedLast = 0xffffffff; |
2552 | int zeroOneLast = 0; |
2553 | int whenAtUBLast = 0; |
2554 | int affectedToUBLast = 0; |
2555 | int put=0; |
2556 | for (k=0;k<number;k++) { |
2557 | int affected = sortit[k]>>3; |
2558 | int zeroOne = (sortit[k]&4)>>2; |
2559 | int whenAtUB = (sortit[k]&2)>>1; |
2560 | int affectedToUB = sortit[k]&1; |
2561 | disaggregationAction action; |
2562 | action.affected=0; |
2563 | setAffectedInDisaggregation(action,affected); |
2564 | setZeroOneInDisaggregation(action,zeroOne!=0); |
2565 | setWhenAtUBInDisaggregation(action,whenAtUB!=0); |
2566 | setAffectedToUBInDisaggregation(action,affectedToUB!=0); |
2567 | if (affected!=affectedLast||zeroOne!=zeroOneLast) { |
2568 | |
2569 | thisOne.index[put++]=action; |
2570 | } else if (whenAtUB!=whenAtUBLast||affectedToUB!=affectedToUBLast) { |
2571 | |
2572 | thisOne.index[put++]=action; |
2573 | int j=cutVector_[i].sequence; |
2574 | int k=affected; |
2575 | if (zeroOne) { |
2576 | k=cutVector_[k].sequence; |
2577 | if (logLevel_>1) |
2578 | printf("For %d %d 0-1 pair",j,k) ; |
2579 | } else { |
2580 | if (logLevel_>1) |
2581 | printf("For %d %d pair",j,k) ; |
2582 | } |
2583 | if (logLevel_>1) |
2584 | printf(" old whenAtUB, affectedToUB %d %d, new whenAtUB, affectedToUB %d %d\n", |
2585 | whenAtUBLast, affectedToUBLast,whenAtUB, affectedToUB); |
2586 | } |
2587 | affectedLast=affected; |
2588 | zeroOneLast=zeroOne; |
2589 | whenAtUBLast=whenAtUB; |
2590 | affectedToUBLast=affectedToUB; |
2591 | } |
2592 | if (put<number) { |
2593 | |
2594 | thisOne.length=put; |
2595 | } |
2596 | } |
2597 | |
2598 | for (i=0;i<number01Integers_;i++) { |
2599 | disaggregation & thisOne=cutVector_[i]; |
2600 | int k; |
2601 | int number = thisOne.length; |
2602 | for (k=0;k<number;k++) { |
2603 | int affected = affectedInDisaggregation(thisOne.index[k]); |
2604 | bool zeroOne = zeroOneInDisaggregation(thisOne.index[k]); |
2605 | if (zeroOne&&static_cast<int>(affected)>i) { |
2606 | bool whenAtUB = whenAtUBInDisaggregation(thisOne.index[k]); |
2607 | bool affectedToUB = affectedToUBInDisaggregation(thisOne.index[k]); |
2608 | disaggregation otherOne=cutVector_[affected]; |
2609 | int numberOther = otherOne.length; |
2610 | |
2611 | int lastAction=-1; |
2612 | for (int j=0;j<numberOther;j++) { |
2613 | if (affectedInDisaggregation(otherOne.index[j])==i) { |
2614 | bool whenAtUBOther = whenAtUBInDisaggregation(otherOne.index[j]); |
2615 | bool affectedToUBOther = affectedToUBInDisaggregation(otherOne.index[j]); |
2616 | |
2617 | |
2618 | |
2619 | |
2620 | |
2621 | |
2622 | |
2623 | |
2624 | |
2625 | |
2626 | |
2627 | |
2628 | int action=-1; |
2629 | if (whenAtUB) { |
2630 | if (affectedToUB) { |
2631 | |
2632 | if (whenAtUBOther) { |
2633 | if (affectedToUBOther) { |
2634 | |
2635 | action=10; |
2636 | } else { |
2637 | |
2638 | action=20; |
2639 | } |
2640 | } else { |
2641 | if (affectedToUBOther) { |
2642 | |
2643 | action=23; |
2644 | } else { |
2645 | |
2646 | action=1; |
2647 | } |
2648 | } |
2649 | } else { |
2650 | |
2651 | if (whenAtUBOther) { |
2652 | if (affectedToUBOther) { |
2653 | |
2654 | action=22; |
2655 | } else { |
2656 | |
2657 | action=0; |
2658 | } |
2659 | } else { |
2660 | if (affectedToUBOther) { |
2661 | |
2662 | action=11; |
2663 | } else { |
2664 | |
2665 | action=20; |
2666 | } |
2667 | } |
2668 | } |
2669 | } else { |
2670 | if (affectedToUB) { |
2671 | |
2672 | if (whenAtUBOther) { |
2673 | if (affectedToUBOther) { |
2674 | |
2675 | action=21; |
2676 | } else { |
2677 | |
2678 | action=11; |
2679 | } |
2680 | } else { |
2681 | if (affectedToUBOther) { |
2682 | |
2683 | action=3; |
2684 | } else { |
2685 | |
2686 | action=23; |
2687 | } |
2688 | } |
2689 | } else { |
2690 | |
2691 | if (whenAtUBOther) { |
2692 | if (affectedToUBOther) { |
2693 | |
2694 | action=2; |
2695 | } else { |
2696 | |
2697 | action=22; |
2698 | } |
2699 | } else { |
2700 | if (affectedToUBOther) { |
2701 | |
2702 | action=21; |
2703 | } else { |
2704 | |
2705 | action=10; |
2706 | } |
2707 | } |
2708 | } |
2709 | } |
2710 | assert (action>=0); |
2711 | if (action<4) { |
2712 | |
2713 | if (oneFixStart_) { |
2714 | switch (action) { |
2715 | case 0: |
2716 | break; |
2717 | case 1: |
2718 | break; |
2719 | case 2: |
2720 | break; |
2721 | case 3: |
2722 | break; |
2723 | } |
2724 | |
2725 | } |
2726 | |
2727 | if (lastAction>=0) { |
2728 | if (logLevel_>1) |
2729 | printf("XX lastAction %d, this %d\n",lastAction,action); |
2730 | } |
2731 | } else if (action<12) { |
2732 | if (logLevel_>1) |
2733 | printf("XX Could eliminate one of %d %d 0-1 variables %c\n",i,affected, |
2734 | (lastAction>=0) ? '*' : ' '); |
2735 | if (info->strengthenRow) { |
2736 | OsiRowCut rc; |
2737 | int index[2]; |
2738 | double element[2]; |
2739 | index[0]=cutVector_[i].sequence; |
2740 | element[0]=1.0; |
2741 | index[1]=cutVector_[affected].sequence; |
2742 | if (action==10) { |
2743 | |
2744 | rc.setLb(0.0); |
2745 | rc.setUb(0.0); |
2746 | element[1]= -1.0; |
2747 | } else { |
2748 | |
2749 | rc.setLb(1.0); |
2750 | rc.setUb(1.0); |
2751 | element[1]= 1.0; |
2752 | } |
2753 | rc.setRow(2,index,element,false); |
2754 | cs.insert(rc); |
2755 | } |
2756 | } else { |
2757 | if (action<22) { |
2758 | if (logLevel_>1) |
2759 | printf("XX Could fix a 0-1 variable %d\n",i); |
2760 | } else { |
2761 | if (logLevel_>1) |
2762 | printf("XX Could fix a 0-1 variable %d\n",affected); |
2763 | } |
2764 | } |
2765 | |
2766 | |
2767 | |
2768 | } |
2769 | } |
2770 | } |
2771 | } |
2772 | } |
2773 | delete [] sortit; |
2774 | } |
2775 | if (cutVector_) { |
2776 | |
2777 | for (i=0;i<number01Integers_;i++) { |
2778 | int j=cutVector_[i].sequence; |
2779 | double solInt=colsol[j]; |
2780 | double upper, solValue; |
2781 | int icol; |
2782 | int index[2]; |
2783 | double element[2]; |
2784 | if (colUpper[j]-colLower[j]>1.0e-8) { |
2785 | double away = fabs(0.5-(solInt-floor(solInt))); |
2786 | if (away<0.4999999) { |
2787 | disaggregation thisOne=cutVector_[i]; |
2788 | int k; |
2789 | OsiRowCut rc; |
2790 | for (k=0;k<thisOne.length;k++) { |
2791 | icol = affectedInDisaggregation(thisOne.index[k]); |
2792 | if (zeroOneInDisaggregation(thisOne.index[k])) |
2793 | icol = cutVector_[icol].sequence; |
2794 | solValue=colsol[icol]; |
2795 | upper=colUpper_[icol]; |
2796 | double infeasibility=0.0; |
2797 | if (!whenAtUBInDisaggregation(thisOne.index[k])) { |
2798 | if (!affectedToUBInDisaggregation(thisOne.index[k])) { |
2799 | |
2800 | infeasibility = solValue - upper * solInt; |
2801 | if (infeasibility > 1.0e-3) { |
2802 | rc.setLb(-COIN_DBL_MAX); |
2803 | rc.setUb(0.0); |
2804 | index[0]=icol; |
2805 | element[0]=1.0; |
2806 | index[1]=j; |
2807 | element[1]= -upper; |
2808 | } else { |
2809 | infeasibility=0.0; |
2810 | } |
2811 | } else { |
2812 | |
2813 | abort(); |
2814 | } |
2815 | } else { |
2816 | if (affectedToUBInDisaggregation(thisOne.index[k])) { |
2817 | |
2818 | icol = affectedInDisaggregation(thisOne.index[k]); |
2819 | if (zeroOneInDisaggregation(thisOne.index[k])) |
2820 | icol = cutVector_[icol].sequence; |
2821 | solValue=colsol[icol]; |
2822 | upper=colUpper_[icol]; |
2823 | if (!colLower[icol]) { |
2824 | infeasibility = upper * solInt - solValue; |
2825 | if (infeasibility > 1.0e-3) { |
2826 | rc.setLb(-COIN_DBL_MAX); |
2827 | rc.setUb(0.0); |
2828 | index[0]=icol; |
2829 | element[0]=-1.0; |
2830 | index[1]=j; |
2831 | element[1]= upper; |
2832 | } else { |
2833 | infeasibility=0.0; |
2834 | } |
2835 | } else { |
2836 | assert (upper==colLower[icol]); |
2837 | infeasibility=0.0; |
2838 | } |
2839 | } else { |
2840 | |
2841 | assert (zeroOneInDisaggregation(thisOne.index[k])); |
2842 | |
2843 | icol = affectedInDisaggregation(thisOne.index[k]); |
2844 | icol = cutVector_[icol].sequence; |
2845 | |
2846 | if (icol >j && colUpper[icol] ) { |
2847 | solValue=colsol[icol]; |
2848 | if (!colLower[icol]) { |
2849 | infeasibility = solInt + solValue - 1.0; |
2850 | if (infeasibility > 1.0e-3) { |
2851 | rc.setLb(-COIN_DBL_MAX); |
2852 | rc.setUb(1.0); |
2853 | index[0]=icol; |
2854 | element[0]=1.0; |
2855 | index[1]=j; |
2856 | element[1]= 1.0; |
2857 | } else { |
2858 | infeasibility=0.0; |
2859 | } |
2860 | } else { |
2861 | assert (upper==colLower[icol]); |
2862 | infeasibility=0.0; |
2863 | } |
2864 | } |
2865 | } |
2866 | } |
2867 | if (infeasibility) { |
2868 | rc.setEffectiveness(infeasibility); |
2869 | rc.setRow(2,index,element,false); |
2870 | if (logLevel_>1) |
2871 | printf("%g <= %g * x%d + %g * x%d <= %g\n", |
2872 | rc.lb(),element[0],index[0],element[1],index[1],rc.ub()); |
2873 | #ifdef CGL_DEBUG |
2874 | if (debugger) assert(!debugger->invalidCut(rc)); |
2875 | #endif |
2876 | rowCut.addCutIfNotDuplicate(rc); |
2877 | } |
2878 | } |
2879 | } |
2880 | } |
2881 | } |
2882 | } |
2883 | } |
2884 | delete [] markR; |
2885 | delete [] minR; |
2886 | delete [] maxR; |
2887 | |
2888 | if (!ninfeas) { |
2889 | rowCut.addCuts(cs,info->strengthenRow,0); |
2890 | } |
2891 | |
2892 | delete rowCopy; |
2893 | delete columnCopy; |
2894 | if (rowCopy_) { |
2895 | delete [] rowLower; |
2896 | delete [] rowUpper; |
2897 | } |
2898 | delete [] intVar; |
2899 | delete [] rowStartPos; |
2900 | delete [] realRows; |
2901 | |
2902 | const double * trueLower = si.getColLower(); |
2903 | const double * trueUpper = si.getColUpper(); |
2904 | if (!ninfeas) { |
2905 | for (i=0;i<nCols;i++) { |
2906 | if (intVarOriginal[i]==2) { |
2907 | if (colUpper[i] == CGL_REASONABLE_INTEGER_BOUND) |
2908 | colUpper[i] = trueUpper[i]; |
2909 | if (colLower[i] == -CGL_REASONABLE_INTEGER_BOUND) |
2910 | colLower[i] = trueLower[i]; |
2911 | } |
2912 | } |
2913 | } else { |
2914 | memcpy(colLower,trueLower,nCols*sizeof(double)); |
2915 | memcpy(colUpper,trueUpper,nCols*sizeof(double)); |
2916 | } |
2917 | if (!info->inTree&&((info->options&4)==4||((info->options&8)&&!info->pass))) { |
2918 | int numberRowCutsAfter = cs.sizeRowCuts(); |
2919 | for (int i=numberRowCutsBefore;i<numberRowCutsAfter;i++) |
2920 | cs.rowCutPtr(i)->setGloballyValid(); |
2921 | } |
2922 | return ninfeas; |
2923 | } |
2924 | |
2925 | int CglProbing::probe( const OsiSolverInterface & si, |
2926 | const OsiRowCutDebugger * |
2927 | #ifdef CGL_DEBUG |
2928 | debugger |
2929 | #endif |
2930 | ,OsiCuts & cs, |
2931 | double * colLower, double * colUpper, |
2932 | CoinPackedMatrix *rowCopy, |
2933 | CoinPackedMatrix *columnCopy, |
2934 | const CoinBigIndex * rowStartPos,const int * realRows, |
2935 | const double * rowLower, const double * rowUpper, |
2936 | const char * intVar, double * minR, double * maxR, |
2937 | int * markR, |
2938 | CglTreeInfo * info) |
2939 | { |
2940 | int nRows=rowCopy->getNumRows(); |
2941 | int nRowsSafe=CoinMin(nRows,si.getNumRows()); |
2942 | int nCols=rowCopy->getNumCols(); |
2943 | const double * currentColLower = si.getColLower(); |
2944 | const double * currentColUpper = si.getColUpper(); |
2945 | |
2946 | int maxStack = info->inTree ? maxStack_ : maxStackRoot_; |
2947 | int maxPass = info->inTree ? maxPass_ : maxPassRoot_; |
2948 | if ((totalTimesCalled_%10)==-1) { |
2949 | int newMax=CoinMin(2*maxStack,50); |
2950 | maxStack=CoinMax(newMax,maxStack); |
2951 | } |
2952 | #define ONE_ARRAY |
2953 | #ifdef ONE_ARRAY |
2954 | unsigned int DIratio = sizeof(double)/sizeof(int); |
2955 | assert (DIratio==1||DIratio==2); |
2956 | int nSpace = 8*nCols+4*nRows+2*maxStack; |
2957 | nSpace += (4*nCols+nRows+maxStack+DIratio-1)>>(DIratio-1); |
2958 | double * colsol = new double[nSpace]; |
2959 | double * djs = colsol + nCols; |
2960 | double * columnGap = djs + nCols; |
2961 | double * saveL = columnGap + nCols; |
2962 | double * saveU = saveL + 2*nCols; |
2963 | double * saveMin = saveU + 2*nCols; |
2964 | double * saveMax = saveMin + nRows; |
2965 | double * largestPositiveInRow = saveMax + nRows; |
2966 | double * largestNegativeInRow = largestPositiveInRow + nRows; |
2967 | double * element = largestNegativeInRow + nRows; |
2968 | double * lo0 = element + nCols; |
2969 | double * up0 = lo0 + maxStack; |
2970 | int * markC = reinterpret_cast<int *> (up0+maxStack); |
2971 | int * stackC = markC + nCols; |
2972 | int * stackR = stackC + 2*nCols; |
2973 | int * index = stackR + nRows; |
2974 | int * stackC0 = index + nCols; |
2975 | #else |
2976 | double * colsol = new double[nCols]; |
2977 | double * djs = new double[nCols]; |
2978 | double * columnGap = new double [nCols]; |
2979 | double * saveL = new double [2*nCols]; |
2980 | double * saveU = new double [2*nCols]; |
2981 | double * saveMin = new double [nRows]; |
2982 | double * saveMax = new double [nRows]; |
2983 | double * largestPositiveInRow = new double [nRows]; |
2984 | double * largestNegativeInRow = new double [nRows]; |
2985 | double * element = new double[nCols]; |
2986 | double * lo0 = new double[maxStack]; |
2987 | double * up0 = new double[maxStack]; |
2988 | int * markC = new int [nCols]; |
2989 | int * stackC = new int [2*nCols]; |
2990 | int * stackR = new int [nRows]; |
2991 | int * index = new int[nCols]; |
2992 | int * stackC0 = new int[maxStack]; |
2993 | #endif |
2994 | |
2995 | |
2996 | #define PROBING4 |
2997 | #ifdef PROBING4 |
2998 | int nRowsFake = info->inTree ? nRowsSafe/3 : nRowsSafe*10; |
2999 | #else |
3000 | int nRowsFake = info->inTree ? nRowsSafe/3 : nRowsSafe; |
3001 | #endif |
3002 | if (!info->inTree&&!info->pass) |
3003 | nRowsFake *= 10; |
3004 | bool justReplace = ((info->options&64)!=0)&&(realRows!=NULL); |
3005 | if (justReplace) { |
3006 | nRowsFake=nRows; |
3007 | } |
3008 | row_cut rowCut(nRowsFake, !info->inTree); |
3009 | totalTimesCalled_++; |
3010 | const int * column = rowCopy->getIndices(); |
3011 | const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); |
3012 | const double * rowElements = rowCopy->getElements(); |
3013 | const int * row = columnCopy->getIndices(); |
3014 | const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); |
3015 | const int * columnLength = columnCopy->getVectorLengths(); |
3016 | const double * columnElements = columnCopy->getElements(); |
3017 | #define MOVE_SINGLETONS |
3018 | #ifdef MOVE_SINGLETONS |
3019 | const double * objective = si.getObjCoefficients(); |
3020 | const int * columnLength2 = si.getMatrixByCol()->getVectorLengths(); |
3021 | #endif |
3022 | bool anyColumnCuts=false; |
3023 | int ninfeas=0; |
3024 | int rowCuts; |
3025 | double disaggEffectiveness; |
3026 | |
3027 | CoinMemcpyN(si.getReducedCost(),nCols,djs); |
3028 | CoinMemcpyN( si.getColSolution(),nCols,colsol); |
3029 | disaggEffectiveness=1.0e-3; |
3030 | rowCuts=rowCuts_; |
3031 | |
3032 | #ifndef NDEBUG |
3033 | const int * rowLength = rowCopy->getVectorLengths(); |
3034 | #endif |
3035 | for (int i=0;i<nRows;i++) { |
3036 | assert (rowStart[i]+rowLength[i]==rowStart[i+1]); |
3037 | int kk; |
3038 | #ifndef NDEBUG |
3039 | for ( kk =rowStart[i];kk<rowStart[i+1];kk++) { |
3040 | double value = rowElements[kk]; |
3041 | if (value>0.0) |
3042 | break; |
3043 | } |
3044 | assert (rowStartPos[i]==kk); |
3045 | #endif |
3046 | double value; |
3047 | value=0.0; |
3048 | for ( kk =rowStart[i];kk<rowStartPos[i];kk++) { |
3049 | int iColumn = column[kk]; |
3050 | double gap = CoinMin(1.0e100,colUpper[iColumn]-colLower[iColumn]); |
3051 | value = CoinMin(value,gap*rowElements[kk]); |
3052 | } |
3053 | largestNegativeInRow[i]=value; |
3054 | value=0.0; |
3055 | for ( ;kk<rowStart[i+1];kk++) { |
3056 | int iColumn = column[kk]; |
3057 | double gap = CoinMin(1.0e100,colUpper[iColumn]-colLower[iColumn]); |
3058 | value = CoinMax(value,gap*rowElements[kk]); |
3059 | } |
3060 | largestPositiveInRow[i]=value; |
3061 | } |
3062 | double direction = si.getObjSense(); |
3063 | for (int i = 0; i < nCols; ++i) { |
3064 | double djValue = djs[i]*direction; |
3065 | double gap=colUpper[i]-colLower[i]; |
3066 | if (gap>1.0e-8) { |
3067 | if (colsol[i]<colLower[i]+primalTolerance_) { |
3068 | colsol[i]=colLower[i]; |
3069 | djs[i] = CoinMax(0.0,djValue); |
3070 | } else if (colsol[i]>colUpper[i]-primalTolerance_) { |
3071 | colsol[i]=colUpper[i]; |
3072 | djs[i] = CoinMin(0.0,djValue); |
3073 | } else { |
3074 | djs[i]=0.0; |
3075 | } |
3076 | } |
3077 | columnGap[i]=gap-primalTolerance_; |
3078 | } |
3079 | |
3080 | int ipass=0,nfixed=-1; |
3081 | |
3082 | double cutoff; |
3083 | bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff); |
3084 | if (!cutoff_available||usingObjective_<0) { |
3085 | cutoff = si.getInfinity(); |
3086 | } |
3087 | cutoff *= direction; |
3088 | if (fabs(cutoff)>1.0e30) |
3089 | assert (cutoff>1.0e30); |
3090 | double current = si.getObjValue(); |
3091 | current *= direction; |
3092 | |
3093 | int nstackC0=-1; |
3094 | int nstackR,nstackC; |
3095 | |
3096 | for (int i=0;i<nCols;i++) { |
3097 | if (colUpper[i]-colLower[i]<1.0e-8) { |
3098 | markC[i]=3; |
3099 | |
3100 | } else { |
3101 | markC[i]=0; |
3102 | if (colUpper[i]>1.0e10) |
3103 | markC[i] |= 8; |
3104 | if (colLower[i]<-1.0e10) |
3105 | markC[i] |= 4; |
3106 | } |
3107 | } |
3108 | |
3109 | double tolerance = 1.0e1*primalTolerance_; |
3110 | |
3111 | |
3112 | double needEffectiveness = info->strengthenRow ? 1.0e-8 : 1.0e-3; |
3113 | if (justReplace&&(info->pass&1)!=0) |
3114 | needEffectiveness=-1.0e10; |
3115 | if (PROBING_EXTRA_STUFF) { |
3116 | int nCut=0; |
3117 | for (int iRow=0;iRow<nRows;iRow++) { |
3118 | int numberInt=0; |
3119 | int whichInt=-1; |
3120 | int numberNeg=0; |
3121 | double sumFixed=0.0; |
3122 | double intValue=0.0; |
3123 | for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow+1];j++) { |
3124 | int jColumn = column[j]; |
3125 | double value = rowElements[j]; |
3126 | if (colUpper[jColumn] > colLower[jColumn]+1.0e-8) { |
3127 | if (intVar[jColumn]) { |
3128 | numberInt++; |
3129 | whichInt=jColumn; |
3130 | intValue=value; |
3131 | } else if (value<0) { |
3132 | numberNeg++; |
3133 | } |
3134 | } else { |
3135 | sumFixed += colLower[jColumn]*value; |
3136 | } |
3137 | } |
3138 | if (numberInt==1&&numberNeg==0&&intValue<0.0&&!rowUpper[iRow]&&rowLower[iRow]<-1.0e30&&!sumFixed) { |
3139 | double intSol = colsol[whichInt]; |
3140 | for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow+1];j++) { |
3141 | int jColumn = column[j]; |
3142 | |
3143 | if (colUpper[jColumn] > colLower[jColumn]+1.0e-8) { |
3144 | if (!intVar[jColumn]) { |
3145 | if (colLower[jColumn]||colUpper[jColumn]>1.0) |
3146 | continue;; |
3147 | double upper = colUpper[jColumn]; |
3148 | if (colsol[jColumn]>intSol*upper+1.0e-4) { |
3149 | nCut++; |
3150 | OsiRowCut rc; |
3151 | rc.setLb(-COIN_DBL_MAX); |
3152 | rc.setUb(0.0); |
3153 | rc.setEffectiveness(1.0e-5); |
3154 | int index[2]; |
3155 | double element[2]; |
3156 | index[0]=jColumn; |
3157 | index[1]=whichInt; |
3158 | element[0]=1.0; |
3159 | element[1]=-upper; |
3160 | rc.setRow(2,index,element,false); |
3161 | cs.insert(rc); |
3162 | } |
3163 | } |
3164 | } |
3165 | } |
3166 | } |
3167 | } |
3168 | if (nCut) |
3169 | printf("%d possible cuts\n",nCut); |
3170 | } |
3171 | bool saveFixingInfo = false; |
3172 | #if PROBING100 |
3173 | CglTreeProbingInfo * probingInfo = dynamic_cast<CglTreeProbingInfo *> (info); |
3174 | const int * backward = NULL; |
3175 | const int * integerVariable = NULL; |
3176 | const int * toZero = NULL; |
3177 | const int * toOne = NULL; |
3178 | const fixEntry * fixEntries=NULL; |
3179 | #endif |
3180 | if (info->inTree) { |
3181 | #if PROBING100 |
3182 | backward = probingInfo->backward(); |
3183 | integerVariable = probingInfo->integerVariable(); |
3184 | toZero = probingInfo->toZero(); |
3185 | toOne = probingInfo->toOne(); |
3186 | fixEntries=probingInfo->fixEntries(); |
3187 | #endif |
3188 | } else { |
3189 | saveFixingInfo = (info->initializeFixing(&si)>0); |
3190 | } |
3191 | while (ipass<maxPass&&nfixed) { |
3192 | int iLook; |
3193 | ipass++; |
3194 | |
3195 | nfixed=0; |
3196 | int justFix= (!info->inTree&&!info->pass) ? -1 : 0; |
3197 | int maxProbe = info->inTree ? maxProbe_ : maxProbeRoot_; |
3198 | if (justFix<0) |
3199 | maxProbe=numberThisTime_; |
3200 | if (maxProbe==123) { |
3201 | |
3202 | maxProbe=0; |
3203 | if (!info->inTree) { |
3204 | if (!info->pass||numberThisTime_<-100) { |
3205 | maxProbe=numberThisTime_; |
3206 | } else { |
3207 | int cutDown = 4; |
3208 | int offset = info->pass % cutDown; |
3209 | int i; |
3210 | int k=0; |
3211 | int kk=offset; |
3212 | for (i=0;i<numberThisTime_;i++) { |
3213 | if (!kk) { |
3214 | #define XXXXXX |
3215 | #ifdef XXXXXX |
3216 | lookedAt_[maxProbe]=lookedAt_[i]; |
3217 | #endif |
3218 | maxProbe++; |
3219 | kk=cutDown-1; |
3220 | } else { |
3221 | stackC[k++]=lookedAt_[i]; |
3222 | kk--; |
3223 | } |
3224 | } |
3225 | #ifdef XXXXXX |
3226 | memcpy(lookedAt_+maxProbe,stackC,k*sizeof(int)); |
3227 | #endif |
3228 | } |
3229 | } else { |
3230 | |
3231 | if (numberThisTime_<200) { |
3232 | maxProbe=numberThisTime_; |
3233 | } else { |
3234 | int cutDown = CoinMax(numberThisTime_/100,4); |
3235 | int offset = info->pass % cutDown; |
3236 | int i; |
3237 | int k=0; |
3238 | int kk=offset; |
3239 | for (i=0;i<numberThisTime_;i++) { |
3240 | if (!kk) { |
3241 | #ifdef XXXXXX |
3242 | lookedAt_[maxProbe]=lookedAt_[i]; |
3243 | #endif |
3244 | maxProbe++; |
3245 | kk=cutDown-1; |
3246 | } else { |
3247 | stackC[k++]=lookedAt_[i]; |
3248 | kk--; |
3249 | } |
3250 | } |
3251 | #ifdef XXXXXX |
3252 | memcpy(lookedAt_+maxProbe,stackC,k*sizeof(int)); |
3253 | #endif |
3254 | } |
3255 | } |
3256 | } |
3257 | int leftTotalStack=maxStack*CoinMax(200,maxProbe); |
3258 | #ifdef PROBING5 |
3259 | if (!info->inTree&&!info->pass) |
3260 | leftTotalStack = 1234567890; |
3261 | #endif |
3262 | |
3263 | |
3264 | for (iLook=0;iLook<numberThisTime_;iLook++) { |
3265 | double solval; |
3266 | double down; |
3267 | double up; |
3268 | if (rowCut.outOfSpace()||leftTotalStack<=0) { |
3269 | if (!justFix&&(!nfixed||info->inTree)) { |
3270 | #ifdef COIN_DEVELOP |
3271 | if (!info->inTree) |
3272 | printf("Exiting a on pass %d, maxProbe %d\n", |
3273 | ipass,maxProbe); |
3274 | #endif |
3275 | break; |
3276 | } else if (justFix<=0) { |
3277 | if (!info->inTree) { |
3278 | rowCuts=0; |
3279 | justFix=1; |
3280 | disaggEffectiveness=COIN_DBL_MAX; |
3281 | needEffectiveness=COIN_DBL_MAX; |
3282 | |
3283 | maxPass=1; |
3284 | } else if (!nfixed) { |
3285 | #ifdef COIN_DEVELOP |
3286 | printf("Exiting b on pass %d, maxProbe %d\n", |
3287 | ipass,maxProbe); |
3288 | #endif |
3289 | break; |
3290 | } |
3291 | } |
3292 | } |
3293 | int j=lookedAt_[iLook]; |
3294 | |
3295 | |
3296 | solval=colsol[j]; |
3297 | down = floor(solval+tolerance); |
3298 | up = ceil(solval-tolerance); |
3299 | if(columnGap[j]<0.0) markC[j]=3; |
3300 | if ((markC[j]&3)!=0||!intVar[j]) continue; |
3301 | double saveSolval = solval; |
3302 | if (solval>=colUpper[j]-tolerance||solval<=colLower[j]+tolerance||up==down) { |
3303 | if (solval<=colLower[j]+2.0*tolerance) { |
3304 | solval = colLower[j]+1.0e-1; |
3305 | down=colLower[j]; |
3306 | up=down+1.0; |
3307 | } else if (solval>=colUpper[j]-2.0*tolerance) { |
3308 | solval = colUpper[j]-1.0e-1; |
3309 | up=colUpper[j]; |
3310 | down=up-1; |
3311 | } else { |
3312 | |
3313 | up=down+1.0; |
3314 | solval = down+1.0e-1; |
3315 | } |
3316 | } |
3317 | assert (up<=colUpper[j]); |
3318 | assert (down>=colLower[j]); |
3319 | assert (up>down); |
3320 | int istackC,iway, istackR; |
3321 | int way[]={1,2,1}; |
3322 | int feas[]={1,2,4}; |
3323 | int feasible=0; |
3324 | int notFeasible; |
3325 | for (iway=0;iway<3;iway ++) { |
3326 | int fixThis=0; |
3327 | double objVal=current; |
3328 | int goingToTrueBound=0; |
3329 | stackC[0]=j; |
3330 | markC[j]=way[iway]; |
3331 | double solMovement; |
3332 | double movement; |
3333 | if (way[iway]==1) { |
3334 | movement=down-colUpper[j]; |
3335 | solMovement = down-colsol[j]; |
3336 | assert(movement<-0.99999); |
3337 | if (fabs(down-colLower[j])<1.0e-7) { |
3338 | goingToTrueBound=2; |
3339 | down=colLower[j]; |
3340 | } |
3341 | } else { |
3342 | movement=up-colLower[j]; |
3343 | solMovement = up-colsol[j]; |
3344 | assert(movement>0.99999); |
3345 | if (fabs(up-colUpper[j])<1.0e-7) { |
3346 | goingToTrueBound=2; |
3347 | up=colUpper[j]; |
3348 | } |
3349 | } |
3350 | if (goingToTrueBound&&(colUpper[j]-colLower[j]>1.5||colLower[j])) |
3351 | goingToTrueBound=1; |
3352 | |
3353 | if ((rowCuts&1)==0) |
3354 | goingToTrueBound=0; |
3355 | bool canReplace = info->strengthenRow&&(goingToTrueBound==2); |
3356 | #ifdef PRINT_DEBUG |
3357 | if (fabs(movement)>1.01) { |
3358 | printf("big %d %g %g %g\n",j,colLower[j],solval,colUpper[j]); |
3359 | } |
3360 | #endif |
3361 | if (solMovement*djs[j]>0.0) |
3362 | objVal += solMovement*djs[j]; |
3363 | nstackC=1; |
3364 | nstackR=0; |
3365 | saveL[0]=colLower[j]; |
3366 | saveU[0]=colUpper[j]; |
3367 | assert (saveU[0]>saveL[0]); |
3368 | notFeasible=0; |
3369 | if (movement<0.0) { |
3370 | colUpper[j] += movement; |
3371 | colUpper[j] = floor(colUpper[j]+0.5); |
3372 | columnGap[j] = colUpper[j]-colLower[j]-primalTolerance_; |
3373 | #ifdef PRINT_DEBUG |
3374 | printf("** Trying %d down to 0\n",j); |
3375 | #endif |
3376 | } else { |
3377 | colLower[j] += movement; |
3378 | colLower[j] = floor(colLower[j]+0.5); |
3379 | columnGap[j] = colUpper[j]-colLower[j]-primalTolerance_; |
3380 | #ifdef PRINT_DEBUG |
3381 | printf("** Trying %d up to 1\n",j); |
3382 | #endif |
3383 | } |
3384 | if (fabs(colUpper[j]-colLower[j])<1.0e-6) |
3385 | markC[j]=3; |
3386 | markC[j] &= ~12; |
3387 | if (colUpper[j]>1.0e10) |
3388 | markC[j] |= 8; |
3389 | if (colLower[j]<-1.0e10) |
3390 | markC[j] |= 4; |
3391 | istackC=0; |
3392 | |
3393 | int k; |
3394 | for ( k=columnStart[j];k<columnStart[j]+columnLength[j];k++) { |
3395 | int irow = row[k]; |
3396 | double value = columnElements[k]; |
3397 | assert (markR[irow]!=-2); |
3398 | if (markR[irow]==-1) { |
3399 | stackR[nstackR]=irow; |
3400 | markR[irow]=nstackR; |
3401 | saveMin[nstackR]=minR[irow]; |
3402 | saveMax[nstackR]=maxR[irow]; |
3403 | nstackR++; |
3404 | #if 0 |
3405 | } else if (markR[irow]==-2) { |
3406 | continue; |
3407 | #endif |
3408 | } |
3409 | |
3410 | if (movement>0.0) { |
3411 | |
3412 | if (value>0.0) { |
3413 | |
3414 | if (minR[irow]>-1.0e10) |
3415 | minR[irow] += value; |
3416 | if (minR[irow]>rowUpper[irow]+1.0e-5) { |
3417 | notFeasible=1; |
3418 | istackC=1; |
3419 | break; |
3420 | } |
3421 | } else { |
3422 | |
3423 | if (maxR[irow]<1.0e10) |
3424 | maxR[irow] += value; |
3425 | if (maxR[irow]<rowLower[irow]-1.0e-5) { |
3426 | notFeasible=1; |
3427 | istackC=1; |
3428 | break; |
3429 | } |
3430 | } |
3431 | } else { |
3432 | |
3433 | if (value<0.0) { |
3434 | |
3435 | if (minR[irow]>-1.0e10) |
3436 | minR[irow] -= value; |
3437 | if (minR[irow]>rowUpper[irow]+1.0e-5) { |
3438 | notFeasible=1; |
3439 | istackC=1; |
3440 | break; |
3441 | } |
3442 | } else { |
3443 | |
3444 | if (maxR[irow]<1.0e10) |
3445 | maxR[irow] -= value; |
3446 | if (maxR[irow]<rowLower[irow]-1.0e-5) { |
3447 | notFeasible=1; |
3448 | istackC=1; |
3449 | break; |
3450 | } |
3451 | } |
3452 | } |
3453 | } |
3454 | while (istackC<nstackC&&nstackC<maxStack) { |
3455 | leftTotalStack--; |
3456 | int jway; |
3457 | int jcol =stackC[istackC]; |
3458 | jway=markC[jcol]; |
3459 | |
3460 | if ((jway&3)==3&&istackC) { |
3461 | |
3462 | |
3463 | |
3464 | } |
3465 | #if PROBING100 |
3466 | if (backward) { |
3467 | int jColumn = backward[jcol]; |
3468 | if (jColumn>=0) { |
3469 | int nFix=0; |
3470 | |
3471 | if (jway==1) { |
3472 | |
3473 | int j; |
3474 | for ( j=toZero_[jColumn];j<toOne_[jColumn];j++) { |
3475 | int kColumn=fixEntry_[j].sequence; |
3476 | kColumn = integerVariable_[kColumn]; |
3477 | bool fixToOne = fixEntry_[j].oneFixed; |
3478 | if (fixToOne) { |
3479 | if (colLower[kColumn]==0.0) { |
3480 | if (colUpper[kColumn]==1.0) { |
3481 | |
3482 | if (!(markC[kColumn]&3)) { |
3483 | if(nStackC<nCols) { |
3484 | stackC[nstackC]=kColumn; |
3485 | saveL[nstackC]=colLower[kColumn]; |
3486 | saveU[nstackC]=colUpper[kColumn]; |
3487 | assert (saveU[nstackC]>saveL[nstackC]); |
3488 | assert (nstackC<nCols); |
3489 | nstackC++; |
3490 | markC[kColumn]|=2; |
3491 | nFix++; |
3492 | } |
3493 | } else if ((markC[kColumn]&3)==1) { |
3494 | notFeasible=true; |
3495 | } |
3496 | } else { |
3497 | |
3498 | notFeasible=true; |
3499 | } |
3500 | } |
3501 | } else { |
3502 | if (colUpper[kColumn]==1.0) { |
3503 | if (colLower[kColumn]==0.0) { |
3504 | |
3505 | if (!(markC[kColumn]&3)) { |
3506 | if(nStackC<nCols) { |
3507 | stackC[nstackC]=kColumn; |
3508 | saveL[nstackC]=colLower[kColumn]; |
3509 | saveU[nstackC]=colUpper[kColumn]; |
3510 | assert (saveU[nstackC]>saveL[nstackC]); |
3511 | assert (nstackC<nCols); |
3512 | nstackC++; |
3513 | markC[kColumn]|=1; |
3514 | nFix++; |
3515 | } |
3516 | } else if ((markC[kColumn]&3)==2) { |
3517 | notFeasible=true; |
3518 | } |
3519 | } else { |
3520 | |
3521 | notFeasible=true; |
3522 | } |
3523 | } |
3524 | } |
3525 | } |
3526 | } else if (jway==2) { |
3527 | int j; |
3528 | for ( j=toOne_[jColumn];j<toZero_[jColumn+1];j++) { |
3529 | int kColumn=fixEntry_[j].sequence; |
3530 | kColumn = integerVariable_[kColumn]; |
3531 | bool fixToOne = fixEntry_[j].oneFixed; |
3532 | if (fixToOne) { |
3533 | if (colLower[kColumn]==0.0) { |
3534 | if (colUpper[kColumn]==1.0) { |
3535 | |
3536 | if (!(markC[kColumn]&3)) { |
3537 | if(nStackC<nCols) { |
3538 | stackC[nstackC]=kColumn; |
3539 | saveL[nstackC]=colLower[kColumn]; |
3540 | saveU[nstackC]=colUpper[kColumn]; |
3541 | assert (saveU[nstackC]>saveL[nstackC]); |
3542 | assert (nstackC<nCols); |
3543 | nstackC++; |
3544 | markC[kColumn]|=2; |
3545 | nFix++; |
3546 | } |
3547 | } else if ((markC[kColumn]&3)==1) { |
3548 | notFeasible=true; |
3549 | } |
3550 | } else { |
3551 | |
3552 | notFeasible=true; |
3553 | } |
3554 | } |
3555 | } else { |
3556 | if (colUpper[kColumn]==1.0) { |
3557 | if (colLower[kColumn]==0.0) { |
3558 | |
3559 | if (!(markC[kColumn]&3)) { |
3560 | if(nStackC<nCols) { |
3561 | stackC[nstackC]=kColumn; |
3562 | saveL[nstackC]=colLower[kColumn]; |
3563 | saveU[nstackC]=colUpper[kColumn]; |
3564 | assert (saveU[nstackC]>saveL[nstackC]); |
3565 | assert (nstackC<nCols); |
3566 | nstackC++; |
3567 | markC[kColumn]|=1; |
3568 | nFix++; |
3569 | } |
3570 | } else if ((markC[kColumn]&3)==2) { |
3571 | notFeasible=true; |
3572 | } |
3573 | } else { |
3574 | |
3575 | notFeasible=true; |
3576 | } |
3577 | } |
3578 | } |
3579 | } |
3580 | } |
3581 | } |
3582 | } |
3583 | #endif |
3584 | for (k=columnStart[jcol];k<columnStart[jcol]+columnLength[jcol];k++) { |
3585 | |
3586 | if (notFeasible) |
3587 | break; |
3588 | int irow = row[k]; |
3589 | |
3590 | int rStart = rowStart[irow]; |
3591 | int rEnd = rowStartPos[irow]; |
3592 | double rowUp = rowUpper[irow]; |
3593 | double rowUp2=0.0; |
3594 | bool doRowUpN; |
3595 | bool doRowUpP; |
3596 | if (rowUp<1.0e10) { |
3597 | doRowUpN=true; |
3598 | doRowUpP=true; |
3599 | rowUp2 = rowUp-minR[irow]; |
3600 | if (rowUp2<-primalTolerance_) { |
3601 | notFeasible=true; |
3602 | break; |
3603 | } else { |
3604 | if (rowUp2+largestNegativeInRow[irow]>0) |
3605 | doRowUpN=false; |
3606 | if (rowUp2-largestPositiveInRow[irow]>0) |
3607 | doRowUpP=false; |
3608 | } |
3609 | } else { |
3610 | doRowUpN=false; |
3611 | doRowUpP=false; |
3612 | rowUp2=COIN_DBL_MAX; |
3613 | } |
3614 | double rowLo = rowLower[irow]; |
3615 | double rowLo2=0.0; |
3616 | bool doRowLoN; |
3617 | bool doRowLoP; |
3618 | if (rowLo>-1.0e10) { |
3619 | doRowLoN=true; |
3620 | doRowLoP=true; |
3621 | rowLo2 = rowLo-maxR[irow]; |
3622 | if (rowLo2>primalTolerance_) { |
3623 | notFeasible=true; |
3624 | break; |
3625 | } else { |
3626 | if (rowLo2-largestNegativeInRow[irow]<0) |
3627 | doRowLoN=false; |
3628 | if (rowLo2+largestPositiveInRow[irow]<0) |
3629 | doRowLoP=false; |
3630 | } |
3631 | } else { |
3632 | doRowLoN=false; |
3633 | doRowLoP=false; |
3634 | rowLo2=-COIN_DBL_MAX; |
3635 | } |
3636 | if (doRowUpN&&doRowLoN) { |
3637 | |
3638 | |
3639 | for (int kk =rStart;kk<rEnd;kk++) { |
3640 | int kcol=column[kk]; |
3641 | int markIt=markC[kcol]; |
3642 | if ((markIt&3)!=3) { |
3643 | double value2=rowElements[kk]; |
3644 | if (colUpper[kcol]<=1e10) |
3645 | assert ((markIt&8)==0); |
3646 | else |
3647 | assert ((markIt&8)!=0); |
3648 | if (colLower[kcol]>=-1e10) |
3649 | assert ((markIt&4)==0); |
3650 | else |
3651 | assert ((markIt&4)!=0); |
3652 | assert (value2<0.0); |
3653 | double gap = columnGap[kcol]*value2; |
3654 | bool doUp = (rowUp2 + gap < 0.0); |
3655 | bool doDown = (rowLo2 -gap > 0.0); |
3656 | if (doUp||doDown) { |
3657 | double moveUp=0.0; |
3658 | double moveDown=0.0; |
3659 | double newUpper=-1.0; |
3660 | double newLower=1.0; |
3661 | if ( doUp&&(markIt&(2+8))==0) { |
3662 | double dbound = colUpper[kcol]+rowUp2/value2; |
3663 | if (intVar[kcol]) { |
3664 | markIt |= 2; |
3665 | newLower = ceil(dbound-primalTolerance_); |
3666 | } else { |
3667 | newLower=dbound; |
3668 | if (newLower+primalTolerance_>colUpper[kcol]&& |
3669 | newLower-primalTolerance_<=colUpper[kcol]) { |
3670 | newLower=colUpper[kcol]; |
3671 | markIt |= 2; |
3672 | |
3673 | } else { |
3674 | |
3675 | markIt=3; |
3676 | } |
3677 | } |
3678 | moveUp = newLower-colLower[kcol]; |
3679 | } |
3680 | if ( doDown&&(markIt&(1+4))==0) { |
3681 | double dbound = colLower[kcol] + rowLo2/value2; |
3682 | if (intVar[kcol]) { |
3683 | markIt |= 1; |
3684 | newUpper = floor(dbound+primalTolerance_); |
3685 | } else { |
3686 | newUpper=dbound; |
3687 | if (newUpper-primalTolerance_<colLower[kcol]&& |
3688 | newUpper+primalTolerance_>=colLower[kcol]) { |
3689 | newUpper=colLower[kcol]; |
3690 | markIt |= 1; |
3691 | |
3692 | } else { |
3693 | |
3694 | markIt=3; |
3695 | } |
3696 | } |
3697 | moveDown = newUpper-colUpper[kcol]; |
3698 | } |
3699 | if (!moveUp&&!moveDown) |
3700 | continue; |
3701 | bool onList = ((markC[kcol]&3)!=0); |
3702 | if (nstackC<2*maxStack) { |
3703 | markC[kcol] = markIt; |
3704 | } |
3705 | if (moveUp&&nstackC<2*maxStack) { |
3706 | fixThis++; |
3707 | if (!onList) { |
3708 | stackC[nstackC]=kcol; |
3709 | saveL[nstackC]=colLower[kcol]; |
3710 | saveU[nstackC]=colUpper[kcol]; |
3711 | assert (saveU[nstackC]>saveL[nstackC]); |
3712 | assert (nstackC<nCols); |
3713 | nstackC++; |
3714 | onList=true; |
3715 | } |
3716 | if (newLower>colsol[kcol]) { |
3717 | if (djs[kcol]<0.0) { |
3718 | |
3719 | assert (newLower>colUpper[kcol]+primalTolerance_); |
3720 | } else { |
3721 | objVal += moveUp*djs[kcol]; |
3722 | } |
3723 | } |
3724 | if (intVar[kcol]) |
3725 | newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4)); |
3726 | colLower[kcol]=newLower; |
3727 | columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_; |
3728 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
3729 | markC[kcol]=3; |
3730 | } |
3731 | markC[kcol] &= ~12; |
3732 | if (colUpper[kcol]>1.0e10) |
3733 | markC[kcol] |= 8; |
3734 | if (colLower[kcol]<-1.0e10) |
3735 | markC[kcol] |= 4; |
3736 | |
3737 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
3738 | int krow = row[jj]; |
3739 | double value = columnElements[jj]; |
3740 | assert (markR[krow]!=-2); |
3741 | if (markR[krow]==-1) { |
3742 | stackR[nstackR]=krow; |
3743 | markR[krow]=nstackR; |
3744 | saveMin[nstackR]=minR[krow]; |
3745 | saveMax[nstackR]=maxR[krow]; |
3746 | nstackR++; |
3747 | } |
3748 | |
3749 | |
3750 | if (value>0.0) { |
3751 | |
3752 | if (minR[krow]>-1.0e10) |
3753 | minR[krow] += value*moveUp; |
3754 | if (krow==irow) |
3755 | rowUp2 = rowUp-minR[irow]; |
3756 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
3757 | colUpper[kcol]=-1.0e50; |
3758 | break; |
3759 | } |
3760 | } else { |
3761 | |
3762 | if (maxR[krow]<1.0e10) |
3763 | maxR[krow] += value*moveUp; |
3764 | if (krow==irow) |
3765 | rowLo2 = rowLo-maxR[irow]; |
3766 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
3767 | colUpper[kcol]=-1.0e50; |
3768 | break; |
3769 | } |
3770 | } |
3771 | } |
3772 | } |
3773 | if (moveDown&&nstackC<2*maxStack) { |
3774 | fixThis++; |
3775 | if (!onList) { |
3776 | stackC[nstackC]=kcol; |
3777 | saveL[nstackC]=colLower[kcol]; |
3778 | saveU[nstackC]=colUpper[kcol]; |
3779 | assert (saveU[nstackC]>saveL[nstackC]); |
3780 | assert (nstackC<nCols); |
3781 | nstackC++; |
3782 | onList=true; |
3783 | } |
3784 | if (newUpper<colsol[kcol]) { |
3785 | if (djs[kcol]>0.0) { |
3786 | |
3787 | assert (colLower[kcol]>newUpper+primalTolerance_); |
3788 | } else { |
3789 | objVal += moveDown*djs[kcol]; |
3790 | } |
3791 | } |
3792 | if (intVar[kcol]) |
3793 | newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4)); |
3794 | colUpper[kcol]=newUpper; |
3795 | columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_; |
3796 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
3797 | markC[kcol]=3; |
3798 | } |
3799 | markC[kcol] &= ~12; |
3800 | if (colUpper[kcol]>1.0e10) |
3801 | markC[kcol] |= 8; |
3802 | if (colLower[kcol]<-1.0e10) |
3803 | markC[kcol] |= 4; |
3804 | |
3805 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
3806 | int krow = row[jj]; |
3807 | double value = columnElements[jj]; |
3808 | assert (markR[krow]!=-2); |
3809 | if (markR[krow]==-1) { |
3810 | stackR[nstackR]=krow; |
3811 | markR[krow]=nstackR; |
3812 | saveMin[nstackR]=minR[krow]; |
3813 | saveMax[nstackR]=maxR[krow]; |
3814 | nstackR++; |
3815 | } |
3816 | |
3817 | |
3818 | if (value<0.0) { |
3819 | |
3820 | if (minR[krow]>-1.0e10) |
3821 | minR[krow] += value*moveDown; |
3822 | if (krow==irow) |
3823 | rowUp2 = rowUp-minR[irow]; |
3824 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
3825 | colUpper[kcol]=-1.0e50; |
3826 | columnGap[kcol] = -1.0e50; |
3827 | break; |
3828 | } |
3829 | } else { |
3830 | |
3831 | if (maxR[krow]<1.0e10) |
3832 | maxR[krow] += value*moveDown; |
3833 | if (krow==irow) |
3834 | rowLo2 = rowLo-maxR[irow]; |
3835 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
3836 | colUpper[kcol]=-1.0e50; |
3837 | columnGap[kcol] = -1.0e50; |
3838 | break; |
3839 | } |
3840 | } |
3841 | } |
3842 | } |
3843 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
3844 | notFeasible=1;; |
3845 | k=columnStart[jcol]+columnLength[jcol]; |
3846 | istackC=nstackC+1; |
3847 | break; |
3848 | } |
3849 | } |
3850 | } |
3851 | } |
3852 | } else if (doRowUpN) { |
3853 | |
3854 | for (int kk =rStart;kk<rEnd;kk++) { |
3855 | int kcol =column[kk]; |
3856 | int markIt=markC[kcol]; |
3857 | if ((markIt&3)!=3) { |
3858 | double value2=rowElements[kk]; |
3859 | double gap = columnGap[kcol]*value2; |
3860 | if (!(rowUp2 + gap < 0.0)) |
3861 | continue; |
3862 | double moveUp=0.0; |
3863 | double newLower=1.0; |
3864 | if ((markIt&(2+8))==0) { |
3865 | double dbound = colUpper[kcol]+rowUp2/value2; |
3866 | if (intVar[kcol]) { |
3867 | markIt |= 2; |
3868 | newLower = ceil(dbound-primalTolerance_); |
3869 | } else { |
3870 | newLower=dbound; |
3871 | if (newLower+primalTolerance_>colUpper[kcol]&& |
3872 | newLower-primalTolerance_<=colUpper[kcol]) { |
3873 | newLower=colUpper[kcol]; |
3874 | markIt |= 2; |
3875 | |
3876 | } else { |
3877 | |
3878 | markIt=3; |
3879 | } |
3880 | } |
3881 | moveUp = newLower-colLower[kcol]; |
3882 | if (!moveUp) |
3883 | continue; |
3884 | bool onList = ((markC[kcol]&3)!=0); |
3885 | if (nstackC<2*maxStack) { |
3886 | markC[kcol] = markIt; |
3887 | } |
3888 | if (moveUp&&nstackC<2*maxStack) { |
3889 | fixThis++; |
3890 | if (!onList) { |
3891 | stackC[nstackC]=kcol; |
3892 | saveL[nstackC]=colLower[kcol]; |
3893 | saveU[nstackC]=colUpper[kcol]; |
3894 | assert (saveU[nstackC]>saveL[nstackC]); |
3895 | assert (nstackC<nCols); |
3896 | nstackC++; |
3897 | onList=true; |
3898 | } |
3899 | if (newLower>colsol[kcol]) { |
3900 | if (djs[kcol]<0.0) { |
3901 | |
3902 | assert (newLower>colUpper[kcol]+primalTolerance_); |
3903 | } else { |
3904 | objVal += moveUp*djs[kcol]; |
3905 | } |
3906 | } |
3907 | if (intVar[kcol]) |
3908 | newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4)); |
3909 | colLower[kcol]=newLower; |
3910 | columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_; |
3911 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
3912 | markC[kcol]=3; |
3913 | } |
3914 | markC[kcol] &= ~12; |
3915 | if (colUpper[kcol]>1.0e10) |
3916 | markC[kcol] |= 8; |
3917 | if (colLower[kcol]<-1.0e10) |
3918 | markC[kcol] |= 4; |
3919 | |
3920 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
3921 | int krow = row[jj]; |
3922 | double value = columnElements[jj]; |
3923 | assert (markR[krow]!=-2); |
3924 | if (markR[krow]==-1) { |
3925 | stackR[nstackR]=krow; |
3926 | markR[krow]=nstackR; |
3927 | saveMin[nstackR]=minR[krow]; |
3928 | saveMax[nstackR]=maxR[krow]; |
3929 | nstackR++; |
3930 | } |
3931 | |
3932 | |
3933 | if (value>0.0) { |
3934 | |
3935 | if (minR[krow]>-1.0e10) |
3936 | minR[krow] += value*moveUp; |
3937 | if (krow==irow) |
3938 | rowUp2 = rowUp-minR[irow]; |
3939 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
3940 | colUpper[kcol]=-1.0e50; |
3941 | columnGap[kcol] = -1.0e50; |
3942 | break; |
3943 | } |
3944 | } else { |
3945 | |
3946 | if (maxR[krow]<1.0e10) |
3947 | maxR[krow] += value*moveUp; |
3948 | if (krow==irow) |
3949 | rowLo2 = rowLo-maxR[irow]; |
3950 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
3951 | colUpper[kcol]=-1.0e50; |
3952 | columnGap[kcol] = -1.0e50; |
3953 | break; |
3954 | } |
3955 | } |
3956 | } |
3957 | } |
3958 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
3959 | notFeasible=1;; |
3960 | k=columnStart[jcol]+columnLength[jcol]; |
3961 | istackC=nstackC+1; |
3962 | break; |
3963 | } |
3964 | } |
3965 | } |
3966 | } |
3967 | } else if (doRowLoN) { |
3968 | |
3969 | for (int kk =rStart;kk<rEnd;kk++) { |
3970 | int kcol =column[kk]; |
3971 | if ((markC[kcol]&3)!=3) { |
3972 | double moveDown=0.0; |
3973 | double newUpper=-1.0; |
3974 | double value2=rowElements[kk]; |
3975 | int markIt=markC[kcol]; |
3976 | assert (value2<0.0); |
3977 | double gap = columnGap[kcol]*value2; |
3978 | bool doDown = (rowLo2 -gap > 0.0); |
3979 | if (doDown&& (markIt&(1+4))==0 ) { |
3980 | double dbound = colLower[kcol] + rowLo2/value2; |
3981 | if (intVar[kcol]) { |
3982 | markIt |= 1; |
3983 | newUpper = floor(dbound+primalTolerance_); |
3984 | } else { |
3985 | newUpper=dbound; |
3986 | if (newUpper-primalTolerance_<colLower[kcol]&& |
3987 | newUpper+primalTolerance_>=colLower[kcol]) { |
3988 | newUpper=colLower[kcol]; |
3989 | markIt |= 1; |
3990 | |
3991 | } else { |
3992 | |
3993 | markIt=3; |
3994 | } |
3995 | } |
3996 | moveDown = newUpper-colUpper[kcol]; |
3997 | if (!moveDown) |
3998 | continue; |
3999 | bool onList = ((markC[kcol]&3)!=0); |
4000 | if (nstackC<2*maxStack) { |
4001 | markC[kcol] = markIt; |
4002 | } |
4003 | if (moveDown&&nstackC<2*maxStack) { |
4004 | fixThis++; |
4005 | if (!onList) { |
4006 | stackC[nstackC]=kcol; |
4007 | saveL[nstackC]=colLower[kcol]; |
4008 | saveU[nstackC]=colUpper[kcol]; |
4009 | assert (saveU[nstackC]>saveL[nstackC]); |
4010 | assert (nstackC<nCols); |
4011 | nstackC++; |
4012 | onList=true; |
4013 | } |
4014 | if (newUpper<colsol[kcol]) { |
4015 | if (djs[kcol]>0.0) { |
4016 | |
4017 | assert (colLower[kcol]>newUpper+primalTolerance_); |
4018 | } else { |
4019 | objVal += moveDown*djs[kcol]; |
4020 | } |
4021 | } |
4022 | if (intVar[kcol]) |
4023 | newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4)); |
4024 | colUpper[kcol]=newUpper; |
4025 | columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_; |
4026 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
4027 | markC[kcol]=3; |
4028 | } |
4029 | markC[kcol] &= ~12; |
4030 | if (colUpper[kcol]>1.0e10) |
4031 | markC[kcol] |= 8; |
4032 | if (colLower[kcol]<-1.0e10) |
4033 | markC[kcol] |= 4; |
4034 | |
4035 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
4036 | int krow = row[jj]; |
4037 | double value = columnElements[jj]; |
4038 | assert (markR[krow]!=-2); |
4039 | if (markR[krow]==-1) { |
4040 | stackR[nstackR]=krow; |
4041 | markR[krow]=nstackR; |
4042 | saveMin[nstackR]=minR[krow]; |
4043 | saveMax[nstackR]=maxR[krow]; |
4044 | nstackR++; |
4045 | } |
4046 | |
4047 | |
4048 | if (value<0.0) { |
4049 | |
4050 | if (minR[krow]>-1.0e10) |
4051 | minR[krow] += value*moveDown; |
4052 | if (krow==irow) |
4053 | rowUp2 = rowUp-minR[irow]; |
4054 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
4055 | colUpper[kcol]=-1.0e50; |
4056 | columnGap[kcol] = -1.0e50; |
4057 | break; |
4058 | } |
4059 | } else { |
4060 | |
4061 | if (maxR[krow]<1.0e10) |
4062 | maxR[krow] += value*moveDown; |
4063 | if (krow==irow) |
4064 | rowLo2 = rowLo-maxR[irow]; |
4065 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
4066 | colUpper[kcol]=-1.0e50; |
4067 | columnGap[kcol] = -1.0e50; |
4068 | break; |
4069 | } |
4070 | } |
4071 | } |
4072 | } |
4073 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
4074 | notFeasible=1;; |
4075 | k=columnStart[jcol]+columnLength[jcol]; |
4076 | istackC=nstackC+1; |
4077 | break; |
4078 | } |
4079 | } |
4080 | } |
4081 | } |
4082 | } |
4083 | rStart = rEnd; |
4084 | rEnd = rowStart[irow+1]; |
4085 | if (doRowUpP&&doRowLoP) { |
4086 | |
4087 | |
4088 | for (int kk =rStart;kk<rEnd;kk++) { |
4089 | int kcol=column[kk]; |
4090 | int markIt=markC[kcol]; |
4091 | if ((markIt&3)!=3) { |
4092 | double value2=rowElements[kk]; |
4093 | assert (value2 > 0.0); |
4094 | |
4095 | double gap = columnGap[kcol]*value2; |
4096 | bool doDown = (rowLo2 + gap > 0.0); |
4097 | bool doUp = (rowUp2 - gap < 0.0); |
4098 | if (doDown||doUp) { |
4099 | double moveUp=0.0; |
4100 | double moveDown=0.0; |
4101 | double newUpper=-1.0; |
4102 | double newLower=1.0; |
4103 | if (doDown&&(markIt&(2+8))==0) { |
4104 | double dbound = colUpper[kcol] + rowLo2/value2; |
4105 | if (intVar[kcol]) { |
4106 | markIt |= 2; |
4107 | newLower = ceil(dbound-primalTolerance_); |
4108 | } else { |
4109 | newLower=dbound; |
4110 | if (newLower+primalTolerance_>colUpper[kcol]&& |
4111 | newLower-primalTolerance_<=colUpper[kcol]) { |
4112 | newLower=colUpper[kcol]; |
4113 | markIt |= 2; |
4114 | |
4115 | } else { |
4116 | |
4117 | markIt=3; |
4118 | } |
4119 | } |
4120 | moveUp = newLower-colLower[kcol]; |
4121 | } |
4122 | if (doUp&&(markIt&(1+4))==0) { |
4123 | double dbound = colLower[kcol] + rowUp2/value2; |
4124 | if (intVar[kcol]) { |
4125 | markIt |= 1; |
4126 | newUpper = floor(dbound+primalTolerance_); |
4127 | } else { |
4128 | newUpper=dbound; |
4129 | if (newUpper-primalTolerance_<colLower[kcol]&& |
4130 | newUpper+primalTolerance_>=colLower[kcol]) { |
4131 | newUpper=colLower[kcol]; |
4132 | markIt |= 1; |
4133 | |
4134 | } else { |
4135 | |
4136 | markIt=3; |
4137 | } |
4138 | } |
4139 | moveDown = newUpper-colUpper[kcol]; |
4140 | } |
4141 | if (!moveUp&&!moveDown) |
4142 | continue; |
4143 | bool onList = ((markC[kcol]&3)!=0); |
4144 | if (nstackC<2*maxStack) { |
4145 | markC[kcol] = markIt; |
4146 | } |
4147 | if (moveUp&&nstackC<2*maxStack) { |
4148 | fixThis++; |
4149 | if (!onList) { |
4150 | stackC[nstackC]=kcol; |
4151 | saveL[nstackC]=colLower[kcol]; |
4152 | saveU[nstackC]=colUpper[kcol]; |
4153 | assert (saveU[nstackC]>saveL[nstackC]); |
4154 | assert (nstackC<nCols); |
4155 | nstackC++; |
4156 | onList=true; |
4157 | } |
4158 | if (newLower>colsol[kcol]) { |
4159 | if (djs[kcol]<0.0) { |
4160 | |
4161 | assert (newLower>colUpper[kcol]+primalTolerance_); |
4162 | } else { |
4163 | objVal += moveUp*djs[kcol]; |
4164 | } |
4165 | } |
4166 | if (intVar[kcol]) |
4167 | newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4)); |
4168 | colLower[kcol]=newLower; |
4169 | columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_; |
4170 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
4171 | markC[kcol]=3; |
4172 | } |
4173 | markC[kcol] &= ~12; |
4174 | if (colUpper[kcol]>1.0e10) |
4175 | markC[kcol] |= 8; |
4176 | if (colLower[kcol]<-1.0e10) |
4177 | markC[kcol] |= 4; |
4178 | |
4179 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
4180 | int krow = row[jj]; |
4181 | double value = columnElements[jj]; |
4182 | assert (markR[krow]!=-2); |
4183 | if (markR[krow]==-1) { |
4184 | stackR[nstackR]=krow; |
4185 | markR[krow]=nstackR; |
4186 | saveMin[nstackR]=minR[krow]; |
4187 | saveMax[nstackR]=maxR[krow]; |
4188 | nstackR++; |
4189 | } |
4190 | |
4191 | |
4192 | if (value>0.0) { |
4193 | |
4194 | if (minR[krow]>-1.0e10) |
4195 | minR[krow] += value*moveUp; |
4196 | if (krow==irow) |
4197 | rowUp2 = rowUp-minR[irow]; |
4198 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
4199 | colUpper[kcol]=-1.0e50; |
4200 | columnGap[kcol] = -1.0e50; |
4201 | break; |
4202 | } |
4203 | } else { |
4204 | |
4205 | if (maxR[krow]<1.0e10) |
4206 | maxR[krow] += value*moveUp; |
4207 | if (krow==irow) |
4208 | rowLo2 = rowLo-maxR[irow]; |
4209 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
4210 | colUpper[kcol]=-1.0e50; |
4211 | columnGap[kcol] = -1.0e50; |
4212 | break; |
4213 | } |
4214 | } |
4215 | } |
4216 | } |
4217 | if (moveDown&&nstackC<2*maxStack) { |
4218 | fixThis++; |
4219 | if (!onList) { |
4220 | stackC[nstackC]=kcol; |
4221 | saveL[nstackC]=colLower[kcol]; |
4222 | saveU[nstackC]=colUpper[kcol]; |
4223 | assert (saveU[nstackC]>saveL[nstackC]); |
4224 | assert (nstackC<nCols); |
4225 | nstackC++; |
4226 | onList=true; |
4227 | } |
4228 | if (newUpper<colsol[kcol]) { |
4229 | if (djs[kcol]>0.0) { |
4230 | |
4231 | assert (colLower[kcol]>newUpper+primalTolerance_); |
4232 | } else { |
4233 | objVal += moveDown*djs[kcol]; |
4234 | } |
4235 | } |
4236 | if (intVar[kcol]) |
4237 | newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4)); |
4238 | colUpper[kcol]=newUpper; |
4239 | columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_; |
4240 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
4241 | markC[kcol]=3; |
4242 | } |
4243 | markC[kcol] &= ~12; |
4244 | if (colUpper[kcol]>1.0e10) |
4245 | markC[kcol] |= 8; |
4246 | if (colLower[kcol]<-1.0e10) |
4247 | markC[kcol] |= 4; |
4248 | |
4249 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
4250 | int krow = row[jj]; |
4251 | double value = columnElements[jj]; |
4252 | assert (markR[krow]!=-2); |
4253 | if (markR[krow]==-1) { |
4254 | stackR[nstackR]=krow; |
4255 | markR[krow]=nstackR; |
4256 | saveMin[nstackR]=minR[krow]; |
4257 | saveMax[nstackR]=maxR[krow]; |
4258 | nstackR++; |
4259 | } |
4260 | |
4261 | |
4262 | if (value<0.0) { |
4263 | |
4264 | if (minR[krow]>-1.0e10) |
4265 | minR[krow] += value*moveDown; |
4266 | if (krow==irow) |
4267 | rowUp2 = rowUp-minR[irow]; |
4268 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
4269 | colUpper[kcol]=-1.0e50; |
4270 | columnGap[kcol] = -1.0e50; |
4271 | break; |
4272 | } |
4273 | } else { |
4274 | |
4275 | if (maxR[krow]<1.0e10) |
4276 | maxR[krow] += value*moveDown; |
4277 | if (krow==irow) |
4278 | rowLo2 = rowLo-maxR[irow]; |
4279 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
4280 | colUpper[kcol]=-1.0e50; |
4281 | columnGap[kcol] = -1.0e50; |
4282 | break; |
4283 | } |
4284 | } |
4285 | } |
4286 | } |
4287 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
4288 | notFeasible=1;; |
4289 | k=columnStart[jcol]+columnLength[jcol]; |
4290 | istackC=nstackC+1; |
4291 | break; |
4292 | } |
4293 | } |
4294 | } |
4295 | } |
4296 | } else if (doRowUpP) { |
4297 | |
4298 | for (int kk =rStart;kk<rEnd;kk++) { |
4299 | int kcol =column[kk]; |
4300 | int markIt=markC[kcol]; |
4301 | if ((markIt&3)!=3) { |
4302 | double value2=rowElements[kk]; |
4303 | assert (value2 > 0.0); |
4304 | |
4305 | double gap = columnGap[kcol]*value2; |
4306 | bool doUp = (rowUp2 - gap < 0.0); |
4307 | if (doUp&&(markIt&(1+4))==0) { |
4308 | double newUpper=-1.0; |
4309 | double dbound = colLower[kcol] + rowUp2/value2; |
4310 | if (intVar[kcol]) { |
4311 | markIt |= 1; |
4312 | newUpper = floor(dbound+primalTolerance_); |
4313 | } else { |
4314 | newUpper=dbound; |
4315 | if (newUpper-primalTolerance_<colLower[kcol]&& |
4316 | newUpper+primalTolerance_>=colLower[kcol]) { |
4317 | newUpper=colLower[kcol]; |
4318 | markIt |= 1; |
4319 | |
4320 | } else { |
4321 | |
4322 | markIt=3; |
4323 | } |
4324 | } |
4325 | double moveDown = newUpper-colUpper[kcol]; |
4326 | if (!moveDown) |
4327 | continue; |
4328 | bool onList = ((markC[kcol]&3)!=0); |
4329 | if (nstackC<2*maxStack) { |
4330 | markC[kcol] = markIt; |
4331 | } |
4332 | if (nstackC<2*maxStack) { |
4333 | fixThis++; |
4334 | if (!onList) { |
4335 | stackC[nstackC]=kcol; |
4336 | saveL[nstackC]=colLower[kcol]; |
4337 | saveU[nstackC]=colUpper[kcol]; |
4338 | assert (saveU[nstackC]>saveL[nstackC]); |
4339 | assert (nstackC<nCols); |
4340 | nstackC++; |
4341 | onList=true; |
4342 | } |
4343 | if (newUpper<colsol[kcol]) { |
4344 | if (djs[kcol]>0.0) { |
4345 | |
4346 | assert (colLower[kcol]>newUpper+primalTolerance_); |
4347 | } else { |
4348 | objVal += moveDown*djs[kcol]; |
4349 | } |
4350 | } |
4351 | if (intVar[kcol]) |
4352 | newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4)); |
4353 | colUpper[kcol]=newUpper; |
4354 | columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_; |
4355 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
4356 | markC[kcol]=3; |
4357 | } |
4358 | markC[kcol] &= ~12; |
4359 | if (colUpper[kcol]>1.0e10) |
4360 | markC[kcol] |= 8; |
4361 | if (colLower[kcol]<-1.0e10) |
4362 | markC[kcol] |= 4; |
4363 | |
4364 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
4365 | int krow = row[jj]; |
4366 | double value = columnElements[jj]; |
4367 | assert (markR[krow]!=-2); |
4368 | if (markR[krow]==-1) { |
4369 | stackR[nstackR]=krow; |
4370 | markR[krow]=nstackR; |
4371 | saveMin[nstackR]=minR[krow]; |
4372 | saveMax[nstackR]=maxR[krow]; |
4373 | nstackR++; |
4374 | } |
4375 | |
4376 | |
4377 | if (value<0.0) { |
4378 | |
4379 | if (minR[krow]>-1.0e10) |
4380 | minR[krow] += value*moveDown; |
4381 | if (krow==irow) |
4382 | rowUp2 = rowUp-minR[irow]; |
4383 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
4384 | colUpper[kcol]=-1.0e50; |
4385 | columnGap[kcol] = -1.0e50; |
4386 | break; |
4387 | } |
4388 | } else { |
4389 | |
4390 | if (maxR[krow]<1.0e10) |
4391 | maxR[krow] += value*moveDown; |
4392 | if (krow==irow) |
4393 | rowLo2 = rowLo-maxR[irow]; |
4394 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
4395 | colUpper[kcol]=-1.0e50; |
4396 | columnGap[kcol] = -1.0e50; |
4397 | break; |
4398 | } |
4399 | } |
4400 | } |
4401 | } |
4402 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
4403 | notFeasible=1;; |
4404 | k=columnStart[jcol]+columnLength[jcol]; |
4405 | istackC=nstackC+1; |
4406 | break; |
4407 | } |
4408 | } |
4409 | } |
4410 | } |
4411 | } else if (doRowLoP) { |
4412 | |
4413 | for (int kk =rStart;kk<rEnd;kk++) { |
4414 | int kcol =column[kk]; |
4415 | if ((markC[kcol]&3)!=3) { |
4416 | double value2=rowElements[kk]; |
4417 | int markIt=markC[kcol]; |
4418 | assert (value2 > 0.0); |
4419 | |
4420 | double gap = columnGap[kcol]*value2; |
4421 | bool doDown = (rowLo2 +gap > 0.0); |
4422 | if (doDown&&(markIt&(2+8))==0) { |
4423 | double newLower=1.0; |
4424 | double dbound = colUpper[kcol] + rowLo2/value2; |
4425 | if (intVar[kcol]) { |
4426 | markIt |= 2; |
4427 | newLower = ceil(dbound-primalTolerance_); |
4428 | } else { |
4429 | newLower=dbound; |
4430 | if (newLower+primalTolerance_>colUpper[kcol]&& |
4431 | newLower-primalTolerance_<=colUpper[kcol]) { |
4432 | newLower=colUpper[kcol]; |
4433 | markIt |= 2; |
4434 | |
4435 | } else { |
4436 | |
4437 | markIt=3; |
4438 | } |
4439 | } |
4440 | double moveUp = newLower-colLower[kcol]; |
4441 | if (!moveUp) |
4442 | continue; |
4443 | bool onList = ((markC[kcol]&3)!=0); |
4444 | if (nstackC<2*maxStack) { |
4445 | markC[kcol] = markIt; |
4446 | } |
4447 | if (nstackC<2*maxStack) { |
4448 | fixThis++; |
4449 | if (!onList) { |
4450 | stackC[nstackC]=kcol; |
4451 | saveL[nstackC]=colLower[kcol]; |
4452 | saveU[nstackC]=colUpper[kcol]; |
4453 | assert (saveU[nstackC]>saveL[nstackC]); |
4454 | assert (nstackC<nCols); |
4455 | nstackC++; |
4456 | onList=true; |
4457 | } |
4458 | if (newLower>colsol[kcol]) { |
4459 | if (djs[kcol]<0.0) { |
4460 | |
4461 | assert (newLower>colUpper[kcol]+primalTolerance_); |
4462 | } else { |
4463 | objVal += moveUp*djs[kcol]; |
4464 | } |
4465 | } |
4466 | if (intVar[kcol]) |
4467 | newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4)); |
4468 | colLower[kcol]=newLower; |
4469 | columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_; |
4470 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
4471 | markC[kcol]=3; |
4472 | } |
4473 | markC[kcol] &= ~12; |
4474 | if (colUpper[kcol]>1.0e10) |
4475 | markC[kcol] |= 8; |
4476 | if (colLower[kcol]<-1.0e10) |
4477 | markC[kcol] |= 4; |
4478 | |
4479 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
4480 | int krow = row[jj]; |
4481 | double value = columnElements[jj]; |
4482 | assert (markR[krow]!=-2); |
4483 | if (markR[krow]==-1) { |
4484 | stackR[nstackR]=krow; |
4485 | markR[krow]=nstackR; |
4486 | saveMin[nstackR]=minR[krow]; |
4487 | saveMax[nstackR]=maxR[krow]; |
4488 | nstackR++; |
4489 | } |
4490 | |
4491 | |
4492 | if (value>0.0) { |
4493 | |
4494 | if (minR[krow]>-1.0e10) |
4495 | minR[krow] += value*moveUp; |
4496 | if (krow==irow) |
4497 | rowUp2 = rowUp-minR[irow]; |
4498 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
4499 | colUpper[kcol]=-1.0e50; |
4500 | columnGap[kcol] = -1.0e50; |
4501 | break; |
4502 | } |
4503 | } else { |
4504 | |
4505 | if (maxR[krow]<1.0e10) |
4506 | maxR[krow] += value*moveUp; |
4507 | if (krow==irow) |
4508 | rowLo2 = rowLo-maxR[irow]; |
4509 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
4510 | colUpper[kcol]=-1.0e50; |
4511 | columnGap[kcol] = -1.0e50; |
4512 | break; |
4513 | } |
4514 | } |
4515 | } |
4516 | } |
4517 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
4518 | notFeasible=1;; |
4519 | k=columnStart[jcol]+columnLength[jcol]; |
4520 | istackC=nstackC+1; |
4521 | break; |
4522 | } |
4523 | } |
4524 | } |
4525 | } |
4526 | } |
4527 | } |
4528 | istackC++; |
4529 | } |
4530 | if (!notFeasible) { |
4531 | if (objVal<=cutoff) { |
4532 | feasible |= feas[iway]; |
4533 | } else { |
4534 | #ifdef PRINT_DEBUG |
4535 | printf("not feasible on dj\n"); |
4536 | #endif |
4537 | notFeasible=1; |
4538 | if (iway==1&&feasible==0) { |
4539 | |
4540 | ninfeas=1; |
4541 | j=nCols-1; |
4542 | break; |
4543 | } |
4544 | } |
4545 | if (!notFeasible&&saveFixingInfo) { |
4546 | |
4547 | assert (j==stackC[0]); |
4548 | int toValue = (way[iway]==1) ? -1 : +1; |
4549 | for (istackC=1;istackC<nstackC;istackC++) { |
4550 | int icol=stackC[istackC]; |
4551 | |
4552 | if (colUpper[icol]-colLower[icol]<1.0e-12&&!saveL[istackC]&&saveU[istackC]==1.0) { |
4553 | assert(saveL[istackC]==colLower[icol]|| |
4554 | saveU[istackC]==colUpper[icol]); |
4555 | saveFixingInfo = info->fixes(j,toValue, |
4556 | icol,colLower[icol]==saveL[istackC]); |
4557 | } |
4558 | } |
4559 | } |
4560 | } else if (iway==1&&feasible==0) { |
4561 | |
4562 | ninfeas=1; |
4563 | j=nCols-1; |
4564 | iLook=numberThisTime_; |
4565 | ipass=maxPass; |
4566 | break; |
4567 | } |
4568 | if (notFeasible) |
4569 | goingToTrueBound=0; |
4570 | if (iway==2||(iway==1&&feasible==2)) { |
4571 | |
4572 | iway=3; |
4573 | nfixed++; |
4574 | OsiColCut cc; |
4575 | int nTot=0,nFix=0,nInt=0; |
4576 | bool ifCut=false; |
4577 | for (istackC=0;istackC<nstackC;istackC++) { |
4578 | int icol=stackC[istackC]; |
4579 | if (intVar[icol]) { |
4580 | if (colUpper[icol]<currentColUpper[icol]-1.0e-4) { |
4581 | element[nFix]=colUpper[icol]; |
4582 | index[nFix++]=icol; |
4583 | nInt++; |
4584 | if (colsol[icol]>colUpper[icol]+primalTolerance_) { |
4585 | ifCut=true; |
4586 | anyColumnCuts=true; |
4587 | } |
4588 | } |
4589 | } |
4590 | } |
4591 | if (nFix) { |
4592 | nTot=nFix; |
4593 | cc.setUbs(nFix,index,element); |
4594 | nFix=0; |
4595 | } |
4596 | for (istackC=0;istackC<nstackC;istackC++) { |
4597 | int icol=stackC[istackC]; |
4598 | if (intVar[icol]) { |
4599 | if (colLower[icol]>currentColLower[icol]+1.0e-4) { |
4600 | element[nFix]=colLower[icol]; |
4601 | index[nFix++]=icol; |
4602 | nInt++; |
4603 | if (colsol[icol]<colLower[icol]-primalTolerance_) { |
4604 | ifCut=true; |
4605 | anyColumnCuts=true; |
4606 | } |
4607 | } |
4608 | } |
4609 | } |
4610 | if (nFix) { |
4611 | nTot+=nFix; |
4612 | cc.setLbs(nFix,index,element); |
4613 | } |
4614 | |
4615 | if (nInt) { |
4616 | if (ifCut) { |
4617 | cc.setEffectiveness(100.0); |
4618 | } else { |
4619 | cc.setEffectiveness(1.0e-5); |
4620 | } |
4621 | #ifdef CGL_DEBUG |
4622 | checkBounds(debugger,cc); |
4623 | #endif |
4624 | cs.insert(cc); |
4625 | } |
4626 | for (istackC=0;istackC<nstackC;istackC++) { |
4627 | int icol=stackC[istackC]; |
4628 | if (colUpper[icol]-colLower[icol]>primalTolerance_) { |
4629 | markC[icol]&= ~3; |
4630 | } else { |
4631 | markC[icol]=3; |
4632 | } |
4633 | } |
4634 | for (istackR=0;istackR<nstackR;istackR++) { |
4635 | int irow=stackR[istackR]; |
4636 | markR[irow]=-1; |
4637 | } |
4638 | } else { |
4639 | |
4640 | |
4641 | if (iway==0) { |
4642 | nstackC0=CoinMin(nstackC,maxStack); |
4643 | double solMove = saveSolval-down; |
4644 | double boundChange; |
4645 | if (notFeasible) { |
4646 | nstackC0=0; |
4647 | } else { |
4648 | for (istackC=0;istackC<nstackC0;istackC++) { |
4649 | int icol=stackC[istackC]; |
4650 | stackC0[istackC]=icol; |
4651 | lo0[istackC]=colLower[icol]; |
4652 | up0[istackC]=colUpper[icol]; |
4653 | } |
4654 | } |
4655 | |
4656 | assert (iway==0); |
4657 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
4658 | int icol=stackC[istackC]; |
4659 | double oldU=saveU[istackC]; |
4660 | double oldL=saveL[istackC]; |
4661 | if(goingToTrueBound==2&&istackC&&!justReplace) { |
4662 | |
4663 | |
4664 | boundChange = oldU-colUpper[icol]; |
4665 | if (boundChange>0.0&&oldU<1.0e10&& |
4666 | (colsol[icol]>colUpper[icol] |
4667 | + boundChange*solMove+primalTolerance_)) { |
4668 | |
4669 | OsiRowCut rc; |
4670 | rc.setLb(-COIN_DBL_MAX); |
4671 | rc.setUb(colUpper[icol]-down*boundChange); |
4672 | index[0]=icol; |
4673 | element[0]=1.0; |
4674 | index[1]=j; |
4675 | element[1]= - boundChange; |
4676 | |
4677 | double newSol = (colsol[icol]-colUpper[icol])/ |
4678 | boundChange; |
4679 | assert(newSol>solMove); |
4680 | rc.setEffectiveness(newSol-solMove); |
4681 | if (rc.effectiveness()>disaggEffectiveness) { |
4682 | rc.setRow(2,index,element,false); |
4683 | #ifdef CGL_DEBUG |
4684 | if (debugger) assert(!debugger->invalidCut(rc)); |
4685 | #endif |
4686 | rowCut.addCutIfNotDuplicate(rc); |
4687 | } |
4688 | } |
4689 | |
4690 | |
4691 | boundChange = oldL-colLower[icol]; |
4692 | if (boundChange<0.0&&oldL>-1.0e10&& |
4693 | (colsol[icol]<colLower[icol] |
4694 | + boundChange*solMove-primalTolerance_)) { |
4695 | |
4696 | OsiRowCut rc; |
4697 | rc.setLb(colLower[icol]-down*boundChange); |
4698 | rc.setUb(COIN_DBL_MAX); |
4699 | index[0]=icol; |
4700 | element[0]=1.0; |
4701 | index[1]=j; |
4702 | element[1]=- boundChange; |
4703 | |
4704 | double newSol = (colsol[icol]-colLower[icol])/ |
4705 | boundChange; |
4706 | assert(newSol>solMove); |
4707 | rc.setEffectiveness(newSol-solMove); |
4708 | if (rc.effectiveness()>disaggEffectiveness) { |
4709 | rc.setRow(2,index,element,false); |
4710 | #ifdef CGL_DEBUG |
4711 | if (debugger) assert(!debugger->invalidCut(rc)); |
4712 | #endif |
4713 | rowCut.addCutIfNotDuplicate(rc); |
4714 | #if 0 |
4715 | printf("%d original bounds %g, %g new Lo %g sol= %g int %d sol= %g\n",icol,oldL,oldU,colLower[icol],colsol[icol], j, colsol[j]); |
4716 | printf("-1.0 * x(%d) + %g * y(%d) <= %g\n", |
4717 | icol,boundChange,j,rc.ub()); |
4718 | #endif |
4719 | } |
4720 | } |
4721 | } |
4722 | colUpper[icol]=oldU; |
4723 | colLower[icol]=oldL; |
4724 | columnGap[icol] = oldU-oldL-primalTolerance_; |
4725 | markC[icol]= 0; |
4726 | if (oldU>1.0e10) |
4727 | markC[icol] |= 8; |
4728 | if (oldL<-1.0e10) |
4729 | markC[icol] |= 4; |
4730 | } |
4731 | for (istackR=0;istackR<nstackR;istackR++) { |
4732 | int irow=stackR[istackR]; |
4733 | |
4734 | if ((rowCuts&2)!=0&&goingToTrueBound) { |
4735 | bool ifCut=anyColumnCuts; |
4736 | double gap = rowUpper[irow]-maxR[irow]; |
4737 | double sum=0.0; |
4738 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
4739 | |
4740 | |
4741 | |
4742 | |
4743 | #ifdef MOVE_SINGLETONS |
4744 | bool moveSingletons=true; |
4745 | #endif |
4746 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
4747 | kk++) { |
4748 | int iColumn = column[kk]; |
4749 | double value = rowElements[kk]; |
4750 | sum += value*colsol[iColumn]; |
4751 | #ifdef MOVE_SINGLETONS |
4752 | if (moveSingletons&&j!=iColumn) { |
4753 | if (colUpper[iColumn]>colLower[iColumn]) { |
4754 | if (columnLength2[iColumn]!=1) { |
4755 | moveSingletons=false; |
4756 | } |
4757 | } |
4758 | } |
4759 | #endif |
4760 | } |
4761 | #ifdef MOVE_SINGLETONS |
4762 | if (moveSingletons) { |
4763 | |
4764 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
4765 | kk++) { |
4766 | int iColumn = column[kk]; |
4767 | if (j!=iColumn) { |
4768 | if (colUpper[iColumn]>colLower[iColumn]) { |
4769 | if (columnLength2[iColumn]==1) { |
4770 | double value = rowElements[kk]; |
4771 | if (direction*objective[iColumn]*value<0.0&&!(markC[iColumn]&3)) { |
4772 | |
4773 | if (nstackC0+1<maxStack) { |
4774 | stackC0[nstackC0]=iColumn; |
4775 | if (value>0.0) { |
4776 | lo0[nstackC0]=colUpper[iColumn]; |
4777 | up0[nstackC0]=colUpper[iColumn]; |
4778 | } else { |
4779 | lo0[nstackC0]=colLower[iColumn]; |
4780 | up0[nstackC0]=colLower[iColumn]; |
4781 | } |
4782 | nstackC0++; |
4783 | } |
4784 | } |
4785 | } |
4786 | } |
4787 | } |
4788 | } |
4789 | } |
4790 | #endif |
4791 | if (sum-gap*colsol[j]>maxR[irow]+primalTolerance_||(info->strengthenRow&&rowLower[irow]<-1.0e20)) { |
4792 | |
4793 | |
4794 | |
4795 | int * index = reinterpret_cast<int *>(saveL); |
4796 | double * element = saveU; |
4797 | int n=0; |
4798 | bool coefficientExists=false; |
4799 | double sum2=0.0; |
4800 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
4801 | kk++) { |
4802 | int kColumn = column[kk]; |
4803 | double el = rowElements[kk]; |
4804 | if (kColumn!=j) { |
4805 | index[n]=kColumn; |
4806 | element[n++]=el; |
4807 | } else { |
4808 | el=el-gap; |
4809 | if (fabs(el)>1.0e-12) { |
4810 | index[n]=kColumn; |
4811 | element[n++]=el; |
4812 | } |
4813 | coefficientExists=true; |
4814 | } |
4815 | sum2 += colsol[kColumn]*el; |
4816 | } |
4817 | if (!coefficientExists) { |
4818 | index[n]=j; |
4819 | element[n++]=-gap; |
4820 | sum2 -= colsol[j]*gap; |
4821 | } |
4822 | OsiRowCut rc; |
4823 | rc.setLb(-COIN_DBL_MAX); |
4824 | double ub =rowUpper[irow]-gap*(colLower[j]+1.0); |
4825 | rc.setUb(ub); |
4826 | double effectiveness=sum2-ub; |
4827 | effectiveness = CoinMax(effectiveness, |
4828 | (sum-gap*colsol[j] |
4829 | -maxR[irow])/gap); |
4830 | if (!coefficientExists) |
4831 | effectiveness=CoinMax(1.0e-7, |
4832 | effectiveness); |
4833 | rc.setEffectiveness(effectiveness); |
4834 | |
4835 | if (rc.effectiveness()>needEffectiveness) { |
4836 | rc.setRow(n,index,element,false); |
4837 | #ifdef CGL_DEBUG |
4838 | if (debugger) assert(!debugger->invalidCut(rc)); |
4839 | #endif |
4840 | |
4841 | |
4842 | |
4843 | |
4844 | #ifdef STRENGTHEN_PRINT |
4845 | if (canReplace&&rowLower[irow]<-1.0e20) { |
4846 | printf("1Cut %g <= ",rc.lb()); |
4847 | int k; |
4848 | |
4849 | |
4850 | |
4851 | |
4852 | for ( k=0;k<n;k++) { |
4853 | int iColumn = index[k]; |
4854 | printf("%g*",element[k]); |
4855 | if (si.isInteger(iColumn)) |
4856 | printf("i%d ",iColumn); |
4857 | else |
4858 | printf("x%d ",iColumn); |
4859 | } |
4860 | printf("<= %g\n",rc.ub()); |
4861 | printf("Row %g <= ",rowLower[irow]); |
4862 | for (k=rowStart[irow];k<rowStart[irow+1];k++) { |
4863 | int iColumn = column[k]; |
4864 | printf("%g*",rowElements[k]); |
4865 | if (si.isInteger(iColumn)) |
4866 | printf("i%d ",iColumn); |
4867 | else |
4868 | printf("x%d ",iColumn); |
4869 | } |
4870 | printf("<= %g\n",rowUpper[irow]); |
4871 | } |
4872 | #endif |
4873 | int realRow = (canReplace&&rowLower[irow]<-1.0e20) ? irow : -1; |
4874 | if (realRows&&realRow>=0) |
4875 | realRow=realRows[realRow]; |
4876 | if (!justReplace) { |
4877 | rowCut.addCutIfNotDuplicate(rc,realRow); |
4878 | } else if (realRow>=0) { |
4879 | double effectiveness=0.0; |
4880 | for (int i=0;i<n;i++) |
4881 | effectiveness+=fabs(element[i]); |
4882 | if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) { |
4883 | delete info->strengthenRow[realRow]; |
4884 | rc.setEffectiveness(effectiveness); |
4885 | info->strengthenRow[realRow]=rc.clone(); |
4886 | } |
4887 | } |
4888 | } |
4889 | } |
4890 | } |
4891 | gap = minR[irow]-rowLower[irow]; |
4892 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
4893 | |
4894 | sum =0.0; |
4895 | |
4896 | #ifdef MOVE_SINGLETONS |
4897 | bool moveSingletons=true; |
4898 | #endif |
4899 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
4900 | kk++) { |
4901 | int iColumn = column[kk]; |
4902 | double value = rowElements[kk]; |
4903 | sum += value*colsol[iColumn]; |
4904 | #ifdef MOVE_SINGLETONS |
4905 | if (moveSingletons&&j!=iColumn) { |
4906 | if (colUpper[iColumn]>colLower[iColumn]) { |
4907 | if (columnLength2[iColumn]!=1) { |
4908 | moveSingletons=false; |
4909 | } |
4910 | } |
4911 | } |
4912 | #endif |
4913 | } |
4914 | #ifdef MOVE_SINGLETONS |
4915 | if (moveSingletons) { |
4916 | |
4917 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
4918 | kk++) { |
4919 | int iColumn = column[kk]; |
4920 | if (j!=iColumn) { |
4921 | if (colUpper[iColumn]>colLower[iColumn]) { |
4922 | if (columnLength2[iColumn]==1) { |
4923 | double value = rowElements[kk]; |
4924 | if (direction*objective[iColumn]*value>0.0&&!(markC[iColumn]&3)) { |
4925 | |
4926 | if (nstackC0+1<maxStack) { |
4927 | stackC0[nstackC0]=iColumn; |
4928 | if (value<0.0) { |
4929 | lo0[nstackC0]=colUpper[iColumn]; |
4930 | up0[nstackC0]=colUpper[iColumn]; |
4931 | } else { |
4932 | lo0[nstackC0]=colLower[iColumn]; |
4933 | up0[nstackC0]=colLower[iColumn]; |
4934 | } |
4935 | nstackC0++; |
4936 | } |
4937 | } |
4938 | } |
4939 | } |
4940 | } |
4941 | } |
4942 | } |
4943 | #endif |
4944 | if (sum+gap*colsol[j]<minR[irow]-primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) { |
4945 | |
4946 | |
4947 | |
4948 | int * index = reinterpret_cast<int *>(saveL); |
4949 | double * element = saveU; |
4950 | int n=0; |
4951 | bool coefficientExists=false; |
4952 | double sum2=0.0; |
4953 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
4954 | kk++) { |
4955 | int kColumn = column[kk]; |
4956 | double el = rowElements[kk]; |
4957 | if (kColumn!=j) { |
4958 | index[n]=kColumn; |
4959 | element[n++]=el; |
4960 | } else { |
4961 | el=el+gap; |
4962 | if (fabs(el)>1.0e-12) { |
4963 | index[n]=kColumn; |
4964 | element[n++]=el; |
4965 | } |
4966 | coefficientExists=true; |
4967 | } |
4968 | sum2 += colsol[kColumn]*el; |
4969 | } |
4970 | if (!coefficientExists) { |
4971 | index[n]=j; |
4972 | element[n++]=gap; |
4973 | sum2 += colsol[j]*gap; |
4974 | } |
4975 | OsiRowCut rc; |
4976 | double lb = rowLower[irow]+gap*(colLower[j]+1.0); |
4977 | rc.setLb(lb); |
4978 | rc.setUb(COIN_DBL_MAX); |
4979 | |
4980 | double effectiveness=lb-sum2; |
4981 | effectiveness = CoinMax(effectiveness, |
4982 | (minR[irow]- |
4983 | sum-gap*colsol[j])/gap); |
4984 | if (!coefficientExists) |
4985 | effectiveness=CoinMax(1.0e-7, |
4986 | effectiveness); |
4987 | rc.setEffectiveness(effectiveness); |
4988 | if (rc.effectiveness()>needEffectiveness) { |
4989 | rc.setRow(n,index,element,false); |
4990 | #ifdef CGL_DEBUG |
4991 | if (debugger) assert(!debugger->invalidCut(rc)); |
4992 | #endif |
4993 | |
4994 | |
4995 | #ifdef STRENGTHEN_PRINT |
4996 | if (canReplace&&rowUpper[irow]>1.0e20) { |
4997 | printf("2Cut %g <= ",rc.lb()); |
4998 | int k; |
4999 | for ( k=0;k<n;k++) { |
5000 | int iColumn = index[k]; |
5001 | printf("%g*",element[k]); |
5002 | if (si.isInteger(iColumn)) |
5003 | printf("i%d ",iColumn); |
5004 | else |
5005 | printf("x%d ",iColumn); |
5006 | } |
5007 | printf("<= %g\n",rc.ub()); |
5008 | printf("Row %g <= ",rowLower[irow]); |
5009 | for (k=rowStart[irow];k<rowStart[irow+1];k++) { |
5010 | int iColumn = column[k]; |
5011 | printf("%g*",rowElements[k]); |
5012 | if (si.isInteger(iColumn)) |
5013 | printf("i%d ",iColumn); |
5014 | else |
5015 | printf("x%d ",iColumn); |
5016 | } |
5017 | printf("<= %g\n",rowUpper[irow]); |
5018 | } |
5019 | #endif |
5020 | int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1; |
5021 | if (realRows&&realRow>=0) |
5022 | realRow=realRows[realRow]; |
5023 | if (!justReplace) { |
5024 | rowCut.addCutIfNotDuplicate(rc,realRow); |
5025 | } else if (realRow>=0) { |
5026 | double effectiveness=0.0; |
5027 | for (int i=0;i<n;i++) |
5028 | effectiveness+=fabs(element[i]); |
5029 | if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) { |
5030 | delete info->strengthenRow[realRow]; |
5031 | rc.setEffectiveness(effectiveness); |
5032 | info->strengthenRow[realRow]=rc.clone(); |
5033 | } |
5034 | } |
5035 | } |
5036 | } |
5037 | } |
5038 | } |
5039 | minR[irow]=saveMin[istackR]; |
5040 | maxR[irow]=saveMax[istackR]; |
5041 | markR[irow]=-1; |
5042 | } |
5043 | } else { |
5044 | if (iway==1&&feasible==3) { |
5045 | iway=3; |
5046 | #ifdef MOVE_SINGLETONS |
5047 | |
5048 | if ((rowCuts&2)!=0&&goingToTrueBound&&info->strengthenRow) { |
5049 | for (istackR=0;istackR<nstackR;istackR++) { |
5050 | int irow=stackR[istackR]; |
5051 | double gap = rowUpper[irow]-maxR[irow]; |
5052 | if (gap>primalTolerance_) { |
5053 | |
5054 | bool moveSingletons=true; |
5055 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5056 | kk++) { |
5057 | int iColumn = column[kk]; |
5058 | if (moveSingletons&&j!=iColumn) { |
5059 | if (colUpper[iColumn]>colLower[iColumn]) { |
5060 | if (columnLength2[iColumn]!=1) { |
5061 | moveSingletons=false; |
5062 | } |
5063 | } |
5064 | } |
5065 | } |
5066 | if (moveSingletons) { |
5067 | |
5068 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5069 | kk++) { |
5070 | int iColumn = column[kk]; |
5071 | if (j!=iColumn) { |
5072 | if (colUpper[iColumn]>colLower[iColumn]) { |
5073 | if (columnLength2[iColumn]==1) { |
5074 | double value = rowElements[kk]; |
5075 | if (direction*objective[iColumn]*value<0.0&&!(markC[iColumn]&3)) { |
5076 | |
5077 | stackC[nstackC]=iColumn; |
5078 | saveL[nstackC]=colLower[iColumn]; |
5079 | saveU[nstackC]=colUpper[iColumn]; |
5080 | assert (saveU[nstackC]>saveL[nstackC]); |
5081 | if (value>0.0) { |
5082 | colLower[iColumn]=colUpper[iColumn]; |
5083 | } else { |
5084 | colUpper[iColumn]=colLower[iColumn]; |
5085 | } |
5086 | columnGap[iColumn] = -primalTolerance_; |
5087 | assert (nstackC<nCols); |
5088 | nstackC++; |
5089 | } |
5090 | } |
5091 | } |
5092 | } |
5093 | } |
5094 | } |
5095 | } |
5096 | gap = minR[irow]-rowLower[irow]; |
5097 | if (gap>primalTolerance_) { |
5098 | |
5099 | bool moveSingletons=true; |
5100 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5101 | kk++) { |
5102 | int iColumn = column[kk]; |
5103 | if (moveSingletons&&j!=iColumn) { |
5104 | if (colUpper[iColumn]>colLower[iColumn]) { |
5105 | if (columnLength2[iColumn]!=1) { |
5106 | moveSingletons=false; |
5107 | } |
5108 | } |
5109 | } |
5110 | } |
5111 | if (moveSingletons) { |
5112 | |
5113 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5114 | kk++) { |
5115 | int iColumn = column[kk]; |
5116 | if (j!=iColumn) { |
5117 | if (colUpper[iColumn]>colLower[iColumn]) { |
5118 | if (columnLength2[iColumn]==1) { |
5119 | double value = rowElements[kk]; |
5120 | if (direction*objective[iColumn]*value>0.0&&!(markC[iColumn]&3)) { |
5121 | |
5122 | stackC[nstackC]=iColumn; |
5123 | saveL[nstackC]=colLower[iColumn]; |
5124 | saveU[nstackC]=colUpper[iColumn]; |
5125 | assert (saveU[nstackC]>saveL[nstackC]); |
5126 | if (value<0.0) { |
5127 | colLower[iColumn]=colUpper[iColumn]; |
5128 | } else { |
5129 | colUpper[iColumn]=colLower[iColumn]; |
5130 | } |
5131 | columnGap[iColumn] = -primalTolerance_; |
5132 | assert (nstackC<nCols); |
5133 | nstackC++; |
5134 | } |
5135 | } |
5136 | } |
5137 | } |
5138 | } |
5139 | } |
5140 | } |
5141 | } |
5142 | } |
5143 | #endif |
5144 | |
5145 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
5146 | int icol=stackC[istackC]; |
5147 | markC[icol]=istackC+1000; |
5148 | } |
5149 | OsiColCut cc; |
5150 | int nTot=0,nFix=0,nInt=0; |
5151 | bool ifCut=false; |
5152 | for (istackC=1;istackC<nstackC0;istackC++) { |
5153 | int icol=stackC0[istackC]; |
5154 | int istackC1=markC[icol]-1000; |
5155 | if (istackC1>=0) { |
5156 | if (CoinMin(lo0[istackC],colLower[icol])>saveL[istackC1]+1.0e-4) { |
5157 | saveL[istackC1]=CoinMin(lo0[istackC],colLower[icol]); |
5158 | if (intVar[icol]) { |
5159 | element[nFix]=saveL[istackC1]; |
5160 | index[nFix++]=icol; |
5161 | nInt++; |
5162 | if (colsol[icol]<saveL[istackC1]-primalTolerance_) |
5163 | ifCut=true; |
5164 | } |
5165 | nfixed++; |
5166 | } |
5167 | } |
5168 | } |
5169 | if (nFix) { |
5170 | nTot=nFix; |
5171 | cc.setLbs(nFix,index,element); |
5172 | nFix=0; |
5173 | } |
5174 | for (istackC=1;istackC<nstackC0;istackC++) { |
5175 | int icol=stackC0[istackC]; |
5176 | int istackC1=markC[icol]-1000; |
5177 | if (istackC1>=0) { |
5178 | if (CoinMax(up0[istackC],colUpper[icol])<saveU[istackC1]-1.0e-4) { |
5179 | saveU[istackC1]=CoinMax(up0[istackC],colUpper[icol]); |
5180 | if (intVar[icol]) { |
5181 | element[nFix]=saveU[istackC1]; |
5182 | index[nFix++]=icol; |
5183 | nInt++; |
5184 | if (colsol[icol]>saveU[istackC1]+primalTolerance_) |
5185 | ifCut=true; |
5186 | } |
5187 | nfixed++; |
5188 | } else if (!info->inTree&&saveL[0]==0.0&&saveU[0]==1.0) { |
5189 | |
5190 | double upperWhenDown = up0[istackC]; |
5191 | double lowerWhenDown = lo0[istackC]; |
5192 | double upperWhenUp = colUpper[icol]; |
5193 | double lowerWhenUp = colLower[icol]; |
5194 | double upperOriginal = saveU[istackC1]; |
5195 | double lowerOriginal = saveL[istackC1]; |
5196 | if (upperWhenDown<lowerOriginal+1.0e-12&&lowerWhenUp>upperOriginal-1.0e-12) { |
5197 | OsiRowCut rc; |
5198 | rc.setLb(lowerOriginal); |
5199 | rc.setUb(lowerOriginal); |
5200 | rc.setEffectiveness(1.0e-5); |
5201 | int index[2]; |
5202 | double element[2]; |
5203 | index[0]=j; |
5204 | index[1]=icol; |
5205 | element[0]=-(upperOriginal-lowerOriginal); |
5206 | |
5207 | if (fabs(element[0])>1.0e-8) { |
5208 | element[1]=1.0; |
5209 | rc.setRow(2,index,element,false); |
5210 | cs.insert(rc); |
5211 | } |
5212 | } else if (upperWhenUp<lowerOriginal+1.0e-12&&lowerWhenDown>upperOriginal-1.0e-12) { |
5213 | OsiRowCut rc; |
5214 | rc.setLb(upperOriginal); |
5215 | rc.setUb(upperOriginal); |
5216 | rc.setEffectiveness(1.0e-5); |
5217 | int index[2]; |
5218 | double element[2]; |
5219 | index[0]=j; |
5220 | index[1]=icol; |
5221 | element[0]=upperOriginal-lowerOriginal; |
5222 | element[1]=1.0; |
5223 | rc.setRow(2,index,element,false); |
5224 | cs.insert(rc); |
5225 | } |
5226 | } |
5227 | } |
5228 | } |
5229 | if (nFix) { |
5230 | nTot+=nFix; |
5231 | cc.setUbs(nFix,index,element); |
5232 | } |
5233 | |
5234 | if (nInt) { |
5235 | if (ifCut) { |
5236 | cc.setEffectiveness(100.0); |
5237 | } else { |
5238 | cc.setEffectiveness(1.0e-5); |
5239 | } |
5240 | #ifdef CGL_DEBUG |
5241 | checkBounds(debugger,cc); |
5242 | #endif |
5243 | cs.insert(cc); |
5244 | } |
5245 | } else { |
5246 | goingToTrueBound=0; |
5247 | } |
5248 | double solMove = up-saveSolval; |
5249 | double boundChange; |
5250 | |
5251 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
5252 | int icol=stackC[istackC]; |
5253 | double oldU=saveU[istackC]; |
5254 | double oldL=saveL[istackC]; |
5255 | if(goingToTrueBound==2&&istackC&&!justReplace) { |
5256 | |
5257 | |
5258 | boundChange = oldU-colUpper[icol]; |
5259 | if (boundChange>0.0&&oldU<1.0e10&& |
5260 | (colsol[icol]>colUpper[icol] |
5261 | + boundChange*solMove+primalTolerance_)) { |
5262 | |
5263 | OsiRowCut rc; |
5264 | rc.setLb(-COIN_DBL_MAX); |
5265 | rc.setUb(colUpper[icol]+up*boundChange); |
5266 | index[0]=icol; |
5267 | element[0]=1.0; |
5268 | index[1]=j; |
5269 | element[1]= + boundChange; |
5270 | |
5271 | double newSol = (colsol[icol]-colUpper[icol])/ |
5272 | boundChange; |
5273 | assert(newSol>solMove); |
5274 | rc.setEffectiveness(newSol-solMove); |
5275 | if (rc.effectiveness()>disaggEffectiveness) { |
5276 | rc.setRow(2,index,element,false); |
5277 | #ifdef CGL_DEBUG |
5278 | if (debugger) assert(!debugger->invalidCut(rc)); |
5279 | #endif |
5280 | rowCut.addCutIfNotDuplicate(rc); |
5281 | } |
5282 | } |
5283 | |
5284 | |
5285 | boundChange = oldL-colLower[icol]; |
5286 | if (boundChange<0.0&&oldL>-1.0e10&& |
5287 | (colsol[icol]<colLower[icol] |
5288 | + boundChange*solMove-primalTolerance_)) { |
5289 | |
5290 | OsiRowCut rc; |
5291 | rc.setLb(colLower[icol]+up*boundChange); |
5292 | rc.setUb(COIN_DBL_MAX); |
5293 | index[0]=icol; |
5294 | element[0]=1.0; |
5295 | index[1]=j; |
5296 | element[1]= + boundChange; |
5297 | |
5298 | double newSol = (colsol[icol]-colLower[icol])/ |
5299 | boundChange; |
5300 | assert(newSol>solMove); |
5301 | rc.setEffectiveness(newSol-solMove); |
5302 | if (rc.effectiveness()>disaggEffectiveness) { |
5303 | rc.setRow(2,index,element,false); |
5304 | #ifdef CGL_DEBUG |
5305 | if (debugger) assert(!debugger->invalidCut(rc)); |
5306 | #endif |
5307 | rowCut.addCutIfNotDuplicate(rc); |
5308 | } |
5309 | } |
5310 | } |
5311 | colUpper[icol]=oldU; |
5312 | colLower[icol]=oldL; |
5313 | columnGap[icol] = oldU-oldL-primalTolerance_; |
5314 | if (oldU>oldL+1.0e-4) { |
5315 | markC[icol]=0; |
5316 | if (oldU>1.0e10) |
5317 | markC[icol] |= 8; |
5318 | if (oldL<-1.0e10) |
5319 | markC[icol] |= 4; |
5320 | } else { |
5321 | markC[icol]=3; |
5322 | } |
5323 | } |
5324 | for (istackR=0;istackR<nstackR;istackR++) { |
5325 | int irow=stackR[istackR]; |
5326 | |
5327 | if ((rowCuts&2)!=0&&goingToTrueBound) { |
5328 | bool canReplace = info->strengthenRow&&(goingToTrueBound==2); |
5329 | bool ifCut=anyColumnCuts; |
5330 | double gap = rowUpper[irow]-maxR[irow]; |
5331 | double sum=0.0; |
5332 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
5333 | |
5334 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5335 | kk++) { |
5336 | sum += rowElements[kk]*colsol[column[kk]]; |
5337 | } |
5338 | if (sum+gap*colsol[j]>rowUpper[irow]+primalTolerance_||(canReplace&&rowLower[irow]<-1.e20)) { |
5339 | |
5340 | |
5341 | |
5342 | int * index = reinterpret_cast<int *>(saveL); |
5343 | double * element = saveU; |
5344 | int n=0; |
5345 | bool coefficientExists=false; |
5346 | double sum2=0.0; |
5347 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5348 | kk++) { |
5349 | int kColumn = column[kk]; |
5350 | double el = rowElements[kk]; |
5351 | if (kColumn!=j) { |
5352 | index[n]=kColumn; |
5353 | element[n++]=el; |
5354 | } else { |
5355 | el=el+gap; |
5356 | if (fabs(el)>1.0e-12) { |
5357 | index[n]=kColumn; |
5358 | element[n++]=el; |
5359 | } |
5360 | coefficientExists=true; |
5361 | } |
5362 | sum2 += colsol[kColumn]*el; |
5363 | } |
5364 | if (!coefficientExists) { |
5365 | index[n]=j; |
5366 | element[n++]=gap; |
5367 | sum2 += colsol[j]*gap; |
5368 | } |
5369 | OsiRowCut rc; |
5370 | rc.setLb(-COIN_DBL_MAX); |
5371 | double ub = rowUpper[irow]+gap*(colUpper[j]-1.0); |
5372 | rc.setUb(ub); |
5373 | |
5374 | double effectiveness=sum2-ub; |
5375 | effectiveness = CoinMax(effectiveness, |
5376 | (sum+gap*colsol[j]- |
5377 | rowUpper[irow])/gap); |
5378 | if (!coefficientExists) |
5379 | effectiveness=CoinMax(1.0e-7, |
5380 | effectiveness); |
5381 | rc.setEffectiveness(effectiveness); |
5382 | if (rc.effectiveness()>needEffectiveness) { |
5383 | rc.setRow(n,index,element,false); |
5384 | #ifdef CGL_DEBUG |
5385 | if (debugger) assert(!debugger->invalidCut(rc)); |
5386 | #endif |
5387 | |
5388 | |
5389 | #ifdef STRENGTHEN_PRINT |
5390 | if (canReplace&&rowLower[irow]<-1.0e20) { |
5391 | printf("3Cut %g <= ",rc.lb()); |
5392 | int k; |
5393 | for ( k=0;k<n;k++) { |
5394 | int iColumn = index[k]; |
5395 | printf("%g*",element[k]); |
5396 | if (si.isInteger(iColumn)) |
5397 | printf("i%d ",iColumn); |
5398 | else |
5399 | printf("x%d ",iColumn); |
5400 | } |
5401 | printf("<= %g\n",rc.ub()); |
5402 | printf("Row %g <= ",rowLower[irow]); |
5403 | for (k=rowStart[irow];k<rowStart[irow+1];k++) { |
5404 | int iColumn = column[k]; |
5405 | printf("%g*",rowElements[k]); |
5406 | if (si.isInteger(iColumn)) |
5407 | printf("i%d ",iColumn); |
5408 | else |
5409 | printf("x%d ",iColumn); |
5410 | } |
5411 | printf("<= %g\n",rowUpper[irow]); |
5412 | } |
5413 | #endif |
5414 | int realRow = (canReplace&&rowLower[irow]<-1.0e20) ? irow : -1; |
5415 | if (realRows&&realRow>=0) |
5416 | realRow=realRows[realRow]; |
5417 | if (!justReplace) { |
5418 | rowCut.addCutIfNotDuplicate(rc,realRow); |
5419 | } else if (realRow>=0) { |
5420 | double effectiveness=0.0; |
5421 | for (int i=0;i<n;i++) |
5422 | effectiveness+=fabs(element[i]); |
5423 | if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) { |
5424 | delete info->strengthenRow[realRow]; |
5425 | rc.setEffectiveness(effectiveness); |
5426 | info->strengthenRow[realRow]=rc.clone(); |
5427 | } |
5428 | } |
5429 | } |
5430 | } |
5431 | } |
5432 | gap = minR[irow]-rowLower[irow]; |
5433 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
5434 | |
5435 | if (!sum) { |
5436 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5437 | kk++) { |
5438 | sum += rowElements[kk]*colsol[column[kk]]; |
5439 | } |
5440 | } |
5441 | if (sum-gap*colsol[j]<rowLower[irow]-primalTolerance_||(canReplace&&rowUpper[irow]>1.0e20)) { |
5442 | |
5443 | |
5444 | |
5445 | int * index = reinterpret_cast<int *>(saveL); |
5446 | double * element = saveU; |
5447 | int n=0; |
5448 | bool coefficientExists=false; |
5449 | double sum2=0.0; |
5450 | for (int kk =rowStart[irow];kk<rowStart[irow+1]; |
5451 | kk++) { |
5452 | int kColumn = column[kk]; |
5453 | double el = rowElements[kk]; |
5454 | if (kColumn!=j) { |
5455 | index[n]=kColumn; |
5456 | element[n++]=el; |
5457 | } else { |
5458 | el=el-gap; |
5459 | if (fabs(el)>1.0e-12) { |
5460 | index[n]=kColumn; |
5461 | element[n++]=el; |
5462 | } |
5463 | coefficientExists=true; |
5464 | } |
5465 | sum2 += colsol[kColumn]*el; |
5466 | } |
5467 | if (!coefficientExists) { |
5468 | index[n]=j; |
5469 | element[n++]=-gap; |
5470 | sum2 -= colsol[j]*gap; |
5471 | } |
5472 | OsiRowCut rc; |
5473 | double lb = rowLower[irow]-gap*(colUpper[j]-1); |
5474 | rc.setLb(lb); |
5475 | rc.setUb(COIN_DBL_MAX); |
5476 | double effectiveness=lb-sum2; |
5477 | effectiveness = CoinMax(effectiveness, |
5478 | (rowLower[irow]- |
5479 | sum+gap*colsol[j])/gap); |
5480 | if (!coefficientExists) |
5481 | effectiveness=CoinMax(1.0e-7, |
5482 | effectiveness); |
5483 | rc.setEffectiveness(effectiveness); |
5484 | if (rc.effectiveness()>needEffectiveness) { |
5485 | rc.setRow(n,index,element,false); |
5486 | #ifdef CGL_DEBUG |
5487 | if (debugger) assert(!debugger->invalidCut(rc)); |
5488 | #endif |
5489 | |
5490 | |
5491 | #ifdef STRENGTHEN_PRINT |
5492 | if (canReplace&&rowUpper[irow]>1.0e20) { |
5493 | printf("4Cut %g <= ",rc.lb()); |
5494 | int k; |
5495 | for ( k=0;k<n;k++) { |
5496 | int iColumn = index[k]; |
5497 | printf("%g*",element[k]); |
5498 | if (si.isInteger(iColumn)) |
5499 | printf("i%d ",iColumn); |
5500 | else |
5501 | printf("x%d ",iColumn); |
5502 | } |
5503 | printf("<= %g\n",rc.ub()); |
5504 | printf("Row %g <= ",rowLower[irow]); |
5505 | for (k=rowStart[irow];k<rowStart[irow+1];k++) { |
5506 | int iColumn = column[k]; |
5507 | printf("%g*",rowElements[k]); |
5508 | if (si.isInteger(iColumn)) |
5509 | printf("i%d ",iColumn); |
5510 | else |
5511 | printf("x%d ",iColumn); |
5512 | } |
5513 | printf("<= %g\n",rowUpper[irow]); |
5514 | } |
5515 | #endif |
5516 | int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1; |
5517 | if (realRows&&realRow>=0) |
5518 | realRow=realRows[realRow]; |
5519 | if (!justReplace) { |
5520 | rowCut.addCutIfNotDuplicate(rc,realRow); |
5521 | } else if (realRow>=0) { |
5522 | double effectiveness=0.0; |
5523 | for (int i=0;i<n;i++) |
5524 | effectiveness+=fabs(element[i]); |
5525 | if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) { |
5526 | delete info->strengthenRow[realRow]; |
5527 | rc.setEffectiveness(effectiveness); |
5528 | info->strengthenRow[realRow]=rc.clone(); |
5529 | } |
5530 | } |
5531 | } |
5532 | } |
5533 | } |
5534 | } |
5535 | minR[irow]=saveMin[istackR]; |
5536 | maxR[irow]=saveMax[istackR]; |
5537 | markR[irow]=-1; |
5538 | } |
5539 | } |
5540 | } |
5541 | } |
5542 | } |
5543 | } |
5544 | if ((!ninfeas&&!rowCut.outOfSpace())&&(info->strengthenRow|| |
5545 | !rowCut.numberCuts())&&rowCuts) { |
5546 | |
5547 | for (int i = 0; i < nRowsSafe; ++i) { |
5548 | if ((rowLower[i]>-1.0e20||rowUpper[i]<1.0e20)&& |
5549 | (!info->strengthenRow||!info->strengthenRow[i])) { |
5550 | int iflagu = 0; |
5551 | int iflagl = 0; |
5552 | double dmaxup = 0.0; |
5553 | double dmaxdown = 0.0; |
5554 | int krs = rowStart[i]; |
5555 | int kre = rowStart[i+1]; |
5556 | int kInt = -1; |
5557 | double rhsAdjustment=0.0; |
5558 | int nPosInt=0; |
5559 | int nNegInt=0; |
5560 | double valueInteger=0.0; |
5561 | |
5562 | int k; |
5563 | for ( k = krs; k < kre; ++k) { |
5564 | int j = column[k]; |
5565 | if (intVar[j]) { |
5566 | double value=rowElements[k]; |
5567 | if (colUpper[j]>colLower[j]&&!colLower[j]&& |
5568 | fabs(value)>fabs(valueInteger)) { |
5569 | kInt=j; |
5570 | valueInteger=value; |
5571 | } |
5572 | } |
5573 | } |
5574 | if (kInt>=0) { |
5575 | double upperBound = CoinMin(colUpper[kInt],static_cast<double>(COIN_INT_MAX)); |
5576 | double upAdjust=0.0; |
5577 | double downAdjust=0.0; |
5578 | for (k = krs; k < kre; ++k) { |
5579 | double value=rowElements[k]; |
5580 | int j = column[k]; |
5581 | if (colUpper[j]==colLower[j]) { |
5582 | rhsAdjustment += colUpper[j]*value; |
5583 | continue; |
5584 | } |
5585 | if (intVar[j]) { |
5586 | if (value>0.0) |
5587 | nPosInt++; |
5588 | else |
5589 | nNegInt++; |
5590 | } else { |
5591 | nPosInt = -nCols; |
5592 | } |
5593 | if (j!=kInt) { |
5594 | |
5595 | if (value > 0.0) { |
5596 | if (colUpper[j] >= 1e15) { |
5597 | dmaxup = 1e31; |
5598 | ++iflagu; |
5599 | } else { |
5600 | dmaxup += colUpper[j] * value; |
5601 | } |
5602 | if (colLower[j] <= -1e15) { |
5603 | dmaxdown = -1e31; |
5604 | ++iflagl; |
5605 | } else { |
5606 | dmaxdown += colLower[j] * value; |
5607 | } |
5608 | } else if (value<0.0) { |
5609 | if (colUpper[j] >= 1e15) { |
5610 | dmaxdown = -1e31; |
5611 | ++iflagl; |
5612 | } else { |
5613 | dmaxdown += colUpper[j] * value; |
5614 | } |
5615 | if (colLower[j] <= -1e15) { |
5616 | dmaxup = 1e31; |
5617 | ++iflagu; |
5618 | } else { |
5619 | dmaxup += colLower[j] * value; |
5620 | } |
5621 | } |
5622 | } else { |
5623 | |
5624 | if (value > 0.0) { |
5625 | if (colUpper[j] >= 1e15) { |
5626 | upAdjust = 1e31; |
5627 | } else { |
5628 | upAdjust = colUpper[j] * value; |
5629 | } |
5630 | if (colLower[j] <= -1e15) { |
5631 | downAdjust = -1e31; |
5632 | } else { |
5633 | downAdjust = colLower[j] * value; |
5634 | } |
5635 | } else if (value<0.0) { |
5636 | if (colUpper[j] >= 1e15) { |
5637 | downAdjust = -1e31; |
5638 | } else { |
5639 | downAdjust = colUpper[j] * value; |
5640 | } |
5641 | if (colLower[j] <= -1e15) { |
5642 | upAdjust = 1e31; |
5643 | } else { |
5644 | upAdjust = colLower[j] * value; |
5645 | } |
5646 | } |
5647 | } |
5648 | } |
5649 | dmaxup += rhsAdjustment; |
5650 | dmaxdown += rhsAdjustment; |
5651 | |
5652 | if (iflagu) |
5653 | dmaxup=1.0e31; |
5654 | if (iflagl) |
5655 | dmaxdown=-1.0e31; |
5656 | |
5657 | if (dmaxdown+downAdjust>rowLower[i]-tolerance&& |
5658 | dmaxup+upAdjust<rowUpper[i]+tolerance) |
5659 | continue; |
5660 | if (dmaxdown+valueInteger*upperBound>rowLower[i]&& |
5661 | dmaxup+valueInteger*upperBound<rowUpper[i]) { |
5662 | |
5663 | if (dmaxdown+valueInteger>rowLower[i]&&dmaxup+valueInteger<rowUpper[i]&& |
5664 | (dmaxdown<rowLower[i]-primalTolerance_||dmaxup>rowUpper[i]+primalTolerance_)) { |
5665 | |
5666 | double saveValue = valueInteger; |
5667 | if (valueInteger>0.0) { |
5668 | assert (dmaxdown<rowLower[i]); |
5669 | valueInteger = rowLower[i]-dmaxdown; |
5670 | } else { |
5671 | assert (dmaxup>rowUpper[i]); |
5672 | valueInteger = rowUpper[i]-dmaxup; |
5673 | } |
5674 | if (fabs(saveValue-valueInteger)>1.0e-12) { |
5675 | |
5676 | OsiRowCut rc; |
5677 | rc.setLb(rowLower[i]); |
5678 | rc.setUb(rowUpper[i]); |
5679 | int n=0; |
5680 | double sum=0.0; |
5681 | for (int kk=rowStart[i];kk<rowStart[i+1];kk++) { |
5682 | int j=column[kk]; |
5683 | if (j!=kInt) { |
5684 | sum += colsol[j]*rowElements[kk]; |
5685 | index[n]=j; |
5686 | element[n++]=rowElements[kk]; |
5687 | } else { |
5688 | sum += colsol[j]*valueInteger; |
5689 | assert (rowElements[kk]*valueInteger>=0.0); |
5690 | #if 0 |
5691 | if (fabs(rowElements[kk])>1.01*fabs(valueInteger)) { |
5692 | printf("row %d changing coefficient of %d from %g to %g\n", |
5693 | i,kInt,rowElements[kk],valueInteger); |
5694 | } |
5695 | #endif |
5696 | if (fabs(valueInteger)>1.0e-12) { |
5697 | index[n]=column[kk]; |
5698 | element[n++]=valueInteger; |
5699 | } |
5700 | } |
5701 | } |
5702 | double gap = 0.0; |
5703 | if (sum<rowLower[i]) |
5704 | gap=rowLower[i]-sum; |
5705 | else if (sum>rowUpper[i]) |
5706 | gap=sum-rowUpper[i]; |
5707 | if (gap>1.0e-4||info->strengthenRow!=NULL) { |
5708 | gap += 1.0e5; |
5709 | rc.setEffectiveness(gap); |
5710 | rc.setRow(n,index,element,false); |
5711 | #ifdef STRENGTHEN_PRINT |
5712 | { |
5713 | printf("1aCut %g <= ",rc.lb()); |
5714 | int irow =i; |
5715 | int k; |
5716 | for ( k=0;k<n;k++) { |
5717 | int iColumn = index[k]; |
5718 | printf("%g*",element[k]); |
5719 | if (si.isInteger(iColumn)) |
5720 | printf("i%d ",iColumn); |
5721 | else |
5722 | printf("x%d ",iColumn); |
5723 | } |
5724 | printf("<= %g\n",rc.ub()); |
5725 | printf("Row %g <= ",rowLower[irow]); |
5726 | for (k=rowStart[irow];k<rowStart[irow+1];k++) { |
5727 | int iColumn = column[k]; |
5728 | printf("%g*",rowElements[k]); |
5729 | if (si.isInteger(iColumn)) |
5730 | printf("i%d ",iColumn); |
5731 | else |
5732 | printf("x%d ",iColumn); |
5733 | } |
5734 | printf("<= %g\n",rowUpper[irow]); |
5735 | } |
5736 | #endif |
5737 | int returnCode=rowCut.addCutIfNotDuplicate(rc,i); |
5738 | if (returnCode<0) |
5739 | break; |
5740 | } |
5741 | } |
5742 | } |
5743 | } |
5744 | } |
5745 | } |
5746 | } |
5747 | } |
5748 | #ifndef ONE_ARRAY |
5749 | delete [] stackC0; |
5750 | delete [] lo0; |
5751 | delete [] up0; |
5752 | delete [] columnGap; |
5753 | delete [] markC; |
5754 | delete [] stackC; |
5755 | delete [] stackR; |
5756 | delete [] saveL; |
5757 | delete [] saveU; |
5758 | delete [] saveMin; |
5759 | delete [] saveMax; |
5760 | delete [] index; |
5761 | delete [] element; |
5762 | delete [] djs; |
5763 | delete [] largestPositiveInRow; |
5764 | delete [] largestNegativeInRow; |
5765 | #endif |
5766 | delete [] colsol; |
5767 | |
5768 | if (!ninfeas) { |
5769 | if (!justReplace) { |
5770 | rowCut.addCuts(cs,info->strengthenRow,info->pass); |
5771 | } else { |
5772 | for (int i=0;i<nRows;i++) { |
5773 | int realRow=realRows[i]; |
5774 | if (realRow>=0) { |
5775 | OsiRowCut * cut = info->strengthenRow[realRow]; |
5776 | if (cut) { |
5777 | #ifdef CLP_INVESTIGATE |
5778 | printf("Row %d, real row %d effectiveness %g\n",i,realRow,cut->effectiveness()); |
5779 | #endif |
5780 | cs.insert(cut); |
5781 | } |
5782 | } |
5783 | } |
5784 | } |
5785 | } |
5786 | #if 0 |
5787 | { |
5788 | int numberRowCutsAfter = cs.sizeRowCuts() ; |
5789 | int k ; |
5790 | for (k = 0;k<numberRowCutsAfter;k++) { |
5791 | OsiRowCut thisCut = cs.rowCut(k) ; |
5792 | printf("Cut %d is %g <=",k,thisCut.lb()); |
5793 | int n=thisCut.row().getNumElements(); |
5794 | const int * column = thisCut.row().getIndices(); |
5795 | const double * element = thisCut.row().getElements(); |
5796 | assert (n); |
5797 | for (int i=0;i<n;i++) { |
5798 | printf(" %g*x%d",element[i],column[i]); |
5799 | } |
5800 | printf(" <= %g\n",thisCut.ub()); |
5801 | } |
5802 | } |
5803 | #endif |
5804 | return (ninfeas); |
5805 | } |
5806 | |
5807 | int CglProbing::probeCliques( const OsiSolverInterface & si, |
5808 | const OsiRowCutDebugger * |
5809 | #ifdef CGL_DEBUG |
5810 | debugger |
5811 | #endif |
5812 | ,OsiCuts & cs, |
5813 | double * colLower, double * colUpper, |
5814 | CoinPackedMatrix *rowCopy, |
5815 | CoinPackedMatrix *columnCopy, const int * realRows, |
5816 | double * rowLower, double * rowUpper, |
5817 | char * intVar, double * minR, double * maxR, |
5818 | int * markR, |
5819 | CglTreeInfo * info) |
5820 | { |
5821 | |
5822 | int maxStack = info->inTree ? maxStack_ : maxStackRoot_; |
5823 | int nRows=rowCopy->getNumRows(); |
5824 | int nCols=rowCopy->getNumCols(); |
5825 | double * colsol = new double[nCols]; |
5826 | double * djs = new double[nCols]; |
5827 | const double * currentColLower = si.getColLower(); |
5828 | const double * currentColUpper = si.getColUpper(); |
5829 | double * tempL = new double [nCols]; |
5830 | double * tempU = new double [nCols]; |
5831 | int * markC = new int [nCols]; |
5832 | int * stackC = new int [2*nCols]; |
5833 | int * stackR = new int [nRows]; |
5834 | double * saveL = new double [2*nCols]; |
5835 | double * saveU = new double [2*nCols]; |
5836 | double * saveMin = new double [nRows]; |
5837 | double * saveMax = new double [nRows]; |
5838 | double * element = new double[nCols]; |
5839 | int * index = new int[nCols]; |
5840 | |
5841 | int * cliqueStack=NULL; |
5842 | int * cliqueCount=NULL; |
5843 | int * to_01=NULL; |
5844 | if (!mode_) { |
5845 | to_01 = new int[nCols]; |
5846 | cliqueStack = new int[numberCliques_]; |
5847 | cliqueCount = new int[numberCliques_]; |
5848 | int i; |
5849 | for (i=0;i<numberCliques_;i++) { |
5850 | cliqueCount[i]=cliqueStart_[i+1]-cliqueStart_[i]; |
5851 | } |
5852 | for (i=0;i<nCols;i++) |
5853 | to_01[i]=-1; |
5854 | for (i=0;i<number01Integers_;i++) { |
5855 | int j=cutVector_[i].sequence; |
5856 | to_01[j]=i; |
5857 | } |
5858 | } |
5859 | |
5860 | |
5861 | int nRowsFake = info->inTree ? nRows/3 : nRows; |
5862 | row_cut rowCut(nRowsFake, !info->inTree); |
5863 | const int * column = rowCopy->getIndices(); |
5864 | const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); |
5865 | const int * rowLength = rowCopy->getVectorLengths(); |
5866 | const double * rowElements = rowCopy->getElements(); |
5867 | const int * row = columnCopy->getIndices(); |
5868 | const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); |
5869 | const int * columnLength = columnCopy->getVectorLengths(); |
5870 | const double * columnElements = columnCopy->getElements(); |
5871 | double movement; |
5872 | int i, j, k,kk,jj; |
5873 | int kcol,krow; |
5874 | bool anyColumnCuts=false; |
5875 | double dbound, value, value2; |
5876 | int ninfeas=0; |
5877 | int rowCuts; |
5878 | double disaggEffectiveness; |
5879 | if (mode_) { |
5880 | |
5881 | CoinMemcpyN(si.getReducedCost(),nCols,djs); |
5882 | CoinMemcpyN( si.getColSolution(),nCols,colsol); |
5883 | disaggEffectiveness=1.0e-3; |
5884 | rowCuts=rowCuts_; |
5885 | } else { |
5886 | |
5887 | memset(djs,0,nCols*sizeof(double)); |
5888 | CoinMemcpyN( si.getColSolution(),nCols,colsol); |
5889 | disaggEffectiveness=-1.0e10; |
5890 | if (rowCuts_!=4) |
5891 | rowCuts=1; |
5892 | else |
5893 | rowCuts=4; |
5894 | } |
5895 | for (i = 0; i < nCols; ++i) { |
5896 | |
5897 | if (1) { |
5898 | if (colUpper[i]-colLower[i]>1.0e-8) { |
5899 | if (colsol[i]<colLower[i]+primalTolerance_) { |
5900 | colsol[i]=colLower[i]; |
5901 | djs[i] = CoinMax(0.0,djs[i]); |
5902 | } else if (colsol[i]>colUpper[i]-primalTolerance_) { |
5903 | colsol[i]=colUpper[i]; |
5904 | djs[i] = CoinMin(0.0,djs[i]); |
5905 | } else { |
5906 | djs[i]=0.0; |
5907 | } |
5908 | |
5909 | |
5910 | } |
5911 | } |
5912 | } |
5913 | |
5914 | int ipass=0,nfixed=-1; |
5915 | |
5916 | double cutoff; |
5917 | bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff); |
5918 | if (!cutoff_available||usingObjective_<0) { |
5919 | cutoff = si.getInfinity(); |
5920 | } |
5921 | cutoff *= si.getObjSense(); |
5922 | if (fabs(cutoff)>1.0e30) |
5923 | assert (cutoff>1.0e30); |
5924 | double current = si.getObjValue(); |
5925 | |
5926 | if (!mode_) |
5927 | cutoff=COIN_DBL_MAX; |
5928 | |
5929 | int nstackC0=-1; |
5930 | int * stackC0 = new int[maxStack]; |
5931 | double * lo0 = new double[maxStack]; |
5932 | double * up0 = new double[maxStack]; |
5933 | int nstackR,nstackC; |
5934 | for (i=0;i<nCols;i++) { |
5935 | if (colUpper[i]-colLower[i]<1.0e-8) { |
5936 | markC[i]=3; |
5937 | } else { |
5938 | markC[i]=0; |
5939 | } |
5940 | } |
5941 | double tolerance = 1.0e1*primalTolerance_; |
5942 | int maxPass = info->inTree ? maxPass_ : maxPassRoot_; |
5943 | |
5944 | double needEffectiveness = info->strengthenRow ? -1.0e10 : 1.0e-3; |
5945 | while (ipass<maxPass&&nfixed) { |
5946 | int iLook; |
5947 | ipass++; |
5948 | nfixed=0; |
5949 | for (iLook=0;iLook<numberThisTime_;iLook++) { |
5950 | double solval; |
5951 | double down; |
5952 | double up; |
5953 | j=lookedAt_[iLook]; |
5954 | solval=colsol[j]; |
5955 | down = floor(solval+tolerance); |
5956 | up = ceil(solval-tolerance); |
5957 | if(colUpper[j]-colLower[j]<1.0e-8) markC[j]=3; |
5958 | if (markC[j]||!intVar[j]) continue; |
5959 | double saveSolval = solval; |
5960 | if (solval>=colUpper[j]-tolerance||solval<=colLower[j]+tolerance||up==down) { |
5961 | if (solval<=colLower[j]+2.0*tolerance) { |
5962 | solval = colLower[j]+1.0e-1; |
5963 | down=colLower[j]; |
5964 | up=down+1.0; |
5965 | } else if (solval>=colUpper[j]-2.0*tolerance) { |
5966 | solval = colUpper[j]-1.0e-1; |
5967 | up=colUpper[j]; |
5968 | down=up-1; |
5969 | } else { |
5970 | |
5971 | up=down+1.0; |
5972 | solval = down+1.0e-1; |
5973 | } |
5974 | } |
5975 | assert (up<=colUpper[j]); |
5976 | assert (down>=colLower[j]); |
5977 | assert (up>down); |
5978 | if ((solval-down>1.0e-6&&up-solval>1.0e-6)||mode_!=1) { |
5979 | int istackC,iway, istackR; |
5980 | int way[]={1,2,1}; |
5981 | int feas[]={1,2,4}; |
5982 | int feasible=0; |
5983 | int notFeasible; |
5984 | for (iway=0;iway<3;iway ++) { |
5985 | int fixThis=0; |
5986 | double objVal=current; |
5987 | int goingToTrueBound=0; |
5988 | stackC[0]=j; |
5989 | markC[j]=way[iway]; |
5990 | double solMovement; |
5991 | if (way[iway]==1) { |
5992 | movement=down-colUpper[j]; |
5993 | solMovement = down-colsol[j]; |
5994 | assert(movement<-0.99999); |
5995 | if (fabs(down-colLower[j])<1.0e-7) { |
5996 | goingToTrueBound=2; |
5997 | down=colLower[j]; |
5998 | } |
5999 | } else { |
6000 | movement=up-colLower[j]; |
6001 | solMovement = up-colsol[j]; |
6002 | assert(movement>0.99999); |
6003 | if (fabs(up-colUpper[j])<1.0e-7) { |
6004 | goingToTrueBound=2; |
6005 | up=colUpper[j]; |
6006 | } |
6007 | } |
6008 | if (goingToTrueBound&&(colUpper[j]-colLower[j]>1.5||colLower[j])) |
6009 | goingToTrueBound=1; |
6010 | |
6011 | if ((rowCuts&1)==0) |
6012 | goingToTrueBound=0; |
6013 | #ifdef PRINT_DEBUG |
6014 | if (fabs(movement)>1.01) { |
6015 | printf("big %d %g %g %g\n",j,colLower[j],solval,colUpper[j]); |
6016 | } |
6017 | #endif |
6018 | if (solMovement*djs[j]>0.0) |
6019 | objVal += solMovement*djs[j]; |
6020 | nstackC=1; |
6021 | nstackR=0; |
6022 | saveL[0]=colLower[j]; |
6023 | saveU[0]=colUpper[j]; |
6024 | assert (saveU[0]>saveL[0]); |
6025 | notFeasible=0; |
6026 | if (movement<0.0) { |
6027 | colUpper[j] += movement; |
6028 | colUpper[j] = floor(colUpper[j]+0.5); |
6029 | #ifdef PRINT_DEBUG |
6030 | printf("** Trying %d down to 0\n",j); |
6031 | #endif |
6032 | } else { |
6033 | colLower[j] += movement; |
6034 | colLower[j] = floor(colLower[j]+0.5); |
6035 | #ifdef PRINT_DEBUG |
6036 | printf("** Trying %d up to 1\n",j); |
6037 | #endif |
6038 | } |
6039 | if (fabs(colUpper[j]-colLower[j])<1.0e-6) |
6040 | markC[j]=3; |
6041 | istackC=0; |
6042 | |
6043 | for (k=columnStart[j];k<columnStart[j]+columnLength[j];k++) { |
6044 | int irow = row[k]; |
6045 | value = columnElements[k]; |
6046 | assert (markR[irow]!=-2); |
6047 | if (markR[irow]==-1) { |
6048 | stackR[nstackR]=irow; |
6049 | markR[irow]=nstackR; |
6050 | saveMin[nstackR]=minR[irow]; |
6051 | saveMax[nstackR]=maxR[irow]; |
6052 | nstackR++; |
6053 | #if 0 |
6054 | } else if (markR[irow]==-2) { |
6055 | continue; |
6056 | #endif |
6057 | } |
6058 | |
6059 | if (movement>0.0) { |
6060 | |
6061 | if (value>0.0) { |
6062 | |
6063 | if (minR[irow]>-1.0e10) |
6064 | minR[irow] += value; |
6065 | if (minR[irow]>rowUpper[irow]+1.0e-5) { |
6066 | notFeasible=1; |
6067 | istackC=1; |
6068 | break; |
6069 | } |
6070 | } else { |
6071 | |
6072 | if (maxR[irow]<1.0e10) |
6073 | maxR[irow] += value; |
6074 | if (maxR[irow]<rowLower[irow]-1.0e-5) { |
6075 | notFeasible=1; |
6076 | istackC=1; |
6077 | break; |
6078 | } |
6079 | } |
6080 | } else { |
6081 | |
6082 | if (value<0.0) { |
6083 | |
6084 | if (minR[irow]>-1.0e10) |
6085 | minR[irow] -= value; |
6086 | if (minR[irow]>rowUpper[irow]+1.0e-5) { |
6087 | notFeasible=1; |
6088 | istackC=1; |
6089 | break; |
6090 | } |
6091 | } else { |
6092 | |
6093 | if (maxR[irow]<1.0e10) |
6094 | maxR[irow] -= value; |
6095 | if (maxR[irow]<rowLower[irow]-1.0e-5) { |
6096 | notFeasible=1; |
6097 | istackC=1; |
6098 | break; |
6099 | } |
6100 | } |
6101 | } |
6102 | } |
6103 | while (istackC<nstackC&&nstackC<maxStack) { |
6104 | int jway; |
6105 | int jcol =stackC[istackC]; |
6106 | jway=markC[jcol]; |
6107 | |
6108 | if (jway==3&&istackC) { |
6109 | |
6110 | |
6111 | |
6112 | } |
6113 | |
6114 | if (oneFixStart_&&oneFixStart_[jcol]>=0) { |
6115 | int start; |
6116 | int end; |
6117 | if (colLower[jcol]>saveL[istackC]) { |
6118 | |
6119 | start = oneFixStart_[jcol]; |
6120 | end = zeroFixStart_[jcol]; |
6121 | } else { |
6122 | assert (colUpper[jcol]<saveU[istackC]); |
6123 | |
6124 | start = zeroFixStart_[jcol]; |
6125 | end = endFixStart_[jcol]; |
6126 | } |
6127 | for (int i=start;i<end;i++) { |
6128 | int iClique = whichClique_[i]; |
6129 | for (int k=cliqueStart_[iClique];k<cliqueStart_[iClique+1];k++) { |
6130 | int kcol = sequenceInCliqueEntry(cliqueEntry_[k]); |
6131 | if (jcol==kcol) |
6132 | continue; |
6133 | int kway = oneFixesInCliqueEntry(cliqueEntry_[k]); |
6134 | if (kcol!=jcol) { |
6135 | if (!markC[kcol]) { |
6136 | |
6137 | if (nstackC<2*maxStack) { |
6138 | markC[kcol] = 3; |
6139 | fixThis++; |
6140 | stackC[nstackC]=kcol; |
6141 | saveL[nstackC]=colLower[kcol]; |
6142 | saveU[nstackC]=colUpper[kcol]; |
6143 | assert (saveU[nstackC]>saveL[nstackC]); |
6144 | nstackC++; |
6145 | if (!kway) { |
6146 | |
6147 | double solMovement=1.0-colsol[kcol]; |
6148 | if (solMovement>0.0001) { |
6149 | assert (djs[kcol]>=0.0); |
6150 | objVal += djs[kcol]*solMovement; |
6151 | } |
6152 | colLower[kcol]=1.0; |
6153 | |
6154 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
6155 | krow = row[jj]; |
6156 | value = columnElements[jj]; |
6157 | assert (markR[krow]!=-2); |
6158 | if (markR[krow]==-1) { |
6159 | stackR[nstackR]=krow; |
6160 | markR[krow]=nstackR; |
6161 | saveMin[nstackR]=minR[krow]; |
6162 | saveMax[nstackR]=maxR[krow]; |
6163 | nstackR++; |
6164 | #if 0 |
6165 | } else if (markR[krow]==-2) { |
6166 | continue; |
6167 | #endif |
6168 | } |
6169 | |
6170 | |
6171 | if (value>0.0) { |
6172 | |
6173 | if (minR[krow]>-1.0e10) |
6174 | minR[krow] += value; |
6175 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
6176 | colUpper[kcol]=-1.0e50; |
6177 | break; |
6178 | } |
6179 | } else { |
6180 | |
6181 | if (maxR[krow]<1.0e10) |
6182 | maxR[krow] += value; |
6183 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
6184 | notFeasible=1; |
6185 | break; |
6186 | } |
6187 | } |
6188 | } |
6189 | } else { |
6190 | |
6191 | double solMovement=0.0-colsol[kcol]; |
6192 | if (solMovement<-0.0001) { |
6193 | assert (djs[kcol]<=0.0); |
6194 | objVal += djs[kcol]*solMovement; |
6195 | } |
6196 | colUpper[kcol]=0.0; |
6197 | |
6198 | for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
6199 | krow = row[jj]; |
6200 | value = columnElements[jj]; |
6201 | assert (markR[krow]!=-2); |
6202 | if (markR[krow]==-1) { |
6203 | stackR[nstackR]=krow; |
6204 | markR[krow]=nstackR; |
6205 | saveMin[nstackR]=minR[krow]; |
6206 | saveMax[nstackR]=maxR[krow]; |
6207 | nstackR++; |
6208 | #if 0 |
6209 | } else if (markR[krow]==-2) { |
6210 | continue; |
6211 | #endif |
6212 | } |
6213 | |
6214 | |
6215 | if (value<0.0) { |
6216 | |
6217 | if (minR[krow]>-1.0e10) |
6218 | minR[krow] -= value; |
6219 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
6220 | notFeasible=1; |
6221 | break; |
6222 | } |
6223 | } else { |
6224 | |
6225 | if (maxR[krow]<1.0e10) |
6226 | maxR[krow] -= value; |
6227 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
6228 | notFeasible=1; |
6229 | break; |
6230 | } |
6231 | } |
6232 | } |
6233 | } |
6234 | } |
6235 | } else if (markC[kcol]==1) { |
6236 | |
6237 | assert (!colUpper[kcol]); |
6238 | if (!kway) { |
6239 | |
6240 | notFeasible=1; |
6241 | break; |
6242 | } |
6243 | } else if (markC[kcol]==2) { |
6244 | |
6245 | assert (colLower[kcol]); |
6246 | if (kway) { |
6247 | |
6248 | notFeasible=1; |
6249 | break; |
6250 | } |
6251 | } else { |
6252 | |
6253 | assert (markC[kcol]==3); |
6254 | int jkway; |
6255 | if (colLower[kcol]) |
6256 | jkway=1; |
6257 | else |
6258 | jkway=0; |
6259 | if (kway==jkway) { |
6260 | |
6261 | notFeasible=1; |
6262 | break; |
6263 | } |
6264 | } |
6265 | } |
6266 | } |
6267 | if (notFeasible) |
6268 | break; |
6269 | } |
6270 | if (notFeasible) |
6271 | istackC=nstackC+1; |
6272 | } |
6273 | for (k=columnStart[jcol];k<columnStart[jcol]+columnLength[jcol];k++) { |
6274 | |
6275 | if (notFeasible) |
6276 | break; |
6277 | int irow = row[k]; |
6278 | |
6279 | assert (markR[irow]!=-2); |
6280 | #if 0 |
6281 | if (markR[irow]!=-2) { |
6282 | #endif |
6283 | |
6284 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];kk++) { |
6285 | double moveUp=0.0; |
6286 | double moveDown=0.0; |
6287 | double newUpper=-1.0,newLower=1.0; |
6288 | kcol=column[kk]; |
6289 | bool onList = (markC[kcol]!=0); |
6290 | if (markC[kcol]!=3) { |
6291 | value2=rowElements[kk]; |
6292 | int markIt=markC[kcol]; |
6293 | if (value2 < 0.0) { |
6294 | if (colUpper[kcol] < 1e10 && (markIt&2)==0 && |
6295 | rowUpper[irow]<1.0e10) { |
6296 | dbound = colUpper[kcol]+ |
6297 | (rowUpper[irow]-minR[irow])/value2; |
6298 | if (dbound > colLower[kcol] + primalTolerance_) { |
6299 | if (intVar[kcol]) { |
6300 | markIt |= 2; |
6301 | newLower = ceil(dbound-primalTolerance_); |
6302 | } else { |
6303 | newLower=dbound; |
6304 | if (newLower+primalTolerance_>colUpper[kcol]&& |
6305 | newLower-primalTolerance_<=colUpper[kcol]) { |
6306 | newLower=colUpper[kcol]; |
6307 | markIt |= 2; |
6308 | |
6309 | } else { |
6310 | |
6311 | markIt=3; |
6312 | } |
6313 | } |
6314 | moveUp = newLower-colLower[kcol]; |
6315 | } |
6316 | } |
6317 | if (colLower[kcol] > -1e10 && (markIt&1)==0 && |
6318 | rowLower[irow]>-1.0e10) { |
6319 | dbound = colLower[kcol] + |
6320 | (rowLower[irow]-maxR[irow])/value2; |
6321 | if (dbound < colUpper[kcol] - primalTolerance_) { |
6322 | if (intVar[kcol]) { |
6323 | markIt |= 1; |
6324 | newUpper = floor(dbound+primalTolerance_); |
6325 | } else { |
6326 | newUpper=dbound; |
6327 | if (newUpper-primalTolerance_<colLower[kcol]&& |
6328 | newUpper+primalTolerance_>=colLower[kcol]) { |
6329 | newUpper=colLower[kcol]; |
6330 | markIt |= 1; |
6331 | |
6332 | } else { |
6333 | |
6334 | markIt=3; |
6335 | } |
6336 | } |
6337 | moveDown = newUpper-colUpper[kcol]; |
6338 | } |
6339 | } |
6340 | } else { |
6341 | |
6342 | if (colUpper[kcol] < 1e10 && (markIt&2)==0 && |
6343 | rowLower[irow]>-1.0e10) { |
6344 | dbound = colUpper[kcol] + |
6345 | (rowLower[irow]-maxR[irow])/value2; |
6346 | if (dbound > colLower[kcol] + primalTolerance_) { |
6347 | if (intVar[kcol]) { |
6348 | markIt |= 2; |
6349 | newLower = ceil(dbound-primalTolerance_); |
6350 | } else { |
6351 | newLower=dbound; |
6352 | if (newLower+primalTolerance_>colUpper[kcol]&& |
6353 | newLower-primalTolerance_<=colUpper[kcol]) { |
6354 | newLower=colUpper[kcol]; |
6355 | markIt |= 2; |
6356 | |
6357 | } else { |
6358 | |
6359 | markIt=3; |
6360 | } |
6361 | } |
6362 | moveUp = newLower-colLower[kcol]; |
6363 | } |
6364 | } |
6365 | if (colLower[kcol] > -1e10 && (markIt&1)==0 && |
6366 | rowUpper[irow]<1.0e10) { |
6367 | dbound = colLower[kcol] + |
6368 | (rowUpper[irow]-minR[irow])/value2; |
6369 | if (dbound < colUpper[kcol] - primalTolerance_) { |
6370 | if (intVar[kcol]) { |
6371 | markIt |= 1; |
6372 | newUpper = floor(dbound+primalTolerance_); |
6373 | } else { |
6374 | newUpper=dbound; |
6375 | if (newUpper-primalTolerance_<colLower[kcol]&& |
6376 | newUpper+primalTolerance_>=colLower[kcol]) { |
6377 | newUpper=colLower[kcol]; |
6378 | markIt |= 1; |
6379 | |
6380 | } else { |
6381 | |
6382 | markIt=3; |
6383 | } |
6384 | } |
6385 | moveDown = newUpper-colUpper[kcol]; |
6386 | } |
6387 | } |
6388 | } |
6389 | if (nstackC<2*maxStack) { |
6390 | markC[kcol] = markIt; |
6391 | } |
6392 | if (moveUp&&nstackC<2*maxStack) { |
6393 | fixThis++; |
6394 | #ifdef PRINT_DEBUG |
6395 | printf("lower bound on %d increased from %g to %g by row %d %g %g\n",kcol,colLower[kcol],newLower,irow,rowLower[irow],rowUpper[irow]); |
6396 | value=0.0; |
6397 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
6398 | int ii=column[jj]; |
6399 | if (colUpper[ii]-colLower[ii]>primalTolerance_) { |
6400 | printf("(%d, %g) ",ii,rowElements[jj]); |
6401 | } else { |
6402 | value += rowElements[jj]*colLower[ii]; |
6403 | } |
6404 | } |
6405 | printf(" - fixed %g\n",value); |
6406 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
6407 | int ii=column[jj]; |
6408 | if (colUpper[ii]-colLower[ii]<primalTolerance_) { |
6409 | printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]); |
6410 | } |
6411 | } |
6412 | printf("\n"); |
6413 | #endif |
6414 | if (!onList) { |
6415 | stackC[nstackC]=kcol; |
6416 | saveL[nstackC]=colLower[kcol]; |
6417 | saveU[nstackC]=colUpper[kcol]; |
6418 | assert (saveU[nstackC]>saveL[nstackC]); |
6419 | nstackC++; |
6420 | onList=true; |
6421 | } |
6422 | if (newLower>colsol[kcol]) { |
6423 | if (djs[kcol]<0.0) { |
6424 | |
6425 | assert (newLower>colUpper[kcol]+primalTolerance_); |
6426 | } else { |
6427 | objVal += moveUp*djs[kcol]; |
6428 | } |
6429 | } |
6430 | if (intVar[kcol]) |
6431 | newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4)); |
6432 | colLower[kcol]=newLower; |
6433 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
6434 | markC[kcol]=3; |
6435 | } |
6436 | |
6437 | for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
6438 | krow = row[jj]; |
6439 | value = columnElements[jj]; |
6440 | assert (markR[krow]!=-2); |
6441 | if (markR[krow]==-1) { |
6442 | stackR[nstackR]=krow; |
6443 | markR[krow]=nstackR; |
6444 | saveMin[nstackR]=minR[krow]; |
6445 | saveMax[nstackR]=maxR[krow]; |
6446 | nstackR++; |
6447 | #if 0 |
6448 | } else if (markR[krow]==-2) { |
6449 | continue; |
6450 | #endif |
6451 | } |
6452 | |
6453 | |
6454 | if (value>0.0) { |
6455 | |
6456 | if (minR[krow]>-1.0e10) |
6457 | minR[krow] += value*moveUp; |
6458 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
6459 | colUpper[kcol]=-1.0e50; |
6460 | break; |
6461 | } |
6462 | } else { |
6463 | |
6464 | if (maxR[krow]<1.0e10) |
6465 | maxR[krow] += value*moveUp; |
6466 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
6467 | colUpper[kcol]=-1.0e50; |
6468 | break; |
6469 | } |
6470 | } |
6471 | } |
6472 | } |
6473 | if (moveDown&&nstackC<2*maxStack) { |
6474 | fixThis++; |
6475 | #ifdef PRINT_DEBUG |
6476 | printf("upper bound on %d decreased from %g to %g by row %d %g %g\n",kcol,colUpper[kcol],newUpper,irow,rowLower[irow],rowUpper[irow]); |
6477 | value=0.0; |
6478 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
6479 | int ii=column[jj]; |
6480 | if (colUpper[ii]-colLower[ii]>primalTolerance_) { |
6481 | printf("(%d, %g) ",ii,rowElements[jj]); |
6482 | } else { |
6483 | value += rowElements[jj]*colLower[ii]; |
6484 | } |
6485 | } |
6486 | printf(" - fixed %g\n",value); |
6487 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
6488 | int ii=column[jj]; |
6489 | if (colUpper[ii]-colLower[ii]<primalTolerance_) { |
6490 | printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]); |
6491 | } |
6492 | } |
6493 | printf("\n"); |
6494 | #endif |
6495 | if (!onList) { |
6496 | stackC[nstackC]=kcol; |
6497 | saveL[nstackC]=colLower[kcol]; |
6498 | saveU[nstackC]=colUpper[kcol]; |
6499 | assert (saveU[nstackC]>saveL[nstackC]); |
6500 | nstackC++; |
6501 | onList=true; |
6502 | } |
6503 | if (newUpper<colsol[kcol]) { |
6504 | if (djs[kcol]>0.0) { |
6505 | |
6506 | assert (colLower[kcol]>newUpper+primalTolerance_); |
6507 | } else { |
6508 | objVal += moveDown*djs[kcol]; |
6509 | } |
6510 | } |
6511 | if (intVar[kcol]) |
6512 | newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4)); |
6513 | colUpper[kcol]=newUpper; |
6514 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
6515 | markC[kcol]=3; |
6516 | } |
6517 | |
6518 | for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
6519 | krow = row[jj]; |
6520 | value = columnElements[jj]; |
6521 | assert (markR[krow]!=-2); |
6522 | if (markR[krow]==-1) { |
6523 | stackR[nstackR]=krow; |
6524 | markR[krow]=nstackR; |
6525 | saveMin[nstackR]=minR[krow]; |
6526 | saveMax[nstackR]=maxR[krow]; |
6527 | nstackR++; |
6528 | #if 0 |
6529 | } else if (markR[krow]==-2) { |
6530 | #endif |
6531 | continue; |
6532 | } |
6533 | |
6534 | |
6535 | if (value<0.0) { |
6536 | |
6537 | if (minR[krow]>-1.0e10) |
6538 | minR[krow] += value*moveDown; |
6539 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
6540 | colUpper[kcol]=-1.0e50; |
6541 | break; |
6542 | } |
6543 | } else { |
6544 | |
6545 | if (maxR[krow]<1.0e10) |
6546 | maxR[krow] += value*moveDown; |
6547 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
6548 | colUpper[kcol]=-1.0e50; |
6549 | break; |
6550 | } |
6551 | } |
6552 | } |
6553 | } |
6554 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
6555 | notFeasible=1;; |
6556 | k=columnStart[jcol]+columnLength[jcol]; |
6557 | istackC=nstackC+1; |
6558 | #ifdef PRINT_DEBUG |
6559 | printf("** not feasible this way\n"); |
6560 | #endif |
6561 | break; |
6562 | } |
6563 | } |
6564 | } |
6565 | #if 0 |
6566 | } |
6567 | #endif |
6568 | } |
6569 | istackC++; |
6570 | } |
6571 | if (!notFeasible) { |
6572 | if (objVal<=cutoff) { |
6573 | feasible |= feas[iway]; |
6574 | } else { |
6575 | #ifdef PRINT_DEBUG |
6576 | printf("not feasible on dj\n"); |
6577 | #endif |
6578 | notFeasible=1; |
6579 | if (iway==1&&feasible==0) { |
6580 | |
6581 | ninfeas=1; |
6582 | j=nCols-1; |
6583 | break; |
6584 | } |
6585 | } |
6586 | } else if (iway==1&&feasible==0) { |
6587 | |
6588 | ninfeas=1; |
6589 | j=nCols-1; |
6590 | iLook=numberThisTime_; |
6591 | ipass=maxPass; |
6592 | break; |
6593 | } |
6594 | if (notFeasible) |
6595 | goingToTrueBound=0; |
6596 | if (iway==2||(iway==1&&feasible==2)) { |
6597 | |
6598 | iway=3; |
6599 | nfixed++; |
6600 | if (mode_) { |
6601 | OsiColCut cc; |
6602 | int nTot=0,nFix=0,nInt=0; |
6603 | bool ifCut=false; |
6604 | for (istackC=0;istackC<nstackC;istackC++) { |
6605 | int icol=stackC[istackC]; |
6606 | if (intVar[icol]) { |
6607 | if (colUpper[icol]<currentColUpper[icol]-1.0e-4) { |
6608 | element[nFix]=colUpper[icol]; |
6609 | index[nFix++]=icol; |
6610 | nInt++; |
6611 | if (colsol[icol]>colUpper[icol]+primalTolerance_) { |
6612 | ifCut=true; |
6613 | anyColumnCuts=true; |
6614 | } |
6615 | } |
6616 | } |
6617 | } |
6618 | if (nFix) { |
6619 | nTot=nFix; |
6620 | cc.setUbs(nFix,index,element); |
6621 | nFix=0; |
6622 | } |
6623 | for (istackC=0;istackC<nstackC;istackC++) { |
6624 | int icol=stackC[istackC]; |
6625 | if (intVar[icol]) { |
6626 | if (colLower[icol]>currentColLower[icol]+1.0e-4) { |
6627 | element[nFix]=colLower[icol]; |
6628 | index[nFix++]=icol; |
6629 | nInt++; |
6630 | if (colsol[icol]<colLower[icol]-primalTolerance_) { |
6631 | ifCut=true; |
6632 | anyColumnCuts=true; |
6633 | } |
6634 | } |
6635 | } |
6636 | } |
6637 | if (nFix) { |
6638 | nTot+=nFix; |
6639 | cc.setLbs(nFix,index,element); |
6640 | } |
6641 | |
6642 | if (nInt) { |
6643 | if (ifCut) { |
6644 | cc.setEffectiveness(100.0); |
6645 | } else { |
6646 | cc.setEffectiveness(1.0e-5); |
6647 | } |
6648 | #ifdef CGL_DEBUG |
6649 | checkBounds(debugger,cc); |
6650 | #endif |
6651 | cs.insert(cc); |
6652 | } |
6653 | } |
6654 | for (istackC=0;istackC<nstackC;istackC++) { |
6655 | int icol=stackC[istackC]; |
6656 | if (colUpper[icol]-colLower[icol]>primalTolerance_) { |
6657 | markC[icol]=0; |
6658 | } else { |
6659 | markC[icol]=3; |
6660 | } |
6661 | } |
6662 | for (istackR=0;istackR<nstackR;istackR++) { |
6663 | int irow=stackR[istackR]; |
6664 | markR[irow]=-1; |
6665 | } |
6666 | } else { |
6667 | |
6668 | |
6669 | if (iway==0) { |
6670 | nstackC0=CoinMin(nstackC,maxStack); |
6671 | double solMove = saveSolval-down; |
6672 | double boundChange; |
6673 | if (notFeasible) { |
6674 | nstackC0=0; |
6675 | } else { |
6676 | for (istackC=0;istackC<nstackC0;istackC++) { |
6677 | int icol=stackC[istackC]; |
6678 | stackC0[istackC]=icol; |
6679 | lo0[istackC]=colLower[icol]; |
6680 | up0[istackC]=colUpper[icol]; |
6681 | } |
6682 | } |
6683 | |
6684 | int nCliquesAffected=0; |
6685 | assert (iway==0); |
6686 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
6687 | int icol=stackC[istackC]; |
6688 | double oldU=saveU[istackC]; |
6689 | double oldL=saveL[istackC]; |
6690 | if(goingToTrueBound==2&&istackC) { |
6691 | |
6692 | if (!mode_&&numberCliques_) { |
6693 | int i_01 = to_01[icol]; |
6694 | if (i_01>=0) { |
6695 | int start; |
6696 | int end; |
6697 | if (colLower[icol]) { |
6698 | |
6699 | start = zeroFixStart_[icol]; |
6700 | end = endFixStart_[icol]; |
6701 | } else { |
6702 | |
6703 | start = oneFixStart_[icol]; |
6704 | end = zeroFixStart_[icol]; |
6705 | } |
6706 | |
6707 | |
6708 | |
6709 | for (int i=start;i<end;i++) { |
6710 | int iClique = whichClique_[i]; |
6711 | int size = cliqueStart_[iClique+1]-cliqueStart_[iClique]; |
6712 | if (cliqueCount[iClique]==size) { |
6713 | |
6714 | cliqueStack[nCliquesAffected++]=iClique; |
6715 | } |
6716 | |
6717 | cliqueCount[iClique]--; |
6718 | } |
6719 | } |
6720 | } |
6721 | |
6722 | |
6723 | boundChange = oldU-colUpper[icol]; |
6724 | if (boundChange>0.0&&oldU<1.0e10&& |
6725 | (!mode_||colsol[icol]>colUpper[icol] |
6726 | + boundChange*solMove+primalTolerance_)) { |
6727 | |
6728 | OsiRowCut rc; |
6729 | rc.setLb(-COIN_DBL_MAX); |
6730 | rc.setUb(colUpper[icol]-down*boundChange); |
6731 | index[0]=icol; |
6732 | element[0]=1.0; |
6733 | index[1]=j; |
6734 | element[1]= - boundChange; |
6735 | |
6736 | double newSol = (colsol[icol]-colUpper[icol])/ |
6737 | boundChange; |
6738 | if (mode_) |
6739 | assert(newSol>solMove); |
6740 | rc.setEffectiveness(newSol-solMove); |
6741 | if (rc.effectiveness()>disaggEffectiveness) { |
6742 | rc.setRow(2,index,element,false); |
6743 | #ifdef CGL_DEBUG |
6744 | if (debugger) assert(!debugger->invalidCut(rc)); |
6745 | #endif |
6746 | rowCut.addCutIfNotDuplicate(rc); |
6747 | } |
6748 | } |
6749 | |
6750 | |
6751 | boundChange = oldL-colLower[icol]; |
6752 | if (boundChange<0.0&&oldL>-1.0e10&& |
6753 | (!mode_||colsol[icol]<colLower[icol] |
6754 | + boundChange*solMove-primalTolerance_)) { |
6755 | |
6756 | OsiRowCut rc; |
6757 | rc.setLb(colLower[icol]-down*boundChange); |
6758 | rc.setUb(COIN_DBL_MAX); |
6759 | index[0]=icol; |
6760 | element[0]=1.0; |
6761 | index[1]=j; |
6762 | element[1]=- boundChange; |
6763 | |
6764 | double newSol = (colsol[icol]-colLower[icol])/ |
6765 | boundChange; |
6766 | if (mode_) |
6767 | assert(newSol>solMove); |
6768 | rc.setEffectiveness(newSol-solMove); |
6769 | if (rc.effectiveness()>disaggEffectiveness) { |
6770 | rc.setRow(2,index,element,false); |
6771 | #ifdef CGL_DEBUG |
6772 | if (debugger) assert(!debugger->invalidCut(rc)); |
6773 | #endif |
6774 | rowCut.addCutIfNotDuplicate(rc); |
6775 | #if 0 |
6776 | printf("%d original bounds %g, %g new Lo %g sol= %g int %d sol= %g\n",icol,oldL,oldU,colLower[icol],colsol[icol], j, colsol[j]); |
6777 | printf("-1.0 * x(%d) + %g * y(%d) <= %g\n", |
6778 | icol,boundChange,j,rc.ub()); |
6779 | #endif |
6780 | } |
6781 | } |
6782 | } |
6783 | colUpper[icol]=oldU; |
6784 | colLower[icol]=oldL; |
6785 | markC[icol]=0; |
6786 | } |
6787 | if (nCliquesAffected) { |
6788 | for (int i=0;i<nCliquesAffected;i++) { |
6789 | int iClique = cliqueStack[i]; |
6790 | int size = cliqueCount[iClique]; |
6791 | |
6792 | cliqueCount[iClique]= cliqueStart_[iClique+1]-cliqueStart_[iClique]; |
6793 | if (!size) { |
6794 | if (logLevel_>1) |
6795 | printf("** could extend clique by adding j!\n"); |
6796 | } |
6797 | } |
6798 | } |
6799 | for (istackR=0;istackR<nstackR;istackR++) { |
6800 | int irow=stackR[istackR]; |
6801 | |
6802 | if ((rowCuts&2)!=0&&goingToTrueBound) { |
6803 | bool ifCut=anyColumnCuts; |
6804 | double gap = rowUpper[irow]-maxR[irow]; |
6805 | double sum=0.0; |
6806 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
6807 | |
6808 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
6809 | kk++) { |
6810 | sum += rowElements[kk]*colsol[column[kk]]; |
6811 | } |
6812 | if (sum-gap*colsol[j]>maxR[irow]+primalTolerance_||(info->strengthenRow&&rowLower[irow]<-1.0e20)) { |
6813 | |
6814 | |
6815 | |
6816 | int * index = reinterpret_cast<int *>(saveL); |
6817 | double * element = saveU; |
6818 | int n=0; |
6819 | bool coefficientExists=false; |
6820 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
6821 | kk++) { |
6822 | if (column[kk]!=j) { |
6823 | index[n]=column[kk]; |
6824 | element[n++]=rowElements[kk]; |
6825 | } else { |
6826 | double value=rowElements[kk]-gap; |
6827 | if (fabs(value)>1.0e-12) { |
6828 | index[n]=column[kk]; |
6829 | element[n++]=value; |
6830 | } |
6831 | coefficientExists=true; |
6832 | } |
6833 | } |
6834 | if (!coefficientExists) { |
6835 | index[n]=j; |
6836 | element[n++]=-gap; |
6837 | } |
6838 | OsiRowCut rc; |
6839 | rc.setLb(-COIN_DBL_MAX); |
6840 | rc.setUb(rowUpper[irow]-gap*(colLower[j]+1.0)); |
6841 | |
6842 | rc.setEffectiveness((sum-gap*colsol[j]-maxR[irow])/gap); |
6843 | if (rc.effectiveness()>needEffectiveness) { |
6844 | rc.setRow(n,index,element,false); |
6845 | #ifdef CGL_DEBUG |
6846 | if (debugger) assert(!debugger->invalidCut(rc)); |
6847 | #endif |
6848 | |
6849 | |
6850 | |
6851 | #ifdef STRENGTHEN_PRINT |
6852 | if (rowLower[irow]<-1.0e20) { |
6853 | printf("5Cut %g <= ",rc.lb()); |
6854 | int k; |
6855 | for ( k=0;k<n;k++) { |
6856 | int iColumn = index[k]; |
6857 | printf("%g*",element[k]); |
6858 | if (si.isInteger(iColumn)) |
6859 | printf("i%d ",iColumn); |
6860 | else |
6861 | printf("x%d ",iColumn); |
6862 | } |
6863 | printf("<= %g\n",rc.ub()); |
6864 | printf("Row %g <= ",rowLower[irow]); |
6865 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
6866 | int iColumn = column[k]; |
6867 | printf("%g*",rowElements[k]); |
6868 | if (si.isInteger(iColumn)) |
6869 | printf("i%d ",iColumn); |
6870 | else |
6871 | printf("x%d ",iColumn); |
6872 | } |
6873 | printf("<= %g\n",rowUpper[irow]); |
6874 | } |
6875 | #endif |
6876 | int realRow = (rowLower[irow]<-1.0e20) ? irow : -1; |
6877 | if (realRows&&realRow>0) |
6878 | realRow=realRows[realRow]; |
6879 | rowCut.addCutIfNotDuplicate(rc,realRow); |
6880 | } |
6881 | } |
6882 | } |
6883 | gap = minR[irow]-rowLower[irow]; |
6884 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
6885 | |
6886 | if (!sum) { |
6887 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
6888 | kk++) { |
6889 | sum += rowElements[kk]*colsol[column[kk]]; |
6890 | } |
6891 | } |
6892 | if (sum+gap*colsol[j]<minR[irow]+primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) { |
6893 | |
6894 | |
6895 | |
6896 | int * index = reinterpret_cast<int *>(saveL); |
6897 | double * element = saveU; |
6898 | int n=0; |
6899 | bool coefficientExists=false; |
6900 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
6901 | kk++) { |
6902 | if (column[kk]!=j) { |
6903 | index[n]=column[kk]; |
6904 | element[n++]=rowElements[kk]; |
6905 | } else { |
6906 | double value=rowElements[kk]+gap; |
6907 | if (fabs(value)>1.0e-12) { |
6908 | index[n]=column[kk]; |
6909 | element[n++]=value; |
6910 | } |
6911 | coefficientExists=true; |
6912 | } |
6913 | } |
6914 | if (!coefficientExists) { |
6915 | index[n]=j; |
6916 | element[n++]=gap; |
6917 | } |
6918 | OsiRowCut rc; |
6919 | rc.setLb(rowLower[irow]+gap*(colLower[j]+1.0)); |
6920 | rc.setUb(COIN_DBL_MAX); |
6921 | |
6922 | rc.setEffectiveness((minR[irow]-sum-gap*colsol[j])/gap); |
6923 | if (rc.effectiveness()>needEffectiveness) { |
6924 | rc.setRow(n,index,element,false); |
6925 | #ifdef CGL_DEBUG |
6926 | if (debugger) assert(!debugger->invalidCut(rc)); |
6927 | #endif |
6928 | |
6929 | |
6930 | #ifdef STRENGTHEN_PRINT |
6931 | if (rowUpper[irow]>1.0e20) { |
6932 | printf("6Cut %g <= ",rc.lb()); |
6933 | int k; |
6934 | for ( k=0;k<n;k++) { |
6935 | int iColumn = index[k]; |
6936 | printf("%g*",element[k]); |
6937 | if (si.isInteger(iColumn)) |
6938 | printf("i%d ",iColumn); |
6939 | else |
6940 | printf("x%d ",iColumn); |
6941 | } |
6942 | printf("<= %g\n",rc.ub()); |
6943 | printf("Row %g <= ",rowLower[irow]); |
6944 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
6945 | int iColumn = column[k]; |
6946 | printf("%g*",rowElements[k]); |
6947 | if (si.isInteger(iColumn)) |
6948 | printf("i%d ",iColumn); |
6949 | else |
6950 | printf("x%d ",iColumn); |
6951 | } |
6952 | printf("<= %g\n",rowUpper[irow]); |
6953 | } |
6954 | #endif |
6955 | int realRow = (rowUpper[irow]>1.0e20) ? irow : -1; |
6956 | if (realRows&&realRow>0) |
6957 | realRow=realRows[realRow]; |
6958 | rowCut.addCutIfNotDuplicate(rc,realRow); |
6959 | } |
6960 | } |
6961 | } |
6962 | } |
6963 | minR[irow]=saveMin[istackR]; |
6964 | maxR[irow]=saveMax[istackR]; |
6965 | markR[irow]=-1; |
6966 | } |
6967 | } else { |
6968 | if (iway==1&&feasible==3) { |
6969 | iway=3; |
6970 | |
6971 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
6972 | int icol=stackC[istackC]; |
6973 | markC[icol]=istackC+1000; |
6974 | } |
6975 | if (mode_) { |
6976 | OsiColCut cc; |
6977 | int nTot=0,nFix=0,nInt=0; |
6978 | bool ifCut=false; |
6979 | for (istackC=0;istackC<nstackC0;istackC++) { |
6980 | int icol=stackC0[istackC]; |
6981 | int istackC1=markC[icol]-1000; |
6982 | if (istackC1>=0) { |
6983 | if (CoinMin(lo0[istackC],colLower[icol])>saveL[istackC1]+1.0e-4) { |
6984 | saveL[istackC1]=CoinMin(lo0[istackC],colLower[icol]); |
6985 | if (intVar[icol]) { |
6986 | element[nFix]=saveL[istackC1]; |
6987 | index[nFix++]=icol; |
6988 | nInt++; |
6989 | if (colsol[icol]<saveL[istackC1]-primalTolerance_) |
6990 | ifCut=true; |
6991 | } |
6992 | nfixed++; |
6993 | } |
6994 | } |
6995 | } |
6996 | if (nFix) { |
6997 | nTot=nFix; |
6998 | cc.setLbs(nFix,index,element); |
6999 | nFix=0; |
7000 | } |
7001 | for (istackC=0;istackC<nstackC0;istackC++) { |
7002 | int icol=stackC0[istackC]; |
7003 | int istackC1=markC[icol]-1000; |
7004 | if (istackC1>=0) { |
7005 | if (CoinMax(up0[istackC],colUpper[icol])<saveU[istackC1]-1.0e-4) { |
7006 | saveU[istackC1]=CoinMax(up0[istackC],colUpper[icol]); |
7007 | if (intVar[icol]) { |
7008 | element[nFix]=saveU[istackC1]; |
7009 | index[nFix++]=icol; |
7010 | nInt++; |
7011 | if (colsol[icol]>saveU[istackC1]+primalTolerance_) |
7012 | ifCut=true; |
7013 | } |
7014 | nfixed++; |
7015 | } |
7016 | } |
7017 | } |
7018 | if (nFix) { |
7019 | nTot+=nFix; |
7020 | cc.setUbs(nFix,index,element); |
7021 | } |
7022 | |
7023 | if (nInt) { |
7024 | if (ifCut) { |
7025 | cc.setEffectiveness(100.0); |
7026 | } else { |
7027 | cc.setEffectiveness(1.0e-5); |
7028 | } |
7029 | #ifdef CGL_DEBUG |
7030 | checkBounds(debugger,cc); |
7031 | #endif |
7032 | cs.insert(cc); |
7033 | } |
7034 | } |
7035 | } else { |
7036 | goingToTrueBound=0; |
7037 | } |
7038 | double solMove = up-saveSolval; |
7039 | double boundChange; |
7040 | |
7041 | int nCliquesAffected=0; |
7042 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
7043 | int icol=stackC[istackC]; |
7044 | double oldU=saveU[istackC]; |
7045 | double oldL=saveL[istackC]; |
7046 | if(goingToTrueBound==2&&istackC) { |
7047 | |
7048 | if (!mode_&&numberCliques_&&iway==3) { |
7049 | int i_01 = to_01[icol]; |
7050 | if (i_01>=0) { |
7051 | int start; |
7052 | int end; |
7053 | if (colLower[icol]) { |
7054 | |
7055 | start = zeroFixStart_[icol]; |
7056 | end = endFixStart_[icol]; |
7057 | } else { |
7058 | |
7059 | start = oneFixStart_[icol]; |
7060 | end = zeroFixStart_[icol]; |
7061 | } |
7062 | |
7063 | |
7064 | |
7065 | for (int i=start;i<end;i++) { |
7066 | int iClique = whichClique_[i]; |
7067 | int size = cliqueStart_[iClique+1]-cliqueStart_[iClique]; |
7068 | if (cliqueCount[iClique]==size) { |
7069 | |
7070 | cliqueStack[nCliquesAffected++]=iClique; |
7071 | } |
7072 | |
7073 | cliqueCount[iClique]--; |
7074 | } |
7075 | } |
7076 | } |
7077 | |
7078 | |
7079 | boundChange = oldU-colUpper[icol]; |
7080 | if (boundChange>0.0&&oldU<1.0e10&& |
7081 | (!mode_||colsol[icol]>colUpper[icol] |
7082 | + boundChange*solMove+primalTolerance_)) { |
7083 | |
7084 | OsiRowCut rc; |
7085 | rc.setLb(-COIN_DBL_MAX); |
7086 | rc.setUb(colUpper[icol]+up*boundChange); |
7087 | index[0]=icol; |
7088 | element[0]=1.0; |
7089 | index[1]=j; |
7090 | element[1]= + boundChange; |
7091 | |
7092 | double newSol = (colsol[icol]-colUpper[icol])/ |
7093 | boundChange; |
7094 | if (mode_) |
7095 | assert(newSol>solMove); |
7096 | rc.setEffectiveness(newSol-solMove); |
7097 | if (rc.effectiveness()>disaggEffectiveness) { |
7098 | rc.setRow(2,index,element,false); |
7099 | #ifdef CGL_DEBUG |
7100 | if (debugger) assert(!debugger->invalidCut(rc)); |
7101 | #endif |
7102 | rowCut.addCutIfNotDuplicate(rc); |
7103 | } |
7104 | } |
7105 | |
7106 | |
7107 | boundChange = oldL-colLower[icol]; |
7108 | if (boundChange<0.0&&oldL>-1.0e10&& |
7109 | (!mode_||colsol[icol]<colLower[icol] |
7110 | + boundChange*solMove-primalTolerance_)) { |
7111 | |
7112 | OsiRowCut rc; |
7113 | rc.setLb(colLower[icol]+up*boundChange); |
7114 | rc.setUb(COIN_DBL_MAX); |
7115 | index[0]=icol; |
7116 | element[0]=1.0; |
7117 | index[1]=j; |
7118 | element[1]= + boundChange; |
7119 | |
7120 | double newSol = (colsol[icol]-colLower[icol])/ |
7121 | boundChange; |
7122 | if (mode_) |
7123 | assert(newSol>solMove); |
7124 | rc.setEffectiveness(newSol-solMove); |
7125 | if (rc.effectiveness()>disaggEffectiveness) { |
7126 | rc.setRow(2,index,element,false); |
7127 | #ifdef CGL_DEBUG |
7128 | if (debugger) assert(!debugger->invalidCut(rc)); |
7129 | #endif |
7130 | rowCut.addCutIfNotDuplicate(rc); |
7131 | } |
7132 | } |
7133 | } |
7134 | colUpper[icol]=oldU; |
7135 | colLower[icol]=oldL; |
7136 | if (oldU>oldL+1.0e-4) |
7137 | markC[icol]=0; |
7138 | else |
7139 | markC[icol]=3; |
7140 | } |
7141 | if (nCliquesAffected) { |
7142 | for (int i=0;i<nCliquesAffected;i++) { |
7143 | int iClique = cliqueStack[i]; |
7144 | int size = cliqueCount[iClique]; |
7145 | |
7146 | cliqueCount[iClique]= cliqueStart_[iClique+1]-cliqueStart_[iClique]; |
7147 | if (!size) { |
7148 | if (logLevel_>1) |
7149 | printf("** could extend clique by adding j!\n"); |
7150 | } |
7151 | } |
7152 | } |
7153 | for (istackR=0;istackR<nstackR;istackR++) { |
7154 | int irow=stackR[istackR]; |
7155 | |
7156 | if ((rowCuts&2)!=0&&goingToTrueBound) { |
7157 | bool ifCut=anyColumnCuts; |
7158 | double gap = rowUpper[irow]-maxR[irow]; |
7159 | double sum=0.0; |
7160 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
7161 | |
7162 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
7163 | kk++) { |
7164 | sum += rowElements[kk]*colsol[column[kk]]; |
7165 | } |
7166 | if (sum+gap*colsol[j]>rowUpper[irow]+primalTolerance_||(info->strengthenRow&&rowLower[irow]<-1.0e20)) { |
7167 | |
7168 | |
7169 | |
7170 | int * index = reinterpret_cast<int *>(saveL); |
7171 | double * element = saveU; |
7172 | int n=0; |
7173 | bool coefficientExists=false; |
7174 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
7175 | kk++) { |
7176 | if (column[kk]!=j) { |
7177 | index[n]=column[kk]; |
7178 | element[n++]=rowElements[kk]; |
7179 | } else { |
7180 | double value=rowElements[kk]+gap; |
7181 | if (fabs(value)>1.0e-12) { |
7182 | index[n]=column[kk]; |
7183 | element[n++]=value; |
7184 | } |
7185 | coefficientExists=true; |
7186 | } |
7187 | } |
7188 | if (!coefficientExists) { |
7189 | index[n]=j; |
7190 | element[n++]=gap; |
7191 | } |
7192 | OsiRowCut rc; |
7193 | rc.setLb(-COIN_DBL_MAX); |
7194 | rc.setUb(rowUpper[irow]+gap*(colUpper[j]-1.0)); |
7195 | |
7196 | rc.setEffectiveness((sum+gap*colsol[j]-rowUpper[irow])/gap); |
7197 | if (rc.effectiveness()>needEffectiveness) { |
7198 | rc.setRow(n,index,element,false); |
7199 | #ifdef CGL_DEBUG |
7200 | if (debugger) assert(!debugger->invalidCut(rc)); |
7201 | #endif |
7202 | |
7203 | |
7204 | #ifdef STRENGTHEN_PRINT |
7205 | if (rowLower[irow]<-1.0e20) { |
7206 | printf("7Cut %g <= ",rc.lb()); |
7207 | int k; |
7208 | for ( k=0;k<n;k++) { |
7209 | int iColumn = index[k]; |
7210 | printf("%g*",element[k]); |
7211 | if (si.isInteger(iColumn)) |
7212 | printf("i%d ",iColumn); |
7213 | else |
7214 | printf("x%d ",iColumn); |
7215 | } |
7216 | printf("<= %g\n",rc.ub()); |
7217 | printf("Row %g <= ",rowLower[irow]); |
7218 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
7219 | int iColumn = column[k]; |
7220 | printf("%g*",rowElements[k]); |
7221 | if (si.isInteger(iColumn)) |
7222 | printf("i%d ",iColumn); |
7223 | else |
7224 | printf("x%d ",iColumn); |
7225 | } |
7226 | printf("<= %g\n",rowUpper[irow]); |
7227 | } |
7228 | #endif |
7229 | int realRow = (rowLower[irow]<-1.0e20) ? irow : -1; |
7230 | if (realRows&&realRow>0) |
7231 | realRow=realRows[realRow]; |
7232 | rowCut.addCutIfNotDuplicate(rc,realRow); |
7233 | } |
7234 | } |
7235 | } |
7236 | gap = minR[irow]-rowLower[irow]; |
7237 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
7238 | |
7239 | if (!sum) { |
7240 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
7241 | kk++) { |
7242 | sum += rowElements[kk]*colsol[column[kk]]; |
7243 | } |
7244 | } |
7245 | if (sum-gap*colsol[j]<rowLower[irow]+primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) { |
7246 | |
7247 | |
7248 | |
7249 | int * index = reinterpret_cast<int *>(saveL); |
7250 | double * element = saveU; |
7251 | int n=0; |
7252 | bool coefficientExists=false; |
7253 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
7254 | kk++) { |
7255 | if (column[kk]!=j) { |
7256 | index[n]=column[kk]; |
7257 | element[n++]=rowElements[kk]; |
7258 | } else { |
7259 | double value=rowElements[kk]-gap; |
7260 | if (fabs(value)>1.0e-12) { |
7261 | index[n]=column[kk]; |
7262 | element[n++]=value; |
7263 | } |
7264 | coefficientExists=true; |
7265 | } |
7266 | } |
7267 | if (!coefficientExists) { |
7268 | index[n]=j; |
7269 | element[n++]=-gap; |
7270 | } |
7271 | OsiRowCut rc; |
7272 | rc.setLb(rowLower[irow]-gap*(colUpper[j]-1)); |
7273 | rc.setUb(COIN_DBL_MAX); |
7274 | |
7275 | rc.setEffectiveness((rowLower[irow]-sum+gap*colsol[j])/gap); |
7276 | if (rc.effectiveness()>needEffectiveness) { |
7277 | rc.setRow(n,index,element,false); |
7278 | #ifdef CGL_DEBUG |
7279 | if (debugger) assert(!debugger->invalidCut(rc)); |
7280 | #endif |
7281 | |
7282 | |
7283 | #ifdef STRENGTHEN_PRINT |
7284 | if (rowUpper[irow]>1.0e20) { |
7285 | printf("8Cut %g <= ",rc.lb()); |
7286 | int k; |
7287 | for ( k=0;k<n;k++) { |
7288 | int iColumn = index[k]; |
7289 | printf("%g*",element[k]); |
7290 | if (si.isInteger(iColumn)) |
7291 | printf("i%d ",iColumn); |
7292 | else |
7293 | printf("x%d ",iColumn); |
7294 | } |
7295 | printf("<= %g\n",rc.ub()); |
7296 | printf("Row %g <= ",rowLower[irow]); |
7297 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
7298 | int iColumn = column[k]; |
7299 | printf("%g*",rowElements[k]); |
7300 | if (si.isInteger(iColumn)) |
7301 | printf("i%d ",iColumn); |
7302 | else |
7303 | printf("x%d ",iColumn); |
7304 | } |
7305 | printf("<= %g\n",rowUpper[irow]); |
7306 | } |
7307 | #endif |
7308 | int realRow = (rowUpper[irow]>1.0e20) ? irow : -1; |
7309 | if (realRows&&realRow>0) |
7310 | realRow=realRows[realRow]; |
7311 | rowCut.addCutIfNotDuplicate(rc,realRow); |
7312 | } |
7313 | } |
7314 | } |
7315 | } |
7316 | minR[irow]=saveMin[istackR]; |
7317 | maxR[irow]=saveMax[istackR]; |
7318 | markR[irow]=-1; |
7319 | } |
7320 | } |
7321 | } |
7322 | } |
7323 | } |
7324 | } |
7325 | } |
7326 | delete [] cliqueStack; |
7327 | delete [] cliqueCount; |
7328 | delete [] to_01; |
7329 | delete [] stackC0; |
7330 | delete [] lo0; |
7331 | delete [] up0; |
7332 | delete [] tempL; |
7333 | delete [] tempU; |
7334 | delete [] markC; |
7335 | delete [] stackC; |
7336 | delete [] stackR; |
7337 | delete [] saveL; |
7338 | delete [] saveU; |
7339 | delete [] saveMin; |
7340 | delete [] saveMax; |
7341 | delete [] index; |
7342 | delete [] element; |
7343 | delete [] djs; |
7344 | delete [] colsol; |
7345 | |
7346 | if (!ninfeas) { |
7347 | rowCut.addCuts(cs,info->strengthenRow,0); |
7348 | } |
7349 | return (ninfeas); |
7350 | } |
7351 | |
7352 | int |
7353 | CglProbing::probeSlacks( const OsiSolverInterface & si, |
7354 | const OsiRowCutDebugger * |
7355 | #ifdef CGL_DEBUG |
7356 | debugger |
7357 | #endif |
7358 | ,OsiCuts & cs, |
7359 | double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, |
7360 | CoinPackedMatrix *columnCopy, |
7361 | double * rowLower, double * rowUpper, |
7362 | char * intVar, double * minR, double * maxR,int * markR, |
7363 | CglTreeInfo * info) |
7364 | { |
7365 | if (!numberCliques_) |
7366 | return 0; |
7367 | |
7368 | int maxProbe = info->inTree ? maxProbe_ : maxProbeRoot_; |
7369 | int maxStack = info->inTree ? maxStack_ : maxStackRoot_; |
7370 | int nRows=rowCopy->getNumRows(); |
7371 | int nCols=rowCopy->getNumCols(); |
7372 | double * colsol = new double[nCols]; |
7373 | CoinMemcpyN( si.getColSolution(),nCols,colsol); |
7374 | int rowCuts=rowCuts_; |
7375 | double_int_pair * array = new double_int_pair [numberCliques_]; |
7376 | |
7377 | int iClique; |
7378 | int nLook=0; |
7379 | for (iClique=0;iClique<numberCliques_;iClique++) { |
7380 | if (!cliqueType_[iClique].equality) { |
7381 | double sum=0.0; |
7382 | for (int j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) { |
7383 | int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]); |
7384 | double value = colsol[iColumn]; |
7385 | if (oneFixesInCliqueEntry(cliqueEntry_[j])) |
7386 | sum += value; |
7387 | else |
7388 | sum -= value; |
7389 | } |
7390 | double away = fabs(0.5-(sum-floor(sum))); |
7391 | if (away<0.49999) { |
7392 | array[nLook].infeasibility=away; |
7393 | array[nLook++].sequence=iClique; |
7394 | } |
7395 | } |
7396 | } |
7397 | std::sort(array,array+nLook,double_int_pair_compare()); |
7398 | nLook=CoinMin(nLook,maxProbe); |
7399 | const double * currentColLower = si.getColLower(); |
7400 | const double * currentColUpper = si.getColUpper(); |
7401 | double * tempL = new double [nCols]; |
7402 | double * tempU = new double [nCols]; |
7403 | int * markC = new int [nCols]; |
7404 | int * stackC = new int [2*nCols]; |
7405 | int * stackR = new int [nRows]; |
7406 | double * saveL = new double [2*nCols]; |
7407 | double * saveU = new double [2*nCols]; |
7408 | double * saveMin = new double [nRows]; |
7409 | double * saveMax = new double [nRows]; |
7410 | double * element = new double[nCols]; |
7411 | int * index = new int[nCols]; |
7412 | |
7413 | |
7414 | int nRowsFake = info->inTree ? nRows/3 : nRows; |
7415 | row_cut rowCut(nRowsFake, !info->inTree); |
7416 | const int * column = rowCopy->getIndices(); |
7417 | const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); |
7418 | const int * rowLength = rowCopy->getVectorLengths(); |
7419 | const double * rowElements = rowCopy->getElements(); |
7420 | const int * row = columnCopy->getIndices(); |
7421 | const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); |
7422 | const int * columnLength = columnCopy->getVectorLengths(); |
7423 | const double * columnElements = columnCopy->getElements(); |
7424 | double movement; |
7425 | int i, j, k,kk,jj; |
7426 | int kcol,irow,krow; |
7427 | bool anyColumnCuts=false; |
7428 | double dbound, value, value2; |
7429 | int ninfeas=0; |
7430 | for (i = 0; i < nCols; ++i) { |
7431 | if (colUpper[i]-colLower[i]>1.0e-8) { |
7432 | if (colsol[i]<colLower[i]+primalTolerance_) { |
7433 | colsol[i]=colLower[i]; |
7434 | } else if (colsol[i]>colUpper[i]-primalTolerance_) { |
7435 | colsol[i]=colUpper[i]; |
7436 | } |
7437 | } |
7438 | } |
7439 | |
7440 | int ipass=0,nfixed=-1; |
7441 | |
7442 | |
7443 | int nstackC0=-1; |
7444 | int * stackC0 = new int[maxStack]; |
7445 | double * lo0 = new double[maxStack]; |
7446 | double * up0 = new double[maxStack]; |
7447 | int nstackR,nstackC; |
7448 | for (i=0;i<nCols;i++) { |
7449 | if (colUpper[i]-colLower[i]<1.0e-8) { |
7450 | markC[i]=3; |
7451 | } else { |
7452 | markC[i]=0; |
7453 | } |
7454 | } |
7455 | double tolerance = 1.0e1*primalTolerance_; |
7456 | |
7457 | int maxPass = info->inTree ? maxPass_ : maxPassRoot_; |
7458 | double needEffectiveness = info->strengthenRow ? -1.0e10 : 1.0e-3; |
7459 | while (ipass<maxPass&&nfixed) { |
7460 | int iLook; |
7461 | ipass++; |
7462 | nfixed=0; |
7463 | for (iLook=0;iLook<nLook;iLook++) { |
7464 | double solval; |
7465 | double down; |
7466 | double up; |
7467 | int iClique=array[iLook].sequence; |
7468 | solval=0.0; |
7469 | j=0; |
7470 | for (j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) { |
7471 | int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]); |
7472 | double value = colsol[iColumn]; |
7473 | if (oneFixesInCliqueEntry(cliqueEntry_[j])) |
7474 | solval += value; |
7475 | else |
7476 | solval -= value; |
7477 | } |
7478 | down = floor(solval+tolerance); |
7479 | up = ceil(solval-tolerance); |
7480 | int istackC,iway, istackR; |
7481 | int way[]={1,2,1}; |
7482 | int feas[]={1,2,4}; |
7483 | int feasible=0; |
7484 | int notFeasible; |
7485 | for (iway=0;iway<3;iway ++) { |
7486 | int fixThis=0; |
7487 | stackC[0]=j; |
7488 | markC[j]=way[iway]; |
7489 | if (way[iway]==1) { |
7490 | movement=down-colUpper[j]; |
7491 | assert(movement<-0.99999); |
7492 | down=colLower[j]; |
7493 | } else { |
7494 | movement=up-colLower[j]; |
7495 | assert(movement>0.99999); |
7496 | up=colUpper[j]; |
7497 | } |
7498 | nstackC=1; |
7499 | nstackR=0; |
7500 | saveL[0]=colLower[j]; |
7501 | saveU[0]=colUpper[j]; |
7502 | assert (saveU[0]>saveL[0]); |
7503 | notFeasible=0; |
7504 | if (movement<0.0) { |
7505 | colUpper[j] += movement; |
7506 | colUpper[j] = floor(colUpper[j]+0.5); |
7507 | #ifdef PRINT_DEBUG |
7508 | printf("** Trying %d down to 0\n",j); |
7509 | #endif |
7510 | } else { |
7511 | colLower[j] += movement; |
7512 | colLower[j] = floor(colLower[j]+0.5); |
7513 | #ifdef PRINT_DEBUG |
7514 | printf("** Trying %d up to 1\n",j); |
7515 | #endif |
7516 | } |
7517 | if (fabs(colUpper[j]-colLower[j])<1.0e-6) |
7518 | markC[j]=3; |
7519 | istackC=0; |
7520 | |
7521 | for (k=columnStart[j];k<columnStart[j]+columnLength[j];k++) { |
7522 | int irow = row[k]; |
7523 | value = columnElements[k]; |
7524 | if (markR[irow]==-1) { |
7525 | stackR[nstackR]=irow; |
7526 | markR[irow]=nstackR; |
7527 | saveMin[nstackR]=minR[irow]; |
7528 | saveMax[nstackR]=maxR[irow]; |
7529 | nstackR++; |
7530 | } else if (markR[irow]==-2) { |
7531 | continue; |
7532 | } |
7533 | |
7534 | if (movement>0.0) { |
7535 | |
7536 | if (value>0.0) { |
7537 | |
7538 | if (minR[irow]>-1.0e10) |
7539 | minR[irow] += value; |
7540 | if (minR[irow]>rowUpper[irow]+1.0e-5) { |
7541 | notFeasible=1; |
7542 | istackC=1; |
7543 | break; |
7544 | } |
7545 | } else { |
7546 | |
7547 | if (maxR[irow]<1.0e10) |
7548 | maxR[irow] += value; |
7549 | if (maxR[irow]<rowLower[irow]-1.0e-5) { |
7550 | notFeasible=1; |
7551 | istackC=1; |
7552 | break; |
7553 | } |
7554 | } |
7555 | } else { |
7556 | |
7557 | if (value<0.0) { |
7558 | |
7559 | if (minR[irow]>-1.0e10) |
7560 | minR[irow] -= value; |
7561 | if (minR[irow]>rowUpper[irow]+1.0e-5) { |
7562 | notFeasible=1; |
7563 | istackC=1; |
7564 | break; |
7565 | } |
7566 | } else { |
7567 | |
7568 | if (maxR[irow]<1.0e10) |
7569 | maxR[irow] -= value; |
7570 | if (maxR[irow]<rowLower[irow]-1.0e-5) { |
7571 | notFeasible=1; |
7572 | istackC=1; |
7573 | break; |
7574 | } |
7575 | } |
7576 | } |
7577 | } |
7578 | while (istackC<nstackC&&nstackC<maxStack) { |
7579 | int jway; |
7580 | int jcol =stackC[istackC]; |
7581 | jway=markC[jcol]; |
7582 | |
7583 | if (jway==3&&istackC) { |
7584 | |
7585 | |
7586 | |
7587 | } |
7588 | |
7589 | if (oneFixStart_&&oneFixStart_[jcol]>=0) { |
7590 | int start; |
7591 | int end; |
7592 | if (colLower[jcol]>saveL[istackC]) { |
7593 | |
7594 | start = oneFixStart_[jcol]; |
7595 | end = zeroFixStart_[jcol]; |
7596 | } else { |
7597 | assert (colUpper[jcol]<saveU[istackC]); |
7598 | |
7599 | start = zeroFixStart_[jcol]; |
7600 | end = endFixStart_[jcol]; |
7601 | } |
7602 | for (int i=start;i<end;i++) { |
7603 | int iClique = whichClique_[i]; |
7604 | for (int k=cliqueStart_[iClique];k<cliqueStart_[iClique+1];k++) { |
7605 | int kcol = sequenceInCliqueEntry(cliqueEntry_[k]); |
7606 | if (jcol==kcol) |
7607 | continue; |
7608 | int kway = oneFixesInCliqueEntry(cliqueEntry_[k]); |
7609 | if (kcol!=jcol) { |
7610 | if (!markC[kcol]) { |
7611 | |
7612 | if (nstackC<2*maxStack) { |
7613 | markC[kcol] = 3; |
7614 | fixThis++; |
7615 | stackC[nstackC]=kcol; |
7616 | saveL[nstackC]=colLower[kcol]; |
7617 | saveU[nstackC]=colUpper[kcol]; |
7618 | assert (saveU[nstackC]>saveL[nstackC]); |
7619 | nstackC++; |
7620 | if (!kway) { |
7621 | |
7622 | colLower[kcol]=1.0; |
7623 | |
7624 | for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
7625 | krow = row[jj]; |
7626 | value = columnElements[jj]; |
7627 | if (markR[krow]==-1) { |
7628 | stackR[nstackR]=krow; |
7629 | markR[krow]=nstackR; |
7630 | saveMin[nstackR]=minR[krow]; |
7631 | saveMax[nstackR]=maxR[krow]; |
7632 | nstackR++; |
7633 | } else if (markR[krow]==-2) { |
7634 | continue; |
7635 | } |
7636 | |
7637 | |
7638 | if (value>0.0) { |
7639 | |
7640 | if (minR[krow]>-1.0e10) |
7641 | minR[krow] += value; |
7642 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
7643 | colUpper[kcol]=-1.0e50; |
7644 | break; |
7645 | } |
7646 | } else { |
7647 | |
7648 | if (maxR[krow]<1.0e10) |
7649 | maxR[krow] += value; |
7650 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
7651 | notFeasible=1; |
7652 | break; |
7653 | } |
7654 | } |
7655 | } |
7656 | } else { |
7657 | |
7658 | colUpper[kcol]=0.0; |
7659 | |
7660 | for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
7661 | krow = row[jj]; |
7662 | value = columnElements[jj]; |
7663 | if (markR[krow]==-1) { |
7664 | stackR[nstackR]=krow; |
7665 | markR[krow]=nstackR; |
7666 | saveMin[nstackR]=minR[krow]; |
7667 | saveMax[nstackR]=maxR[krow]; |
7668 | nstackR++; |
7669 | } else if (markR[krow]==-2) { |
7670 | continue; |
7671 | } |
7672 | |
7673 | |
7674 | if (value<0.0) { |
7675 | |
7676 | if (minR[krow]>-1.0e10) |
7677 | minR[krow] -= value; |
7678 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
7679 | notFeasible=1; |
7680 | break; |
7681 | } |
7682 | } else { |
7683 | |
7684 | if (maxR[krow]<1.0e10) |
7685 | maxR[krow] -= value; |
7686 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
7687 | notFeasible=1; |
7688 | break; |
7689 | } |
7690 | } |
7691 | } |
7692 | } |
7693 | } |
7694 | } else if (markC[kcol]==1) { |
7695 | |
7696 | assert (!colUpper[kcol]); |
7697 | if (!kway) { |
7698 | |
7699 | notFeasible=1; |
7700 | break; |
7701 | } |
7702 | } else if (markC[kcol]==2) { |
7703 | |
7704 | assert (colLower[kcol]); |
7705 | if (kway) { |
7706 | |
7707 | notFeasible=1; |
7708 | break; |
7709 | } |
7710 | } else { |
7711 | |
7712 | assert (markC[kcol]==3); |
7713 | int jkway; |
7714 | if (colLower[kcol]) |
7715 | jkway=1; |
7716 | else |
7717 | jkway=0; |
7718 | if (kway==jkway) { |
7719 | |
7720 | notFeasible=1; |
7721 | break; |
7722 | } |
7723 | } |
7724 | } |
7725 | } |
7726 | if (notFeasible) |
7727 | break; |
7728 | } |
7729 | if (notFeasible) |
7730 | istackC=nstackC+1; |
7731 | } |
7732 | for (k=columnStart[jcol];k<columnStart[jcol]+columnLength[jcol];k++) { |
7733 | |
7734 | if (notFeasible) |
7735 | break; |
7736 | irow = row[k]; |
7737 | |
7738 | if (markR[irow]!=-2) { |
7739 | |
7740 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];kk++) { |
7741 | double moveUp=0.0; |
7742 | double moveDown=0.0; |
7743 | double newUpper=-1.0,newLower=1.0; |
7744 | kcol=column[kk]; |
7745 | bool onList = (markC[kcol]!=0); |
7746 | if (markC[kcol]!=3) { |
7747 | value2=rowElements[kk]; |
7748 | int markIt=markC[kcol]; |
7749 | if (value2 < 0.0) { |
7750 | if (colUpper[kcol] < 1e10 && (markIt&2)==0 && |
7751 | rowUpper[irow]<1.0e10) { |
7752 | dbound = colUpper[kcol]+ |
7753 | (rowUpper[irow]-minR[irow])/value2; |
7754 | if (dbound > colLower[kcol] + primalTolerance_) { |
7755 | if (intVar[kcol]) { |
7756 | markIt |= 2; |
7757 | newLower = ceil(dbound-primalTolerance_); |
7758 | } else { |
7759 | newLower=dbound; |
7760 | if (newLower+primalTolerance_>colUpper[kcol]&& |
7761 | newLower-primalTolerance_<=colUpper[kcol]) { |
7762 | newLower=colUpper[kcol]; |
7763 | markIt |= 2; |
7764 | markIt=3; |
7765 | } else { |
7766 | |
7767 | markIt=3; |
7768 | } |
7769 | } |
7770 | moveUp = newLower-colLower[kcol]; |
7771 | } |
7772 | } |
7773 | if (colLower[kcol] > -1e10 && (markIt&1)==0 && |
7774 | rowLower[irow]>-1.0e10) { |
7775 | dbound = colLower[kcol] + |
7776 | (rowLower[irow]-maxR[irow])/value2; |
7777 | if (dbound < colUpper[kcol] - primalTolerance_) { |
7778 | if (intVar[kcol]) { |
7779 | markIt |= 1; |
7780 | newUpper = floor(dbound+primalTolerance_); |
7781 | } else { |
7782 | newUpper=dbound; |
7783 | if (newUpper-primalTolerance_<colLower[kcol]&& |
7784 | newUpper+primalTolerance_>=colLower[kcol]) { |
7785 | newUpper=colLower[kcol]; |
7786 | markIt |= 1; |
7787 | markIt=3; |
7788 | } else { |
7789 | |
7790 | markIt=3; |
7791 | } |
7792 | } |
7793 | moveDown = newUpper-colUpper[kcol]; |
7794 | } |
7795 | } |
7796 | } else { |
7797 | |
7798 | if (colUpper[kcol] < 1e10 && (markIt&2)==0 && |
7799 | rowLower[irow]>-1.0e10) { |
7800 | dbound = colUpper[kcol] + |
7801 | (rowLower[irow]-maxR[irow])/value2; |
7802 | if (dbound > colLower[kcol] + primalTolerance_) { |
7803 | if (intVar[kcol]) { |
7804 | markIt |= 2; |
7805 | newLower = ceil(dbound-primalTolerance_); |
7806 | } else { |
7807 | newLower=dbound; |
7808 | if (newLower+primalTolerance_>colUpper[kcol]&& |
7809 | newLower-primalTolerance_<=colUpper[kcol]) { |
7810 | newLower=colUpper[kcol]; |
7811 | markIt |= 2; |
7812 | markIt=3; |
7813 | } else { |
7814 | |
7815 | markIt=3; |
7816 | } |
7817 | } |
7818 | moveUp = newLower-colLower[kcol]; |
7819 | } |
7820 | } |
7821 | if (colLower[kcol] > -1e10 && (markIt&1)==0 && |
7822 | rowUpper[irow]<1.0e10) { |
7823 | dbound = colLower[kcol] + |
7824 | (rowUpper[irow]-minR[irow])/value2; |
7825 | if (dbound < colUpper[kcol] - primalTolerance_) { |
7826 | if (intVar[kcol]) { |
7827 | markIt |= 1; |
7828 | newUpper = floor(dbound+primalTolerance_); |
7829 | } else { |
7830 | newUpper=dbound; |
7831 | if (newUpper-primalTolerance_<colLower[kcol]&& |
7832 | newUpper+primalTolerance_>=colLower[kcol]) { |
7833 | newUpper=colLower[kcol]; |
7834 | markIt |= 1; |
7835 | markIt=3; |
7836 | } else { |
7837 | |
7838 | markIt=3; |
7839 | } |
7840 | } |
7841 | moveDown = newUpper-colUpper[kcol]; |
7842 | } |
7843 | } |
7844 | } |
7845 | if (nstackC<2*maxStack) { |
7846 | markC[kcol] = markIt; |
7847 | } |
7848 | if (moveUp&&nstackC<2*maxStack) { |
7849 | fixThis++; |
7850 | #ifdef PRINT_DEBUG |
7851 | printf("lower bound on %d increased from %g to %g by row %d %g %g\n",kcol,colLower[kcol],newLower,irow,rowLower[irow],rowUpper[irow]); |
7852 | value=0.0; |
7853 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
7854 | int ii=column[jj]; |
7855 | if (colUpper[ii]-colLower[ii]>primalTolerance_) { |
7856 | printf("(%d, %g) ",ii,rowElements[jj]); |
7857 | } else { |
7858 | value += rowElements[jj]*colLower[ii]; |
7859 | } |
7860 | } |
7861 | printf(" - fixed %g\n",value); |
7862 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
7863 | int ii=column[jj]; |
7864 | if (colUpper[ii]-colLower[ii]<primalTolerance_) { |
7865 | printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]); |
7866 | } |
7867 | } |
7868 | printf("\n"); |
7869 | #endif |
7870 | if (!onList) { |
7871 | stackC[nstackC]=kcol; |
7872 | saveL[nstackC]=colLower[kcol]; |
7873 | saveU[nstackC]=colUpper[kcol]; |
7874 | assert (saveU[nstackC]>saveL[nstackC]); |
7875 | nstackC++; |
7876 | onList=true; |
7877 | } |
7878 | if (intVar[kcol]) |
7879 | newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4)); |
7880 | colLower[kcol]=newLower; |
7881 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
7882 | markC[kcol]=3; |
7883 | } |
7884 | |
7885 | for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
7886 | krow = row[jj]; |
7887 | value = columnElements[jj]; |
7888 | if (markR[krow]==-1) { |
7889 | stackR[nstackR]=krow; |
7890 | markR[krow]=nstackR; |
7891 | saveMin[nstackR]=minR[krow]; |
7892 | saveMax[nstackR]=maxR[krow]; |
7893 | nstackR++; |
7894 | } else if (markR[krow]==-2) { |
7895 | continue; |
7896 | } |
7897 | |
7898 | |
7899 | if (value>0.0) { |
7900 | |
7901 | if (minR[krow]>-1.0e10) |
7902 | minR[krow] += value*moveUp; |
7903 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
7904 | colUpper[kcol]=-1.0e50; |
7905 | break; |
7906 | } |
7907 | } else { |
7908 | |
7909 | if (maxR[krow]<1.0e10) |
7910 | maxR[krow] += value*moveUp; |
7911 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
7912 | colUpper[kcol]=-1.0e50; |
7913 | break; |
7914 | } |
7915 | } |
7916 | } |
7917 | } |
7918 | if (moveDown&&nstackC<2*maxStack) { |
7919 | fixThis++; |
7920 | #ifdef PRINT_DEBUG |
7921 | printf("upper bound on %d decreased from %g to %g by row %d %g %g\n",kcol,colUpper[kcol],newUpper,irow,rowLower[irow],rowUpper[irow]); |
7922 | value=0.0; |
7923 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
7924 | int ii=column[jj]; |
7925 | if (colUpper[ii]-colLower[ii]>primalTolerance_) { |
7926 | printf("(%d, %g) ",ii,rowElements[jj]); |
7927 | } else { |
7928 | value += rowElements[jj]*colLower[ii]; |
7929 | } |
7930 | } |
7931 | printf(" - fixed %g\n",value); |
7932 | for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) { |
7933 | int ii=column[jj]; |
7934 | if (colUpper[ii]-colLower[ii]<primalTolerance_) { |
7935 | printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]); |
7936 | } |
7937 | } |
7938 | printf("\n"); |
7939 | #endif |
7940 | if (!onList) { |
7941 | stackC[nstackC]=kcol; |
7942 | saveL[nstackC]=colLower[kcol]; |
7943 | saveU[nstackC]=colUpper[kcol]; |
7944 | assert (saveU[nstackC]>saveL[nstackC]); |
7945 | nstackC++; |
7946 | onList=true; |
7947 | } |
7948 | if (intVar[kcol]) |
7949 | newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4)); |
7950 | colUpper[kcol]=newUpper; |
7951 | if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) { |
7952 | markC[kcol]=3; |
7953 | } |
7954 | |
7955 | for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) { |
7956 | krow = row[jj]; |
7957 | value = columnElements[jj]; |
7958 | if (markR[krow]==-1) { |
7959 | stackR[nstackR]=krow; |
7960 | markR[krow]=nstackR; |
7961 | saveMin[nstackR]=minR[krow]; |
7962 | saveMax[nstackR]=maxR[krow]; |
7963 | nstackR++; |
7964 | } else if (markR[krow]==-2) { |
7965 | continue; |
7966 | } |
7967 | |
7968 | |
7969 | if (value<0.0) { |
7970 | |
7971 | if (minR[krow]>-1.0e10) |
7972 | minR[krow] += value*moveDown; |
7973 | if (minR[krow]>rowUpper[krow]+1.0e-5) { |
7974 | colUpper[kcol]=-1.0e50; |
7975 | break; |
7976 | } |
7977 | } else { |
7978 | |
7979 | if (maxR[krow]<1.0e10) |
7980 | maxR[krow] += value*moveDown; |
7981 | if (maxR[krow]<rowLower[krow]-1.0e-5) { |
7982 | colUpper[kcol]=-1.0e50; |
7983 | break; |
7984 | } |
7985 | } |
7986 | } |
7987 | } |
7988 | if (colLower[kcol]>colUpper[kcol]+primalTolerance_) { |
7989 | notFeasible=1;; |
7990 | k=columnStart[jcol]+columnLength[jcol]; |
7991 | istackC=nstackC+1; |
7992 | #ifdef PRINT_DEBUG |
7993 | printf("** not feasible this way\n"); |
7994 | #endif |
7995 | break; |
7996 | } |
7997 | } |
7998 | } |
7999 | } |
8000 | } |
8001 | istackC++; |
8002 | } |
8003 | if (!notFeasible) { |
8004 | feasible |= feas[iway]; |
8005 | } else if (iway==1&&feasible==0) { |
8006 | |
8007 | ninfeas=1; |
8008 | j=nCols-1; |
8009 | iLook=nLook; |
8010 | ipass=maxPass; |
8011 | break; |
8012 | } |
8013 | if (iway==2||(iway==1&&feasible==2)) { |
8014 | |
8015 | iway=3; |
8016 | nfixed++; |
8017 | if (mode_) { |
8018 | OsiColCut cc; |
8019 | int nTot=0,nFix=0,nInt=0; |
8020 | bool ifCut=false; |
8021 | for (istackC=0;istackC<nstackC;istackC++) { |
8022 | int icol=stackC[istackC]; |
8023 | if (intVar[icol]) { |
8024 | if (colUpper[icol]<currentColUpper[icol]-1.0e-4) { |
8025 | element[nFix]=colUpper[icol]; |
8026 | index[nFix++]=icol; |
8027 | nInt++; |
8028 | if (colsol[icol]>colUpper[icol]+primalTolerance_) { |
8029 | ifCut=true; |
8030 | anyColumnCuts=true; |
8031 | } |
8032 | } |
8033 | } |
8034 | } |
8035 | if (nFix) { |
8036 | nTot=nFix; |
8037 | cc.setUbs(nFix,index,element); |
8038 | nFix=0; |
8039 | } |
8040 | for (istackC=0;istackC<nstackC;istackC++) { |
8041 | int icol=stackC[istackC]; |
8042 | if (intVar[icol]) { |
8043 | if (colLower[icol]>currentColLower[icol]+1.0e-4) { |
8044 | element[nFix]=colLower[icol]; |
8045 | index[nFix++]=icol; |
8046 | nInt++; |
8047 | if (colsol[icol]<colLower[icol]-primalTolerance_) { |
8048 | ifCut=true; |
8049 | anyColumnCuts=true; |
8050 | } |
8051 | } |
8052 | } |
8053 | } |
8054 | if (nFix) { |
8055 | nTot+=nFix; |
8056 | cc.setLbs(nFix,index,element); |
8057 | } |
8058 | |
8059 | if (nInt) { |
8060 | if (ifCut) { |
8061 | cc.setEffectiveness(100.0); |
8062 | } else { |
8063 | cc.setEffectiveness(1.0e-5); |
8064 | } |
8065 | #ifdef CGL_DEBUG |
8066 | checkBounds(debugger,cc); |
8067 | #endif |
8068 | cs.insert(cc); |
8069 | } |
8070 | } |
8071 | for (istackC=0;istackC<nstackC;istackC++) { |
8072 | int icol=stackC[istackC]; |
8073 | if (colUpper[icol]-colLower[icol]>primalTolerance_) { |
8074 | markC[icol]=0; |
8075 | } else { |
8076 | markC[icol]=3; |
8077 | } |
8078 | } |
8079 | for (istackR=0;istackR<nstackR;istackR++) { |
8080 | int irow=stackR[istackR]; |
8081 | markR[irow]=-1; |
8082 | } |
8083 | } else { |
8084 | |
8085 | |
8086 | if (iway==0) { |
8087 | nstackC0=CoinMin(nstackC,maxStack); |
8088 | if (notFeasible) { |
8089 | nstackC0=0; |
8090 | } else { |
8091 | for (istackC=0;istackC<nstackC0;istackC++) { |
8092 | int icol=stackC[istackC]; |
8093 | stackC0[istackC]=icol; |
8094 | lo0[istackC]=colLower[icol]; |
8095 | up0[istackC]=colUpper[icol]; |
8096 | } |
8097 | } |
8098 | |
8099 | assert (iway==0); |
8100 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
8101 | int icol=stackC[istackC]; |
8102 | double oldU=saveU[istackC]; |
8103 | double oldL=saveL[istackC]; |
8104 | colUpper[icol]=oldU; |
8105 | colLower[icol]=oldL; |
8106 | markC[icol]=0; |
8107 | } |
8108 | for (istackR=0;istackR<nstackR;istackR++) { |
8109 | int irow=stackR[istackR]; |
8110 | |
8111 | if ((rowCuts&2)!=0) { |
8112 | bool ifCut=anyColumnCuts; |
8113 | double gap = rowUpper[irow]-maxR[irow]; |
8114 | double sum=0.0; |
8115 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
8116 | |
8117 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8118 | kk++) { |
8119 | sum += rowElements[kk]*colsol[column[kk]]; |
8120 | } |
8121 | if (sum-gap*colsol[j]>maxR[irow]+primalTolerance_||info->strengthenRow) { |
8122 | |
8123 | |
8124 | |
8125 | int * index = reinterpret_cast<int *>(saveL); |
8126 | double * element = saveU; |
8127 | int n=0; |
8128 | bool coefficientExists=false; |
8129 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8130 | kk++) { |
8131 | if (column[kk]!=j) { |
8132 | index[n]=column[kk]; |
8133 | element[n++]=rowElements[kk]; |
8134 | } else { |
8135 | double value=rowElements[kk]-gap; |
8136 | if (fabs(value)>1.0e-12) { |
8137 | index[n]=column[kk]; |
8138 | element[n++]=value; |
8139 | } |
8140 | coefficientExists=true; |
8141 | } |
8142 | } |
8143 | if (!coefficientExists) { |
8144 | index[n]=j; |
8145 | element[n++]=-gap; |
8146 | } |
8147 | OsiRowCut rc; |
8148 | rc.setLb(-COIN_DBL_MAX); |
8149 | rc.setUb(rowUpper[irow]-gap*(colLower[j]+1.0)); |
8150 | |
8151 | rc.setEffectiveness((sum-gap*colsol[j]-maxR[irow])/gap); |
8152 | if (rc.effectiveness()>needEffectiveness) { |
8153 | rc.setRow(n,index,element,false); |
8154 | #ifdef CGL_DEBUG |
8155 | if (debugger) assert(!debugger->invalidCut(rc)); |
8156 | #endif |
8157 | |
8158 | |
8159 | |
8160 | #ifdef STRENGTHEN_PRINT |
8161 | { |
8162 | printf("9Cut %g <= ",rc.lb()); |
8163 | int k; |
8164 | for ( k=0;k<n;k++) { |
8165 | int iColumn = index[k]; |
8166 | printf("%g*",element[k]); |
8167 | if (si.isInteger(iColumn)) |
8168 | printf("i%d ",iColumn); |
8169 | else |
8170 | printf("x%d ",iColumn); |
8171 | } |
8172 | printf("<= %g\n",rc.ub()); |
8173 | printf("Row %g <= ",rowLower[irow]); |
8174 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
8175 | int iColumn = column[k]; |
8176 | printf("%g*",rowElements[k]); |
8177 | if (si.isInteger(iColumn)) |
8178 | printf("i%d ",iColumn); |
8179 | else |
8180 | printf("x%d ",iColumn); |
8181 | } |
8182 | printf("<= %g\n",rowUpper[irow]); |
8183 | } |
8184 | #endif |
8185 | rowCut.addCutIfNotDuplicate(rc,irow); |
8186 | } |
8187 | } |
8188 | } |
8189 | gap = minR[irow]-rowLower[irow]; |
8190 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
8191 | |
8192 | if (!sum) { |
8193 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8194 | kk++) { |
8195 | sum += rowElements[kk]*colsol[column[kk]]; |
8196 | } |
8197 | } |
8198 | if (sum+gap*colsol[j]<minR[irow]+primalTolerance_||info->strengthenRow) { |
8199 | |
8200 | |
8201 | |
8202 | int * index = reinterpret_cast<int *>(saveL); |
8203 | double * element = saveU; |
8204 | int n=0; |
8205 | bool coefficientExists=false; |
8206 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8207 | kk++) { |
8208 | if (column[kk]!=j) { |
8209 | index[n]=column[kk]; |
8210 | element[n++]=rowElements[kk]; |
8211 | } else { |
8212 | double value=rowElements[kk]+gap; |
8213 | if (fabs(value)>1.0e-12) { |
8214 | index[n]=column[kk]; |
8215 | element[n++]=value; |
8216 | } |
8217 | coefficientExists=true; |
8218 | } |
8219 | } |
8220 | if (!coefficientExists) { |
8221 | index[n]=j; |
8222 | element[n++]=gap; |
8223 | } |
8224 | OsiRowCut rc; |
8225 | rc.setLb(rowLower[irow]+gap*(colLower[j]+1.0)); |
8226 | rc.setUb(COIN_DBL_MAX); |
8227 | |
8228 | rc.setEffectiveness((minR[irow]-sum-gap*colsol[j])/gap); |
8229 | if (rc.effectiveness()>needEffectiveness) { |
8230 | rc.setRow(n,index,element,false); |
8231 | #ifdef CGL_DEBUG |
8232 | if (debugger) assert(!debugger->invalidCut(rc)); |
8233 | #endif |
8234 | |
8235 | |
8236 | #ifdef STRENGTHEN_PRINT |
8237 | { |
8238 | printf("10Cut %g <= ",rc.lb()); |
8239 | int k; |
8240 | for ( k=0;k<n;k++) { |
8241 | int iColumn = index[k]; |
8242 | printf("%g*",element[k]); |
8243 | if (si.isInteger(iColumn)) |
8244 | printf("i%d ",iColumn); |
8245 | else |
8246 | printf("x%d ",iColumn); |
8247 | } |
8248 | printf("<= %g\n",rc.ub()); |
8249 | printf("Row %g <= ",rowLower[irow]); |
8250 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
8251 | int iColumn = column[k]; |
8252 | printf("%g*",rowElements[k]); |
8253 | if (si.isInteger(iColumn)) |
8254 | printf("i%d ",iColumn); |
8255 | else |
8256 | printf("x%d ",iColumn); |
8257 | } |
8258 | printf("<= %g\n",rowUpper[irow]); |
8259 | } |
8260 | #endif |
8261 | rowCut.addCutIfNotDuplicate(rc,irow); |
8262 | } |
8263 | } |
8264 | } |
8265 | } |
8266 | minR[irow]=saveMin[istackR]; |
8267 | maxR[irow]=saveMax[istackR]; |
8268 | markR[irow]=-1; |
8269 | } |
8270 | } else { |
8271 | if (iway==1&&feasible==3) { |
8272 | iway=3; |
8273 | |
8274 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
8275 | int icol=stackC[istackC]; |
8276 | markC[icol]=istackC+1000; |
8277 | } |
8278 | if (mode_) { |
8279 | OsiColCut cc; |
8280 | int nTot=0,nFix=0,nInt=0; |
8281 | bool ifCut=false; |
8282 | for (istackC=0;istackC<nstackC0;istackC++) { |
8283 | int icol=stackC0[istackC]; |
8284 | int istackC1=markC[icol]-1000; |
8285 | if (istackC1>=0) { |
8286 | if (CoinMin(lo0[istackC],colLower[icol])>saveL[istackC1]+1.0e-4) { |
8287 | saveL[istackC1]=CoinMin(lo0[istackC],colLower[icol]); |
8288 | if (intVar[icol]) { |
8289 | element[nFix]=saveL[istackC1]; |
8290 | index[nFix++]=icol; |
8291 | nInt++; |
8292 | if (colsol[icol]<saveL[istackC1]-primalTolerance_) |
8293 | ifCut=true; |
8294 | } |
8295 | nfixed++; |
8296 | } |
8297 | } |
8298 | } |
8299 | if (nFix) { |
8300 | nTot=nFix; |
8301 | cc.setLbs(nFix,index,element); |
8302 | nFix=0; |
8303 | } |
8304 | for (istackC=0;istackC<nstackC0;istackC++) { |
8305 | int icol=stackC0[istackC]; |
8306 | int istackC1=markC[icol]-1000; |
8307 | if (istackC1>=0) { |
8308 | if (CoinMax(up0[istackC],colUpper[icol])<saveU[istackC1]-1.0e-4) { |
8309 | saveU[istackC1]=CoinMax(up0[istackC],colUpper[icol]); |
8310 | if (intVar[icol]) { |
8311 | element[nFix]=saveU[istackC1]; |
8312 | index[nFix++]=icol; |
8313 | nInt++; |
8314 | if (colsol[icol]>saveU[istackC1]+primalTolerance_) |
8315 | ifCut=true; |
8316 | } |
8317 | nfixed++; |
8318 | } |
8319 | } |
8320 | } |
8321 | if (nFix) { |
8322 | nTot+=nFix; |
8323 | cc.setUbs(nFix,index,element); |
8324 | } |
8325 | |
8326 | if (nInt) { |
8327 | if (ifCut) { |
8328 | cc.setEffectiveness(100.0); |
8329 | } else { |
8330 | cc.setEffectiveness(1.0e-5); |
8331 | } |
8332 | #ifdef CGL_DEBUG |
8333 | checkBounds(debugger,cc); |
8334 | #endif |
8335 | cs.insert(cc); |
8336 | } |
8337 | } |
8338 | } |
8339 | |
8340 | for (istackC=nstackC-1;istackC>=0;istackC--) { |
8341 | int icol=stackC[istackC]; |
8342 | double oldU=saveU[istackC]; |
8343 | double oldL=saveL[istackC]; |
8344 | colUpper[icol]=oldU; |
8345 | colLower[icol]=oldL; |
8346 | if (oldU>oldL+1.0e-4) |
8347 | markC[icol]=0; |
8348 | else |
8349 | markC[icol]=3; |
8350 | } |
8351 | for (istackR=0;istackR<nstackR;istackR++) { |
8352 | int irow=stackR[istackR]; |
8353 | |
8354 | if ((rowCuts&2)!=0) { |
8355 | bool ifCut=anyColumnCuts; |
8356 | double gap = rowUpper[irow]-maxR[irow]; |
8357 | double sum=0.0; |
8358 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
8359 | |
8360 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8361 | kk++) { |
8362 | sum += rowElements[kk]*colsol[column[kk]]; |
8363 | } |
8364 | if (sum+gap*colsol[j]>rowUpper[irow]+primalTolerance_||info->strengthenRow) { |
8365 | |
8366 | |
8367 | |
8368 | int * index = reinterpret_cast<int *>(saveL); |
8369 | double * element = saveU; |
8370 | int n=0; |
8371 | bool coefficientExists=false; |
8372 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8373 | kk++) { |
8374 | if (column[kk]!=j) { |
8375 | index[n]=column[kk]; |
8376 | element[n++]=rowElements[kk]; |
8377 | } else { |
8378 | double value=rowElements[kk]+gap; |
8379 | if (fabs(value)>1.0e-12) { |
8380 | index[n]=column[kk]; |
8381 | element[n++]=value; |
8382 | } |
8383 | coefficientExists=true; |
8384 | } |
8385 | } |
8386 | if (!coefficientExists) { |
8387 | index[n]=j; |
8388 | element[n++]=gap; |
8389 | } |
8390 | OsiRowCut rc; |
8391 | rc.setLb(-COIN_DBL_MAX); |
8392 | rc.setUb(rowUpper[irow]+gap*(colUpper[j]-1.0)); |
8393 | |
8394 | rc.setEffectiveness((sum+gap*colsol[j]-rowUpper[irow])/gap); |
8395 | if (rc.effectiveness()>needEffectiveness) { |
8396 | rc.setRow(n,index,element,false); |
8397 | #ifdef CGL_DEBUG |
8398 | if (debugger) assert(!debugger->invalidCut(rc)); |
8399 | #endif |
8400 | |
8401 | |
8402 | #ifdef STRENGTHEN_PRINT |
8403 | { |
8404 | printf("11Cut %g <= ",rc.lb()); |
8405 | int k; |
8406 | for ( k=0;k<n;k++) { |
8407 | int iColumn = index[k]; |
8408 | printf("%g*",element[k]); |
8409 | if (si.isInteger(iColumn)) |
8410 | printf("i%d ",iColumn); |
8411 | else |
8412 | printf("x%d ",iColumn); |
8413 | } |
8414 | printf("<= %g\n",rc.ub()); |
8415 | printf("Row %g <= ",rowLower[irow]); |
8416 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
8417 | int iColumn = column[k]; |
8418 | printf("%g*",rowElements[k]); |
8419 | if (si.isInteger(iColumn)) |
8420 | printf("i%d ",iColumn); |
8421 | else |
8422 | printf("x%d ",iColumn); |
8423 | } |
8424 | printf("<= %g\n",rowUpper[irow]); |
8425 | } |
8426 | #endif |
8427 | rowCut.addCutIfNotDuplicate(rc,irow); |
8428 | } |
8429 | } |
8430 | } |
8431 | gap = minR[irow]-rowLower[irow]; |
8432 | if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) { |
8433 | |
8434 | if (!sum) { |
8435 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8436 | kk++) { |
8437 | sum += rowElements[kk]*colsol[column[kk]]; |
8438 | } |
8439 | } |
8440 | if (sum-gap*colsol[j]<rowLower[irow]+primalTolerance_||info->strengthenRow) { |
8441 | |
8442 | |
8443 | |
8444 | int * index = reinterpret_cast<int *>(saveL); |
8445 | double * element = saveU; |
8446 | int n=0; |
8447 | bool coefficientExists=false; |
8448 | for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow]; |
8449 | kk++) { |
8450 | if (column[kk]!=j) { |
8451 | index[n]=column[kk]; |
8452 | element[n++]=rowElements[kk]; |
8453 | } else { |
8454 | double value=rowElements[kk]-gap; |
8455 | if (fabs(value)>1.0e-12) { |
8456 | index[n]=column[kk]; |
8457 | element[n++]=value; |
8458 | } |
8459 | coefficientExists=true; |
8460 | } |
8461 | } |
8462 | if (!coefficientExists) { |
8463 | index[n]=j; |
8464 | element[n++]=-gap; |
8465 | } |
8466 | OsiRowCut rc; |
8467 | rc.setLb(rowLower[irow]-gap*(colUpper[j]-1)); |
8468 | rc.setUb(COIN_DBL_MAX); |
8469 | |
8470 | rc.setEffectiveness((rowLower[irow]-sum+gap*colsol[j])/gap); |
8471 | if (rc.effectiveness()>needEffectiveness) { |
8472 | rc.setRow(n,index,element,false); |
8473 | #ifdef CGL_DEBUG |
8474 | if (debugger) assert(!debugger->invalidCut(rc)); |
8475 | #endif |
8476 | |
8477 | |
8478 | #ifdef STRENGTHEN_PRINT |
8479 | { |
8480 | printf("12Cut %g <= ",rc.lb()); |
8481 | int k; |
8482 | for ( k=0;k<n;k++) { |
8483 | int iColumn = index[k]; |
8484 | printf("%g*",element[k]); |
8485 | if (si.isInteger(iColumn)) |
8486 | printf("i%d ",iColumn); |
8487 | else |
8488 | printf("x%d ",iColumn); |
8489 | } |
8490 | printf("<= %g\n",rc.ub()); |
8491 | printf("Row %g <= ",rowLower[irow]); |
8492 | for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) { |
8493 | int iColumn = column[k]; |
8494 | printf("%g*",rowElements[k]); |
8495 | if (si.isInteger(iColumn)) |
8496 | printf("i%d ",iColumn); |
8497 | else |
8498 | printf("x%d ",iColumn); |
8499 | } |
8500 | printf("<= %g\n",rowUpper[irow]); |
8501 | } |
8502 | #endif |
8503 | rowCut.addCutIfNotDuplicate(rc,irow); |
8504 | } |
8505 | } |
8506 | } |
8507 | } |
8508 | minR[irow]=saveMin[istackR]; |
8509 | maxR[irow]=saveMax[istackR]; |
8510 | markR[irow]=-1; |
8511 | } |
8512 | } |
8513 | } |
8514 | } |
8515 | } |
8516 | } |
8517 | delete [] stackC0; |
8518 | delete [] lo0; |
8519 | delete [] up0; |
8520 | delete [] tempL; |
8521 | delete [] tempU; |
8522 | delete [] markC; |
8523 | delete [] stackC; |
8524 | delete [] stackR; |
8525 | delete [] saveL; |
8526 | delete [] saveU; |
8527 | delete [] saveMin; |
8528 | delete [] saveMax; |
8529 | delete [] index; |
8530 | delete [] element; |
8531 | delete [] colsol; |
8532 | |
8533 | if (!ninfeas) { |
8534 | rowCut.addCuts(cs,info->strengthenRow,0); |
8535 | } |
8536 | delete [] array; |
8537 | abort(); |
8538 | return (ninfeas); |
8539 | } |
8540 | |
8541 | |
8542 | |
8543 | |
8544 | |
8545 | int CglProbing::snapshot ( const OsiSolverInterface & si, |
8546 | char * possible,bool withObjective) |
8547 | { |
8548 | deleteSnapshot(); |
8549 | |
8550 | |
8551 | numberColumns_=si.getNumCols(); |
8552 | numberRows_=si.getNumRows(); |
8553 | colLower_ = new double[numberColumns_]; |
8554 | colUpper_ = new double[numberColumns_]; |
8555 | CoinMemcpyN(si.getColLower(),numberColumns_,colLower_); |
8556 | CoinMemcpyN(si.getColUpper(),numberColumns_,colUpper_); |
8557 | rowLower_= new double [numberRows_+1]; |
8558 | rowUpper_= new double [numberRows_+1]; |
8559 | CoinMemcpyN(si.getRowLower(),numberRows_,rowLower_); |
8560 | CoinMemcpyN(si.getRowUpper(),numberRows_,rowUpper_); |
8561 | |
8562 | int i; |
8563 | if (possible) { |
8564 | for (i=0;i<numberRows_;i++) { |
8565 | if (!possible[i]) { |
8566 | rowLower_[i]=-COIN_DBL_MAX; |
8567 | rowUpper_[i]=COIN_DBL_MAX; |
8568 | } |
8569 | } |
8570 | } |
8571 | |
8572 | |
8573 | |
8574 | const char * intVarOriginal = si.getColType(true); |
8575 | char * intVar = CoinCopyOfArray(intVarOriginal,numberColumns_); |
8576 | numberIntegers_=0; |
8577 | number01Integers_=0; |
8578 | for (i=0;i<numberColumns_;i++) { |
8579 | if (intVar[i]) { |
8580 | numberIntegers_++; |
8581 | if (intVar[i]==1) { |
8582 | number01Integers_++; |
8583 | } |
8584 | } |
8585 | } |
8586 | |
8587 | rowCopy_ = new CoinPackedMatrix(*si.getMatrixByRow()); |
8588 | |
8589 | int * column = rowCopy_->getMutableIndices(); |
8590 | const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); |
8591 | const int * rowLength = rowCopy_->getVectorLengths(); |
8592 | double * rowElements = rowCopy_->getMutableElements(); |
8593 | |
8594 | int * column2 = new int[numberColumns_]; |
8595 | double * elements2 = new double[numberColumns_]; |
8596 | CoinBigIndex * rowStartPos = new CoinBigIndex [numberRows_]; |
8597 | for (int i=0;i<numberRows_;i++) { |
8598 | CoinBigIndex start = rowStart[i]; |
8599 | CoinBigIndex end = start + rowLength[i]; |
8600 | int nOther=0; |
8601 | for (CoinBigIndex j=start; j<end ; j++) { |
8602 | int iColumn = column[j]; |
8603 | double value = rowElements[j]; |
8604 | if (value<0.0) { |
8605 | rowElements[start]=value; |
8606 | column[start++]=iColumn; |
8607 | } else { |
8608 | elements2[nOther]=value; |
8609 | column2[nOther++]=iColumn; |
8610 | } |
8611 | } |
8612 | rowStartPos[i] = start; |
8613 | for (int k=0;k<nOther;k++) { |
8614 | rowElements[start]=elements2[k]; |
8615 | column[start++]=column2[k]; |
8616 | } |
8617 | } |
8618 | delete [] column2; |
8619 | delete [] elements2; |
8620 | |
8621 | int returnCode=0; |
8622 | int ninfeas= |
8623 | tighten(colLower_, colUpper_, column, rowElements, |
8624 | rowStart, NULL,rowLength, rowLower_, rowUpper_, |
8625 | numberRows_, numberColumns_, intVar, 5, primalTolerance_); |
8626 | delete [] rowStartPos; |
8627 | if (ninfeas) { |
8628 | |
8629 | returnCode = 1; |
8630 | } |
8631 | |
8632 | |
8633 | |
8634 | |
8635 | |
8636 | |
8637 | cutVector_ = new disaggregation [number01Integers_]; |
8638 | memset(cutVector_,0,number01Integers_*sizeof(disaggregation)); |
8639 | number01Integers_=0; |
8640 | for (i=0;i<numberColumns_;i++) { |
8641 | if (intVar[i]==1) |
8642 | cutVector_[number01Integers_++].sequence=i; |
8643 | } |
8644 | delete [] intVar; |
8645 | |
8646 | |
8647 | if (possible) { |
8648 | for (i=0;i<numberRows_;i++) { |
8649 | if (rowLower_[i]<-1.0e30&&rowUpper_[i]>1.0e30) |
8650 | possible[i]=0; |
8651 | } |
8652 | } |
8653 | int * index = new int[numberRows_]; |
8654 | int nDrop=0,nKeep=0; |
8655 | for (i=0;i<numberRows_;i++) { |
8656 | if (rowLower_[i]<-1.0e30&&rowUpper_[i]>1.0e30) { |
8657 | index[nDrop++]=i; |
8658 | } else { |
8659 | rowLower_[nKeep]=rowLower_[i]; |
8660 | rowUpper_[nKeep++]=rowUpper_[i]; |
8661 | } |
8662 | } |
8663 | numberRows_=nKeep; |
8664 | if (nDrop) |
8665 | rowCopy_->deleteRows(nDrop,index); |
8666 | delete [] index; |
8667 | if (withObjective) { |
8668 | |
8669 | int * columns = new int[numberColumns_]; |
8670 | double * elements = new double[numberColumns_]; |
8671 | int n=0; |
8672 | const double * objective = si.getObjCoefficients(); |
8673 | bool maximize = (si.getObjSense()==-1); |
8674 | for (i=0;i<numberColumns_;i++) { |
8675 | if (objective[i]) { |
8676 | elements[n]= (maximize) ? -objective[i] : objective[i]; |
8677 | columns[n++]=i; |
8678 | } |
8679 | } |
8680 | rowCopy_->appendRow(n,columns,elements); |
8681 | delete [] columns; |
8682 | delete [] elements; |
8683 | numberRows_++; |
8684 | } |
8685 | |
8686 | if (rowCopy_->getNumElements()) { |
8687 | columnCopy_=new CoinPackedMatrix(*rowCopy_,0,0,true); |
8688 | } else { |
8689 | columnCopy_=new CoinPackedMatrix(); |
8690 | } |
8691 | |
8692 | columnCopy_->setDimensions(numberRows_,numberColumns_); |
8693 | rowCopy_->setDimensions(numberRows_,numberColumns_); |
8694 | return returnCode; |
8695 | } |
8696 | |
8697 | void CglProbing::deleteSnapshot() |
8698 | { |
8699 | delete [] rowLower_; |
8700 | delete [] rowUpper_; |
8701 | delete [] colLower_; |
8702 | delete [] colUpper_; |
8703 | delete rowCopy_; |
8704 | delete columnCopy_; |
8705 | rowCopy_=NULL; |
8706 | columnCopy_=NULL; |
8707 | rowLower_=NULL; |
8708 | rowUpper_=NULL; |
8709 | colLower_=NULL; |
8710 | colUpper_=NULL; |
8711 | int i; |
8712 | for (i=0;i<number01Integers_;i++) { |
8713 | delete [] cutVector_[i].index; |
8714 | } |
8715 | delete [] cutVector_; |
8716 | numberIntegers_=0; |
8717 | number01Integers_=0; |
8718 | cutVector_=NULL; |
8719 | } |
8720 | |
8721 | void CglProbing::setMode(int mode) |
8722 | { |
8723 | if (mode>=0&&mode<3) { |
8724 | |
8725 | mode_ &= ~15; |
8726 | mode_ |= mode; |
8727 | } |
8728 | } |
8729 | int CglProbing::getMode() const |
8730 | { |
8731 | return mode_&15; |
8732 | } |
8733 | |
8734 | void CglProbing::setMaxPass(int value) |
8735 | { |
8736 | if (value>0) |
8737 | maxPass_=value; |
8738 | } |
8739 | |
8740 | int CglProbing::getMaxPass() const |
8741 | { |
8742 | return maxPass_; |
8743 | } |
8744 | |
8745 | void CglProbing::setLogLevel(int value) |
8746 | { |
8747 | if (value>=0) |
8748 | logLevel_=value; |
8749 | } |
8750 | |
8751 | int CglProbing::getLogLevel() const |
8752 | { |
8753 | return logLevel_; |
8754 | } |
8755 | |
8756 | void CglProbing::setMaxProbe(int value) |
8757 | { |
8758 | if (value>=0) |
8759 | maxProbe_=value; |
8760 | } |
8761 | |
8762 | int CglProbing::getMaxProbe() const |
8763 | { |
8764 | return maxProbe_; |
8765 | } |
8766 | |
8767 | void CglProbing::setMaxLook(int value) |
8768 | { |
8769 | if (value>=0) |
8770 | maxStack_=value; |
8771 | } |
8772 | |
8773 | int CglProbing::getMaxLook() const |
8774 | { |
8775 | return maxStack_; |
8776 | } |
8777 | |
8778 | void CglProbing::setMaxElements(int value) |
8779 | { |
8780 | if (value>0) |
8781 | maxElements_=value; |
8782 | } |
8783 | |
8784 | int CglProbing::getMaxElements() const |
8785 | { |
8786 | return maxElements_; |
8787 | } |
8788 | |
8789 | void CglProbing::setMaxPassRoot(int value) |
8790 | { |
8791 | if (value>0) |
8792 | maxPassRoot_=value; |
8793 | } |
8794 | |
8795 | int CglProbing::getMaxPassRoot() const |
8796 | { |
8797 | return maxPassRoot_; |
8798 | } |
8799 | |
8800 | void CglProbing::setMaxProbeRoot(int value) |
8801 | { |
8802 | if (value>0) |
8803 | maxProbeRoot_=value; |
8804 | } |
8805 | |
8806 | int CglProbing::getMaxProbeRoot() const |
8807 | { |
8808 | return maxProbeRoot_; |
8809 | } |
8810 | |
8811 | void CglProbing::setMaxLookRoot(int value) |
8812 | { |
8813 | if (value>0) |
8814 | maxStackRoot_=value; |
8815 | } |
8816 | |
8817 | int CglProbing::getMaxLookRoot() const |
8818 | { |
8819 | return maxStackRoot_; |
8820 | } |
8821 | |
8822 | void CglProbing::setMaxElementsRoot(int value) |
8823 | { |
8824 | if (value>0) |
8825 | maxElementsRoot_=value; |
8826 | } |
8827 | |
8828 | int CglProbing::getMaxElementsRoot() const |
8829 | { |
8830 | return maxElementsRoot_; |
8831 | } |
8832 | |
8833 | void CglProbing::setUsingObjective(int yesNo) |
8834 | { |
8835 | usingObjective_=yesNo; |
8836 | } |
8837 | |
8838 | int CglProbing::getUsingObjective() const |
8839 | { |
8840 | return usingObjective_; |
8841 | } |
8842 | |
8843 | void CglProbing::setRowCuts(int type) |
8844 | { |
8845 | if (type>-5&&type<5) |
8846 | rowCuts_=type; |
8847 | } |
8848 | |
8849 | int CglProbing::rowCuts() const |
8850 | { |
8851 | return rowCuts_; |
8852 | } |
8853 | |
8854 | const double * CglProbing::tightLower() const |
8855 | { |
8856 | return colLower_; |
8857 | } |
8858 | |
8859 | const double * CglProbing::tightUpper() const |
8860 | { |
8861 | return colUpper_; |
8862 | } |
8863 | |
8864 | const double * CglProbing::relaxedRowLower() const |
8865 | { |
8866 | return rowLower_; |
8867 | } |
8868 | |
8869 | const double * CglProbing::relaxedRowUpper() const |
8870 | { |
8871 | return rowUpper_; |
8872 | } |
8873 | |
8874 | |
8875 | |
8876 | |
8877 | |
8878 | CglProbing::CglProbing () |
8879 | : |
8880 | CglCutGenerator(), |
8881 | primalTolerance_(1.0e-07), |
8882 | mode_(1), |
8883 | rowCuts_(1), |
8884 | maxPass_(3), |
8885 | logLevel_(0), |
8886 | maxProbe_(100), |
8887 | maxStack_(50), |
8888 | maxElements_(1000), |
8889 | maxPassRoot_(3), |
8890 | maxProbeRoot_(100), |
8891 | maxStackRoot_(50), |
8892 | maxElementsRoot_(10000), |
8893 | usingObjective_(0) |
8894 | { |
8895 | |
8896 | numberRows_=0; |
8897 | numberColumns_=0; |
8898 | rowCopy_=NULL; |
8899 | columnCopy_=NULL; |
8900 | rowLower_=NULL; |
8901 | rowUpper_=NULL; |
8902 | colLower_=NULL; |
8903 | colUpper_=NULL; |
8904 | numberIntegers_=0; |
8905 | number01Integers_=0; |
8906 | numberThisTime_=0; |
8907 | totalTimesCalled_=0; |
8908 | lookedAt_=NULL; |
8909 | cutVector_=NULL; |
8910 | numberCliques_=0; |
8911 | cliqueType_=NULL; |
8912 | cliqueStart_=NULL; |
8913 | cliqueEntry_=NULL; |
8914 | oneFixStart_=NULL; |
8915 | zeroFixStart_=NULL; |
8916 | endFixStart_=NULL; |
8917 | whichClique_=NULL; |
8918 | cliqueRow_=NULL; |
8919 | cliqueRowStart_=NULL; |
8920 | tightenBounds_=NULL; |
8921 | } |
8922 | |
8923 | |
8924 | |
8925 | |
8926 | CglProbing::CglProbing ( const CglProbing & rhs) |
8927 | : |
8928 | CglCutGenerator(rhs), |
8929 | primalTolerance_(rhs.primalTolerance_), |
8930 | mode_(rhs.mode_), |
8931 | rowCuts_(rhs.rowCuts_), |
8932 | maxPass_(rhs.maxPass_), |
8933 | logLevel_(rhs.logLevel_), |
8934 | maxProbe_(rhs.maxProbe_), |
8935 | maxStack_(rhs.maxStack_), |
8936 | maxElements_(rhs.maxElements_), |
8937 | maxPassRoot_(rhs.maxPassRoot_), |
8938 | maxProbeRoot_(rhs.maxProbeRoot_), |
8939 | maxStackRoot_(rhs.maxStackRoot_), |
8940 | maxElementsRoot_(rhs.maxElementsRoot_), |
8941 | usingObjective_(rhs.usingObjective_) |
8942 | { |
8943 | numberRows_=rhs.numberRows_; |
8944 | numberColumns_=rhs.numberColumns_; |
8945 | numberCliques_=rhs.numberCliques_; |
8946 | if (rhs.rowCopy_) { |
8947 | rowCopy_= new CoinPackedMatrix(*(rhs.rowCopy_)); |
8948 | columnCopy_= new CoinPackedMatrix(*(rhs.columnCopy_)); |
8949 | rowLower_=new double[numberRows_]; |
8950 | CoinMemcpyN(rhs.rowLower_,numberRows_,rowLower_); |
8951 | rowUpper_=new double[numberRows_]; |
8952 | CoinMemcpyN(rhs.rowUpper_,numberRows_,rowUpper_); |
8953 | colLower_=new double[numberColumns_]; |
8954 | CoinMemcpyN(rhs.colLower_,numberColumns_,colLower_); |
8955 | colUpper_=new double[numberColumns_]; |
8956 | CoinMemcpyN(rhs.colUpper_,numberColumns_,colUpper_); |
8957 | int i; |
8958 | numberIntegers_=rhs.numberIntegers_; |
8959 | number01Integers_=rhs.number01Integers_; |
8960 | cutVector_=new disaggregation [number01Integers_]; |
8961 | CoinMemcpyN(rhs.cutVector_,number01Integers_,cutVector_); |
8962 | for (i=0;i<number01Integers_;i++) { |
8963 | if (cutVector_[i].index) { |
8964 | cutVector_[i].index = CoinCopyOfArray(rhs.cutVector_[i].index,cutVector_[i].length); |
8965 | } |
8966 | } |
8967 | } else { |
8968 | rowCopy_=NULL; |
8969 | columnCopy_=NULL; |
8970 | rowLower_=NULL; |
8971 | rowUpper_=NULL; |
8972 | colLower_=NULL; |
8973 | colUpper_=NULL; |
8974 | numberIntegers_=0; |
8975 | number01Integers_=0; |
8976 | cutVector_=NULL; |
8977 | } |
8978 | numberThisTime_=rhs.numberThisTime_; |
8979 | totalTimesCalled_=rhs.totalTimesCalled_; |
8980 | if (numberColumns_) |
8981 | lookedAt_=CoinCopyOfArray(rhs.lookedAt_,numberColumns_); |
8982 | else |
8983 | lookedAt_ = NULL; |
8984 | if (numberCliques_) { |
8985 | cliqueType_ = new cliqueType [numberCliques_]; |
8986 | CoinMemcpyN(rhs.cliqueType_,numberCliques_,cliqueType_); |
8987 | cliqueStart_ = new int [numberCliques_+1]; |
8988 | CoinMemcpyN(rhs.cliqueStart_,(numberCliques_+1),cliqueStart_); |
8989 | int n = cliqueStart_[numberCliques_]; |
8990 | cliqueEntry_ = new cliqueEntry [n]; |
8991 | CoinMemcpyN(rhs.cliqueEntry_,n,cliqueEntry_); |
8992 | oneFixStart_ = new int [numberColumns_]; |
8993 | CoinMemcpyN(rhs.oneFixStart_,numberColumns_,oneFixStart_); |
8994 | zeroFixStart_ = new int [numberColumns_]; |
8995 | CoinMemcpyN(rhs.zeroFixStart_,numberColumns_,zeroFixStart_); |
8996 | endFixStart_ = new int [numberColumns_]; |
8997 | CoinMemcpyN(rhs.endFixStart_,numberColumns_,endFixStart_); |
8998 | #ifndef NDEBUG |
8999 | int n2=-1; |
9000 | for (int i=numberColumns_-1;i>=0;i--) { |
9001 | if (oneFixStart_[i]>=0) { |
9002 | n2=endFixStart_[i]; |
9003 | break; |
9004 | } |
9005 | } |
9006 | assert (n==n2); |
9007 | #endif |
9008 | whichClique_ = new int [n]; |
9009 | CoinMemcpyN(rhs.whichClique_,n,whichClique_); |
9010 | if (rhs.cliqueRowStart_) { |
9011 | cliqueRowStart_ = CoinCopyOfArray(rhs.cliqueRowStart_,numberRows_+1); |
9012 | n=cliqueRowStart_[numberRows_]; |
9013 | cliqueRow_ = CoinCopyOfArray(rhs.cliqueRow_,n); |
9014 | } else { |
9015 | cliqueRow_=NULL; |
9016 | cliqueRowStart_=NULL; |
9017 | } |
9018 | } else { |
9019 | cliqueType_=NULL; |
9020 | cliqueStart_=NULL; |
9021 | cliqueEntry_=NULL; |
9022 | oneFixStart_=NULL; |
9023 | zeroFixStart_=NULL; |
9024 | endFixStart_=NULL; |
9025 | cliqueRow_=NULL; |
9026 | cliqueRowStart_=NULL; |
9027 | whichClique_=NULL; |
9028 | } |
9029 | if (rhs.tightenBounds_) { |
9030 | assert (numberColumns_); |
9031 | tightenBounds_=CoinCopyOfArray(rhs.tightenBounds_,numberColumns_); |
9032 | } else { |
9033 | tightenBounds_=NULL; |
9034 | } |
9035 | } |
9036 | |
9037 | |
9038 | |
9039 | |
9040 | CglCutGenerator * |
9041 | CglProbing::clone() const |
9042 | { |
9043 | return new CglProbing(*this); |
9044 | } |
9045 | |
9046 | |
9047 | |
9048 | |
9049 | CglProbing::~CglProbing () |
9050 | { |
9051 | |
9052 | delete [] rowLower_; |
9053 | delete [] rowUpper_; |
9054 | delete [] colLower_; |
9055 | delete [] colUpper_; |
9056 | delete rowCopy_; |
9057 | delete columnCopy_; |
9058 | delete [] lookedAt_; |
9059 | delete [] cliqueType_; |
9060 | delete [] cliqueStart_; |
9061 | delete [] cliqueEntry_; |
9062 | delete [] oneFixStart_; |
9063 | delete [] zeroFixStart_; |
9064 | delete [] endFixStart_; |
9065 | delete [] whichClique_; |
9066 | delete [] cliqueRow_; |
9067 | delete [] cliqueRowStart_; |
9068 | if (cutVector_) { |
9069 | for (int i=0;i<number01Integers_;i++) { |
9070 | delete [] cutVector_[i].index; |
9071 | } |
9072 | delete [] cutVector_; |
9073 | } |
9074 | delete [] tightenBounds_; |
9075 | } |
9076 | |
9077 | |
9078 | |
9079 | |
9080 | CglProbing & |
9081 | CglProbing::operator=( |
9082 | const CglProbing& rhs) |
9083 | { |
9084 | if (this != &rhs) { |
9085 | CglCutGenerator::operator=(rhs); |
9086 | primalTolerance_=rhs.primalTolerance_; |
9087 | numberRows_=rhs.numberRows_; |
9088 | numberColumns_=rhs.numberColumns_; |
9089 | delete [] rowLower_; |
9090 | delete [] rowUpper_; |
9091 | delete [] colLower_; |
9092 | delete [] colUpper_; |
9093 | delete rowCopy_; |
9094 | delete columnCopy_; |
9095 | delete [] lookedAt_; |
9096 | delete [] cliqueType_; |
9097 | delete [] cliqueStart_; |
9098 | delete [] cliqueEntry_; |
9099 | delete [] oneFixStart_; |
9100 | delete [] zeroFixStart_; |
9101 | delete [] endFixStart_; |
9102 | delete [] whichClique_; |
9103 | delete [] cliqueRow_; |
9104 | delete [] cliqueRowStart_; |
9105 | delete [] tightenBounds_; |
9106 | mode_=rhs.mode_; |
9107 | rowCuts_=rhs.rowCuts_; |
9108 | maxPass_=rhs.maxPass_; |
9109 | logLevel_=rhs.logLevel_; |
9110 | maxProbe_=rhs.maxProbe_; |
9111 | maxStack_=rhs.maxStack_; |
9112 | maxElements_ = rhs.maxElements_; |
9113 | maxPassRoot_ = rhs.maxPassRoot_; |
9114 | maxProbeRoot_ = rhs.maxProbeRoot_; |
9115 | maxStackRoot_ = rhs.maxStackRoot_; |
9116 | maxElementsRoot_ = rhs.maxElementsRoot_; |
9117 | usingObjective_=rhs.usingObjective_; |
9118 | numberCliques_=rhs.numberCliques_; |
9119 | if (rhs.rowCopy_) { |
9120 | rowCopy_= new CoinPackedMatrix(*(rhs.rowCopy_)); |
9121 | columnCopy_= new CoinPackedMatrix(*(rhs.columnCopy_)); |
9122 | rowLower_=new double[numberRows_]; |
9123 | CoinMemcpyN(rhs.rowLower_,numberRows_,rowLower_); |
9124 | rowUpper_=new double[numberRows_]; |
9125 | CoinMemcpyN(rhs.rowUpper_,numberRows_,rowUpper_); |
9126 | colLower_=new double[numberColumns_]; |
9127 | CoinMemcpyN(rhs.colLower_,numberColumns_,colLower_); |
9128 | colUpper_=new double[numberColumns_]; |
9129 | CoinMemcpyN(rhs.colUpper_,numberColumns_,colUpper_); |
9130 | int i; |
9131 | numberIntegers_=rhs.numberIntegers_; |
9132 | number01Integers_=rhs.number01Integers_; |
9133 | for (i=0;i<number01Integers_;i++) { |
9134 | delete [] cutVector_[i].index; |
9135 | } |
9136 | delete [] cutVector_; |
9137 | cutVector_=new disaggregation [number01Integers_]; |
9138 | CoinMemcpyN(rhs.cutVector_,number01Integers_,cutVector_); |
9139 | for (i=0;i<number01Integers_;i++) { |
9140 | if (cutVector_[i].index) { |
9141 | cutVector_[i].index = CoinCopyOfArray(rhs.cutVector_[i].index,cutVector_[i].length); |
9142 | } |
9143 | } |
9144 | } else { |
9145 | rowCopy_=NULL; |
9146 | columnCopy_=NULL; |
9147 | rowLower_=NULL; |
9148 | rowUpper_=NULL; |
9149 | colLower_=NULL; |
9150 | colUpper_=NULL; |
9151 | numberIntegers_=0; |
9152 | number01Integers_=0; |
9153 | cutVector_=NULL; |
9154 | } |
9155 | numberThisTime_=rhs.numberThisTime_; |
9156 | totalTimesCalled_=rhs.totalTimesCalled_; |
9157 | if (numberColumns_) |
9158 | lookedAt_=CoinCopyOfArray(rhs.lookedAt_,numberColumns_); |
9159 | else |
9160 | lookedAt_ = NULL; |
9161 | if (numberCliques_) { |
9162 | cliqueType_ = new cliqueType [numberCliques_]; |
9163 | CoinMemcpyN(rhs.cliqueType_,numberCliques_,cliqueType_); |
9164 | cliqueStart_ = new int [numberCliques_+1]; |
9165 | CoinMemcpyN(rhs.cliqueStart_,(numberCliques_+1),cliqueStart_); |
9166 | int n = cliqueStart_[numberCliques_]; |
9167 | cliqueEntry_ = new cliqueEntry [n]; |
9168 | CoinMemcpyN(rhs.cliqueEntry_,n,cliqueEntry_); |
9169 | oneFixStart_ = new int [numberColumns_]; |
9170 | CoinMemcpyN(rhs.oneFixStart_,numberColumns_,oneFixStart_); |
9171 | zeroFixStart_ = new int [numberColumns_]; |
9172 | CoinMemcpyN(rhs.zeroFixStart_,numberColumns_,zeroFixStart_); |
9173 | endFixStart_ = new int [numberColumns_]; |
9174 | CoinMemcpyN(rhs.endFixStart_,numberColumns_,endFixStart_); |
9175 | #ifndef NDEBUG |
9176 | int n2=-1; |
9177 | for (int i=numberColumns_-1;i>=0;i--) { |
9178 | if (oneFixStart_[i]>=0) { |
9179 | n2=endFixStart_[i]; |
9180 | break; |
9181 | } |
9182 | } |
9183 | assert (n==n2); |
9184 | #endif |
9185 | whichClique_ = new int [n]; |
9186 | CoinMemcpyN(rhs.whichClique_,n,whichClique_); |
9187 | if (rhs.cliqueRowStart_) { |
9188 | cliqueRowStart_ = CoinCopyOfArray(rhs.cliqueRowStart_,numberRows_+1); |
9189 | n=cliqueRowStart_[numberRows_]; |
9190 | cliqueRow_ = CoinCopyOfArray(rhs.cliqueRow_,n); |
9191 | } else { |
9192 | cliqueRow_=NULL; |
9193 | cliqueRowStart_=NULL; |
9194 | } |
9195 | } else { |
9196 | cliqueType_=NULL; |
9197 | cliqueStart_=NULL; |
9198 | cliqueEntry_=NULL; |
9199 | oneFixStart_=NULL; |
9200 | zeroFixStart_=NULL; |
9201 | endFixStart_=NULL; |
9202 | whichClique_=NULL; |
9203 | cliqueRow_=NULL; |
9204 | cliqueRowStart_=NULL; |
9205 | } |
9206 | if (rhs.tightenBounds_) { |
9207 | assert (numberColumns_); |
9208 | tightenBounds_=CoinCopyOfArray(rhs.tightenBounds_,numberColumns_); |
9209 | } else { |
9210 | tightenBounds_=NULL; |
9211 | } |
9212 | } |
9213 | return *this; |
9214 | } |
9215 | |
9216 | |
9217 | void |
9218 | CglProbing::refreshSolver(OsiSolverInterface * solver) |
9219 | { |
9220 | if (rowCopy_) { |
9221 | |
9222 | snapshot(*solver,NULL); |
9223 | } |
9224 | } |
9225 | |
9226 | |
9227 | |
9228 | |
9229 | int |
9230 | CglProbing::createCliques( OsiSolverInterface & si, |
9231 | int minimumSize, int maximumSize) |
9232 | { |
9233 | |
9234 | deleteCliques(); |
9235 | CoinPackedMatrix matrixByRow(*si.getMatrixByRow()); |
9236 | int numberRows = si.getNumRows(); |
9237 | if (!rowCopy_) |
9238 | numberRows_=numberRows; |
9239 | numberColumns_ = si.getNumCols(); |
9240 | |
9241 | numberCliques_=0; |
9242 | int numberEntries=0; |
9243 | int numberIntegers=0; |
9244 | int * lookup = new int[numberColumns_]; |
9245 | int i; |
9246 | for (i=0;i<numberColumns_;i++) { |
9247 | if (si.isBinary(i)) |
9248 | lookup[i]=numberIntegers++; |
9249 | else |
9250 | lookup[i]=-1; |
9251 | } |
9252 | |
9253 | int * which = new int[numberColumns_]; |
9254 | int * whichRow = new int[numberRows]; |
9255 | |
9256 | int totalP1=0,totalM1=0; |
9257 | int numberBig=0,totalBig=0; |
9258 | int numberFixed=0; |
9259 | |
9260 | |
9261 | const double * elementByRow = matrixByRow.getElements(); |
9262 | const int * column = matrixByRow.getIndices(); |
9263 | const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); |
9264 | const int * rowLength = matrixByRow.getVectorLengths(); |
9265 | |
9266 | const double * lower = si.getColLower(); |
9267 | const double * upper = si.getColUpper(); |
9268 | const double * rowLower = si.getRowLower(); |
9269 | const double * rowUpper = si.getRowUpper(); |
9270 | int iRow; |
9271 | for (iRow=0;iRow<numberRows;iRow++) { |
9272 | int numberP1=0, numberM1=0; |
9273 | int j; |
9274 | double upperValue=rowUpper[iRow]; |
9275 | double lowerValue=rowLower[iRow]; |
9276 | bool good=true; |
9277 | for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { |
9278 | int iColumn = column[j]; |
9279 | int iInteger=lookup[iColumn]; |
9280 | if (upper[iColumn]-lower[iColumn]<1.0e-8) { |
9281 | |
9282 | upperValue -= lower[iColumn]*elementByRow[j]; |
9283 | lowerValue -= lower[iColumn]*elementByRow[j]; |
9284 | continue; |
9285 | } else if (upper[iColumn]!=1.0||lower[iColumn]!=0.0) { |
9286 | good = false; |
9287 | break; |
9288 | } else if (iInteger<0) { |
9289 | good = false; |
9290 | break; |
9291 | } |
9292 | if (fabs(elementByRow[j])!=1.0) { |
9293 | good=false; |
9294 | break; |
9295 | } else if (elementByRow[j]>0.0) { |
9296 | which[numberP1++]=iColumn; |
9297 | } else { |
9298 | numberM1++; |
9299 | which[numberIntegers-numberM1]=iColumn; |
9300 | } |
9301 | } |
9302 | int iUpper = static_cast<int> (floor(upperValue+1.0e-5)); |
9303 | int iLower = static_cast<int> (ceil(lowerValue-1.0e-5)); |
9304 | int state=0; |
9305 | if (upperValue<1.0e6) { |
9306 | if (iUpper==1-numberM1) |
9307 | state=1; |
9308 | else if (iUpper==-numberM1) |
9309 | state=2; |
9310 | else if (iUpper<-numberM1) |
9311 | state=3; |
9312 | } |
9313 | if (!state&&lowerValue>-1.0e6) { |
9314 | if (-iLower==1-numberP1) |
9315 | state=-1; |
9316 | else if (-iLower==-numberP1) |
9317 | state=-2; |
9318 | else if (-iLower<-numberP1) |
9319 | state=-3; |
9320 | } |
9321 | if (good&&state) { |
9322 | if (abs(state)==3) { |
9323 | |
9324 | numberCliques_ = -99999; |
9325 | break; |
9326 | } else if (abs(state)==2) { |
9327 | |
9328 | numberFixed += numberP1+numberM1; |
9329 | if (state>0) { |
9330 | |
9331 | for (i=0;i<numberP1;i++) |
9332 | si.setColUpper(which[i],0.0); |
9333 | for (i=0;i<numberM1;i++) |
9334 | si.setColLower(which[numberIntegers-i-1], |
9335 | 1.0); |
9336 | } else { |
9337 | |
9338 | for (i=0;i<numberP1;i++) |
9339 | si.setColLower(which[i],1.0); |
9340 | for (i=0;i<numberM1;i++) |
9341 | si.setColUpper(which[numberIntegers-i-1], |
9342 | 0.0); |
9343 | } |
9344 | } else { |
9345 | int length = numberP1+numberM1; |
9346 | totalP1 += numberP1; |
9347 | totalM1 += numberM1; |
9348 | if (length >= minimumSize&&length<maximumSize) { |
9349 | whichRow[numberCliques_++]=iRow; |
9350 | numberEntries += length; |
9351 | } else if (numberP1+numberM1 >= maximumSize) { |
9352 | |
9353 | numberBig++; |
9354 | totalBig += numberP1+numberM1; |
9355 | } |
9356 | } |
9357 | } |
9358 | } |
9359 | if (numberCliques_<0) { |
9360 | if (logLevel_) |
9361 | printf("*** Problem infeasible\n"); |
9362 | } else { |
9363 | if (numberCliques_) { |
9364 | if (logLevel_) |
9365 | printf("%d cliques of average size %g found, %d P1, %d M1\n", |
9366 | numberCliques_, |
9367 | (static_cast<double>(totalP1+totalM1))/ |
9368 | (static_cast<double> (numberCliques_)), |
9369 | totalP1,totalM1); |
9370 | } else { |
9371 | if (logLevel_>1) |
9372 | printf("No cliques found\n"); |
9373 | } |
9374 | if (numberBig) { |
9375 | if (logLevel_) |
9376 | printf("%d large cliques ( >= %d) found, total %d\n", |
9377 | numberBig,maximumSize,totalBig); |
9378 | } |
9379 | if (numberFixed) { |
9380 | if (logLevel_) |
9381 | printf("%d variables fixed\n",numberFixed); |
9382 | } |
9383 | } |
9384 | if (numberCliques_>0) { |
9385 | cliqueType_ = new cliqueType [numberCliques_]; |
9386 | cliqueStart_ = new int [numberCliques_+1]; |
9387 | cliqueEntry_ = new cliqueEntry [numberEntries]; |
9388 | oneFixStart_ = new int [numberColumns_]; |
9389 | zeroFixStart_ = new int [numberColumns_]; |
9390 | endFixStart_ = new int [numberColumns_]; |
9391 | whichClique_ = new int [numberEntries]; |
9392 | numberEntries=0; |
9393 | cliqueStart_[0]=0; |
9394 | for (i=0;i<numberColumns_;i++) { |
9395 | oneFixStart_[i]=-1; |
9396 | zeroFixStart_[i]=-1; |
9397 | endFixStart_[i]=-1; |
9398 | } |
9399 | int iClique; |
9400 | |
9401 | int numberCliques=numberCliques_; |
9402 | numberCliques_=0; |
9403 | for (iClique=0;iClique<numberCliques;iClique++) { |
9404 | int iRow=whichRow[iClique]; |
9405 | whichRow[numberCliques_]=iRow; |
9406 | int numberP1=0, numberM1=0; |
9407 | int j; |
9408 | double upperValue=rowUpper[iRow]; |
9409 | double lowerValue=rowLower[iRow]; |
9410 | for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { |
9411 | int iColumn = column[j]; |
9412 | if (upper[iColumn]-lower[iColumn]<1.0e-8) { |
9413 | |
9414 | upperValue -= lower[iColumn]*elementByRow[j]; |
9415 | lowerValue -= lower[iColumn]*elementByRow[j]; |
9416 | continue; |
9417 | } |
9418 | if (elementByRow[j]>0.0) { |
9419 | which[numberP1++]=iColumn; |
9420 | } else { |
9421 | numberM1++; |
9422 | which[numberIntegers-numberM1]=iColumn; |
9423 | } |
9424 | } |
9425 | int iUpper = static_cast<int> (floor(upperValue+1.0e-5)); |
9426 | int iLower = static_cast<int> (ceil(lowerValue-1.0e-5)); |
9427 | int state=0; |
9428 | if (upperValue<1.0e6) { |
9429 | if (iUpper==1-numberM1) |
9430 | state=1; |
9431 | } |
9432 | if (!state&&lowerValue>-1.0e6) { |
9433 | state=-1; |
9434 | } |
9435 | if (abs(state)!=1) |
9436 | continue; |
9437 | if (iLower==iUpper) { |
9438 | cliqueType_[numberCliques_].equality=1; |
9439 | } else { |
9440 | cliqueType_[numberCliques_].equality=0; |
9441 | } |
9442 | if (state>0) { |
9443 | for (i=0;i<numberP1;i++) { |
9444 | |
9445 | int iColumn = which[i]; |
9446 | setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn); |
9447 | setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],true); |
9448 | numberEntries++; |
9449 | |
9450 | oneFixStart_[iColumn]=0; |
9451 | zeroFixStart_[iColumn]=0; |
9452 | } |
9453 | for (i=0;i<numberM1;i++) { |
9454 | |
9455 | int iColumn = which[numberIntegers-i-1]; |
9456 | setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn); |
9457 | setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],false); |
9458 | numberEntries++; |
9459 | |
9460 | oneFixStart_[iColumn]=0; |
9461 | zeroFixStart_[iColumn]=0; |
9462 | } |
9463 | } else { |
9464 | for (i=0;i<numberP1;i++) { |
9465 | |
9466 | int iColumn = which[i]; |
9467 | setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn); |
9468 | setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],false); |
9469 | numberEntries++; |
9470 | |
9471 | oneFixStart_[iColumn]=0; |
9472 | zeroFixStart_[iColumn]=0; |
9473 | } |
9474 | for (i=0;i<numberM1;i++) { |
9475 | |
9476 | int iColumn = which[numberIntegers-i-1]; |
9477 | setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn); |
9478 | setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],true); |
9479 | numberEntries++; |
9480 | |
9481 | oneFixStart_[iColumn]=0; |
9482 | zeroFixStart_[iColumn]=0; |
9483 | } |
9484 | } |
9485 | numberCliques_++; |
9486 | cliqueStart_[numberCliques_]=numberEntries; |
9487 | } |
9488 | |
9489 | |
9490 | for (iClique=0;iClique<numberCliques_;iClique++) { |
9491 | for (int j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) { |
9492 | int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]); |
9493 | if (oneFixesInCliqueEntry(cliqueEntry_[j])) |
9494 | oneFixStart_[iColumn]++; |
9495 | else |
9496 | zeroFixStart_[iColumn]++; |
9497 | } |
9498 | } |
9499 | |
9500 | numberEntries=0; |
9501 | for (int iColumn=0;iColumn<numberColumns_;iColumn++) { |
9502 | if (oneFixStart_[iColumn]>=0) { |
9503 | int n1=oneFixStart_[iColumn]; |
9504 | int n2=zeroFixStart_[iColumn]; |
9505 | oneFixStart_[iColumn]=numberEntries; |
9506 | which[iColumn]=numberEntries; |
9507 | numberEntries += n1; |
9508 | zeroFixStart_[iColumn]=numberEntries; |
9509 | endFixStart_[iColumn]=numberEntries; |
9510 | numberEntries += n2; |
9511 | } |
9512 | } |
9513 | |
9514 | for (iClique=0;iClique<numberCliques_;iClique++) { |
9515 | for (int j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) { |
9516 | int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]); |
9517 | if (oneFixesInCliqueEntry(cliqueEntry_[j])) { |
9518 | int put = which[iColumn]; |
9519 | which[iColumn]++; |
9520 | whichClique_[put]=iClique; |
9521 | } else { |
9522 | int put = endFixStart_[iColumn]; |
9523 | endFixStart_[iColumn]++; |
9524 | whichClique_[put]=iClique; |
9525 | } |
9526 | } |
9527 | } |
9528 | } |
9529 | delete [] which; |
9530 | delete [] whichRow; |
9531 | delete [] lookup; |
9532 | return numberCliques_; |
9533 | } |
9534 | |
9535 | void |
9536 | CglProbing::deleteCliques() |
9537 | { |
9538 | delete [] cliqueType_; |
9539 | delete [] cliqueStart_; |
9540 | delete [] cliqueEntry_; |
9541 | delete [] oneFixStart_; |
9542 | delete [] zeroFixStart_; |
9543 | delete [] endFixStart_; |
9544 | delete [] whichClique_; |
9545 | delete [] cliqueRow_; |
9546 | delete [] cliqueRowStart_; |
9547 | cliqueType_=NULL; |
9548 | cliqueStart_=NULL; |
9549 | cliqueEntry_=NULL; |
9550 | oneFixStart_=NULL; |
9551 | zeroFixStart_=NULL; |
9552 | endFixStart_=NULL; |
9553 | whichClique_=NULL; |
9554 | cliqueRow_=NULL; |
9555 | cliqueRowStart_=NULL; |
9556 | numberCliques_=0; |
9557 | } |
9558 | |
9559 | |
9560 | |
9561 | |
9562 | |
9563 | |
9564 | |
9565 | bool |
9566 | CglProbing::mayGenerateRowCutsInTree() const |
9567 | { |
9568 | return rowCuts_>0; |
9569 | } |
9570 | |
9571 | void |
9572 | CglProbing::setupRowCliqueInformation(const OsiSolverInterface & si) |
9573 | { |
9574 | if (!numberCliques_) |
9575 | return; |
9576 | CoinPackedMatrix * rowCopy; |
9577 | if (!rowCopy_) { |
9578 | |
9579 | numberRows_=si.getNumRows(); |
9580 | numberColumns_=si.getNumCols(); |
9581 | rowCopy = new CoinPackedMatrix(*si.getMatrixByRow()); |
9582 | } else { |
9583 | rowCopy = rowCopy_; |
9584 | assert(numberRows_<=si.getNumRows()); |
9585 | assert(numberColumns_==si.getNumCols()); |
9586 | } |
9587 | assert(numberRows_&&numberColumns_); |
9588 | cliqueRowStart_ = new int [numberRows_+1]; |
9589 | cliqueRowStart_[0]=0; |
9590 | |
9591 | cliqueEntry ** array = new cliqueEntry * [numberRows_]; |
9592 | |
9593 | int * which = new int[numberCliques_]; |
9594 | int * count = new int[numberCliques_]; |
9595 | int * back =new int[numberColumns_]; |
9596 | CoinZeroN(count,numberCliques_); |
9597 | CoinFillN(back,numberColumns_,-1); |
9598 | const int * column = rowCopy->getIndices(); |
9599 | const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); |
9600 | const int * rowLength = rowCopy->getVectorLengths(); |
9601 | const double * lower = si.getColLower(); |
9602 | const double * upper = si.getColUpper(); |
9603 | int iRow; |
9604 | for (iRow=0;iRow<numberRows_;iRow++) { |
9605 | int j; |
9606 | int numberFree=0; |
9607 | int numberUsed=0; |
9608 | for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { |
9609 | int iColumn=column[j]; |
9610 | if (upper[iColumn]>lower[iColumn]) { |
9611 | back[iColumn]=j-rowStart[iRow]; |
9612 | numberFree++; |
9613 | for (int k=oneFixStart_[iColumn];k<endFixStart_[iColumn];k++) { |
9614 | int iClique = whichClique_[k]; |
9615 | if (!count[iClique]) { |
9616 | which[numberUsed++]=iClique; |
9617 | } |
9618 | count[iClique]++; |
9619 | } |
9620 | } |
9621 | } |
9622 | |
9623 | bool finished=false; |
9624 | int numberInThis=0; |
9625 | cliqueEntry * entries = NULL; |
9626 | array[iRow]=entries; |
9627 | while (!finished) { |
9628 | int largest=1; |
9629 | int whichClique=-1; |
9630 | for (int i=0;i<numberUsed;i++) { |
9631 | int iClique = which[i]; |
9632 | if (count[iClique]>largest) { |
9633 | largest=count[iClique]; |
9634 | whichClique=iClique; |
9635 | } |
9636 | } |
9637 | |
9638 | if (whichClique>=0&&largest<numberFree) { |
9639 | if (!numberInThis) { |
9640 | int length=rowLength[iRow]; |
9641 | entries = new cliqueEntry [length]; |
9642 | array[iRow]=entries; |
9643 | for (int i=0;i<length;i++) { |
9644 | setOneFixesInCliqueEntry(entries[i],false); |
9645 | setSequenceInCliqueEntry(entries[i],numberColumns_+1); |
9646 | } |
9647 | } |
9648 | |
9649 | for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { |
9650 | int iColumn=column[j]; |
9651 | if (upper[iColumn]>lower[iColumn]) { |
9652 | bool found=false; |
9653 | int k; |
9654 | for ( k=oneFixStart_[iColumn];k<endFixStart_[iColumn];k++) { |
9655 | int iClique = whichClique_[k]; |
9656 | if (iClique==whichClique) { |
9657 | found=true; |
9658 | break; |
9659 | } |
9660 | } |
9661 | if (found) { |
9662 | for ( k=oneFixStart_[iColumn];k<endFixStart_[iColumn];k++) { |
9663 | int iClique = whichClique_[k]; |
9664 | count[iClique]--; |
9665 | } |
9666 | for (k=cliqueStart_[whichClique];k<cliqueStart_[whichClique+1];k++) { |
9667 | if (sequenceInCliqueEntry(cliqueEntry_[k])==iColumn) { |
9668 | int iback=back[iColumn]; |
9669 | setSequenceInCliqueEntry(entries[iback],numberInThis); |
9670 | setOneFixesInCliqueEntry(entries[iback], |
9671 | oneFixesInCliqueEntry(cliqueEntry_[k])); |
9672 | break; |
9673 | } |
9674 | } |
9675 | } |
9676 | } |
9677 | } |
9678 | numberInThis++; |
9679 | } else { |
9680 | finished=true; |
9681 | } |
9682 | } |
9683 | if (numberInThis) |
9684 | cliqueRowStart_[iRow+1]=cliqueRowStart_[iRow]+rowLength[iRow]; |
9685 | else |
9686 | cliqueRowStart_[iRow+1]=cliqueRowStart_[iRow]; |
9687 | for (int i=0;i<numberUsed;i++) { |
9688 | int iClique = which[i]; |
9689 | count[iClique]=0; |
9690 | } |
9691 | for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) { |
9692 | int iColumn=column[j]; |
9693 | back[iColumn]=-1; |
9694 | } |
9695 | } |
9696 | delete [] which; |
9697 | delete [] count; |
9698 | delete [] back; |
9699 | |
9700 | cliqueRow_ = new cliqueEntry [cliqueRowStart_[numberRows_]]; |
9701 | for (iRow=0;iRow<numberRows_;iRow++) { |
9702 | if (array[iRow]) { |
9703 | int start = cliqueRowStart_[iRow]; |
9704 | CoinMemcpyN(array[iRow],rowLength[iRow],cliqueRow_+start); |
9705 | delete [] array[iRow]; |
9706 | } |
9707 | } |
9708 | delete [] array; |
9709 | if (rowCopy!=rowCopy_) |
9710 | delete rowCopy; |
9711 | } |
9712 | |
9713 | void |
9714 | CglProbing::tightenThese(const OsiSolverInterface & solver,int number, const int * which) |
9715 | { |
9716 | delete [] tightenBounds_; |
9717 | int numberColumns = solver.getNumCols(); |
9718 | if (numberColumns_) |
9719 | assert (numberColumns_==numberColumns); |
9720 | tightenBounds_ = new char [numberColumns]; |
9721 | memset(tightenBounds_,0,numberColumns); |
9722 | for (int i=0;i<number;i++) { |
9723 | int k=which[i]; |
9724 | if (k>=0&&k<numberColumns) |
9725 | tightenBounds_[k]=1; |
9726 | } |
9727 | } |
9728 | |
9729 | std::string |
9730 | CglProbing::generateCpp( FILE * fp) |
9731 | { |
9732 | CglProbing other; |
9733 | fprintf(fp,"0#include \"CglProbing.hpp\"\n"); |
9734 | fprintf(fp,"3 CglProbing probing;\n"); |
9735 | if (getMode()!=other.getMode()) |
9736 | fprintf(fp,"3 probing.setMode(%d);\n",getMode()); |
9737 | else |
9738 | fprintf(fp,"4 probing.setMode(%d);\n",getMode()); |
9739 | if (getMaxPass()!=other.getMaxPass()) |
9740 | fprintf(fp,"3 probing.setMaxPass(%d);\n",getMaxPass()); |
9741 | else |
9742 | fprintf(fp,"4 probing.setMaxPass(%d);\n",getMaxPass()); |
9743 | if (getLogLevel()!=other.getLogLevel()) |
9744 | fprintf(fp,"3 probing.setLogLevel(%d);\n",getLogLevel()); |
9745 | else |
9746 | fprintf(fp,"4 probing.setLogLevel(%d);\n",getLogLevel()); |
9747 | if (getMaxProbe()!=other.getMaxProbe()) |
9748 | fprintf(fp,"3 probing.setMaxProbe(%d);\n",getMaxProbe()); |
9749 | else |
9750 | fprintf(fp,"4 probing.setMaxProbe(%d);\n",getMaxProbe()); |
9751 | if (getMaxLook()!=other.getMaxLook()) |
9752 | fprintf(fp,"3 probing.setMaxLook(%d);\n",getMaxLook()); |
9753 | else |
9754 | fprintf(fp,"4 probing.setMaxLook(%d);\n",getMaxLook()); |
9755 | if (getMaxElements()!=other.getMaxElements()) |
9756 | fprintf(fp,"3 probing.setMaxElements(%d);\n",getMaxElements()); |
9757 | else |
9758 | fprintf(fp,"4 probing.setMaxElements(%d);\n",getMaxElements()); |
9759 | if (getMaxPassRoot()!=other.getMaxPassRoot()) |
9760 | fprintf(fp,"3 probing.setMaxPassRoot(%d);\n",getMaxPassRoot()); |
9761 | else |
9762 | fprintf(fp,"4 probing.setMaxPassRoot(%d);\n",getMaxPassRoot()); |
9763 | if (getMaxProbeRoot()!=other.getMaxProbeRoot()) |
9764 | fprintf(fp,"3 probing.setMaxProbeRoot(%d);\n",getMaxProbeRoot()); |
9765 | else |
9766 | fprintf(fp,"4 probing.setMaxProbeRoot(%d);\n",getMaxProbeRoot()); |
9767 | if (getMaxLookRoot()!=other.getMaxLookRoot()) |
9768 | fprintf(fp,"3 probing.setMaxLookRoot(%d);\n",getMaxLookRoot()); |
9769 | else |
9770 | fprintf(fp,"4 probing.setMaxLookRoot(%d);\n",getMaxLookRoot()); |
9771 | if (getMaxElementsRoot()!=other.getMaxElementsRoot()) |
9772 | fprintf(fp,"3 probing.setMaxElementsRoot(%d);\n",getMaxElementsRoot()); |
9773 | else |
9774 | fprintf(fp,"4 probing.setMaxElementsRoot(%d);\n",getMaxElementsRoot()); |
9775 | if (rowCuts()!=other.rowCuts()) |
9776 | fprintf(fp,"3 probing.setRowCuts(%d);\n",rowCuts()); |
9777 | else |
9778 | fprintf(fp,"4 probing.setRowCuts(%d);\n",rowCuts()); |
9779 | if (getUsingObjective()!=other.getUsingObjective()) |
9780 | fprintf(fp,"3 probing.setUsingObjective(%d);\n",getUsingObjective()); |
9781 | else |
9782 | fprintf(fp,"4 probing.setUsingObjective(%d);\n",getUsingObjective()); |
9783 | if (getAggressiveness()!=other.getAggressiveness()) |
9784 | fprintf(fp,"3 probing.setAggressiveness(%d);\n",getAggressiveness()); |
9785 | else |
9786 | fprintf(fp,"4 probing.setAggressiveness(%d);\n",getAggressiveness()); |
9787 | return "probing"; |
9788 | } |
9789 | |
9790 | void |
9791 | CglImplication::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, |
9792 | const CglTreeInfo info) |
9793 | { |
9794 | if (probingInfo_) { |
9795 | |
9796 | probingInfo_->generateCuts(si,cs,info); |
9797 | |
9798 | |
9799 | |
9800 | } |
9801 | } |
9802 | |
9803 | |
9804 | |
9805 | |
9806 | CglImplication::CglImplication () |
9807 | : |
9808 | CglCutGenerator(), |
9809 | probingInfo_(NULL) |
9810 | { |
9811 | |
9812 | } |
9813 | |
9814 | |
9815 | |
9816 | CglImplication::CglImplication (CglTreeProbingInfo * info) |
9817 | : |
9818 | CglCutGenerator(), |
9819 | probingInfo_(info) |
9820 | { |
9821 | |
9822 | } |
9823 | |
9824 | |
9825 | |
9826 | CglImplication::CglImplication ( |
9827 | const CglImplication & source) |
9828 | : |
9829 | CglCutGenerator(source), |
9830 | probingInfo_(source.probingInfo_) |
9831 | { |
9832 | |
9833 | } |
9834 | |
9835 | |
9836 | |
9837 | |
9838 | |
9839 | CglCutGenerator * |
9840 | CglImplication::clone() const |
9841 | { |
9842 | return new CglImplication(*this); |
9843 | } |
9844 | |
9845 | |
9846 | |
9847 | |
9848 | CglImplication::~CglImplication () |
9849 | { |
9850 | |
9851 | } |
9852 | |
9853 | |
9854 | |
9855 | |
9856 | CglImplication & |
9857 | CglImplication::operator=( |
9858 | const CglImplication& rhs) |
9859 | { |
9860 | if (this != &rhs) { |
9861 | CglCutGenerator::operator=(rhs); |
9862 | probingInfo_=rhs.probingInfo_; |
9863 | } |
9864 | return *this; |
9865 | } |
9866 | |
9867 | std::string |
9868 | CglImplication::generateCpp( FILE * fp) |
9869 | { |
9870 | CglImplication other; |
9871 | fprintf(fp,"0#include \"CglImplication.hpp\"\n"); |
9872 | fprintf(fp,"3 CglImplication implication;\n"); |
9873 | return "implication"; |
9874 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | #ifndef _STL_ALGO_H |
57 | #define _STL_ALGO_H 1 |
58 | |
59 | #include <cstdlib> // for rand |
60 | #include <bits/algorithmfwd.h> |
61 | #include <bits/stl_heap.h> |
62 | #include <bits/stl_tempbuf.h> // for _Temporary_buffer |
63 | #include <bits/predefined_ops.h> |
64 | |
65 | #if __cplusplus >= 201103L |
66 | #include <bits/uniform_int_dist.h> |
67 | #endif |
68 | |
69 | |
70 | |
71 | namespace std _GLIBCXX_VISIBILITY(default) |
72 | { |
73 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
74 | |
75 | |
76 | template<typename _Iterator, typename _Compare> |
77 | _GLIBCXX20_CONSTEXPR |
78 | void |
79 | __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b, |
80 | _Iterator __c, _Compare __comp) |
81 | { |
82 | if (__comp(__a, __b)) |
83 | { |
84 | if (__comp(__b, __c)) |
85 | std::iter_swap(__result, __b); |
86 | else if (__comp(__a, __c)) |
87 | std::iter_swap(__result, __c); |
88 | else |
89 | std::iter_swap(__result, __a); |
90 | } |
91 | else if (__comp(__a, __c)) |
92 | std::iter_swap(__result, __a); |
93 | else if (__comp(__b, __c)) |
94 | std::iter_swap(__result, __c); |
95 | else |
96 | std::iter_swap(__result, __b); |
97 | } |
98 | |
99 | |
100 | template<typename _InputIterator, typename _Predicate> |
101 | _GLIBCXX20_CONSTEXPR |
102 | inline _InputIterator |
103 | __find_if_not(_InputIterator __first, _InputIterator __last, |
104 | _Predicate __pred) |
105 | { |
106 | return std::__find_if(__first, __last, |
107 | __gnu_cxx::__ops::__negate(__pred), |
108 | std::__iterator_category(__first)); |
109 | } |
110 | |
111 | |
112 | |
113 | |
114 | template<typename _InputIterator, typename _Predicate, typename _Distance> |
115 | _GLIBCXX20_CONSTEXPR |
116 | _InputIterator |
117 | __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) |
118 | { |
119 | for (; __len; --__len, (void) ++__first) |
120 | if (!__pred(__first)) |
121 | break; |
122 | return __first; |
123 | } |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
139 | typename _BinaryPredicate> |
140 | _GLIBCXX20_CONSTEXPR |
141 | _ForwardIterator1 |
142 | __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
143 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, |
144 | _BinaryPredicate __predicate) |
145 | { |
146 | |
147 | if (__first1 == __last1 || __first2 == __last2) |
148 | return __first1; |
149 | |
150 | |
151 | _ForwardIterator2 __p1(__first2); |
152 | if (++__p1 == __last2) |
153 | return std::__find_if(__first1, __last1, |
154 | __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); |
155 | |
156 | |
157 | _ForwardIterator1 __current = __first1; |
158 | |
159 | for (;;) |
160 | { |
161 | __first1 = |
162 | std::__find_if(__first1, __last1, |
163 | __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); |
164 | |
165 | if (__first1 == __last1) |
166 | return __last1; |
167 | |
168 | _ForwardIterator2 __p = __p1; |
169 | __current = __first1; |
170 | if (++__current == __last1) |
171 | return __last1; |
172 | |
173 | while (__predicate(__current, __p)) |
174 | { |
175 | if (++__p == __last2) |
176 | return __first1; |
177 | if (++__current == __last1) |
178 | return __last1; |
179 | } |
180 | ++__first1; |
181 | } |
182 | return __first1; |
183 | } |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | template<typename _ForwardIterator, typename _Integer, |
191 | typename _UnaryPredicate> |
192 | _GLIBCXX20_CONSTEXPR |
193 | _ForwardIterator |
194 | __search_n_aux(_ForwardIterator __first, _ForwardIterator __last, |
195 | _Integer __count, _UnaryPredicate __unary_pred, |
196 | std::forward_iterator_tag) |
197 | { |
198 | __first = std::__find_if(__first, __last, __unary_pred); |
199 | while (__first != __last) |
200 | { |
201 | typename iterator_traits<_ForwardIterator>::difference_type |
202 | __n = __count; |
203 | _ForwardIterator __i = __first; |
204 | ++__i; |
205 | while (__i != __last && __n != 1 && __unary_pred(__i)) |
206 | { |
207 | ++__i; |
208 | --__n; |
209 | } |
210 | if (__n == 1) |
211 | return __first; |
212 | if (__i == __last) |
213 | return __last; |
214 | __first = std::__find_if(++__i, __last, __unary_pred); |
215 | } |
216 | return __last; |
217 | } |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | template<typename _RandomAccessIter, typename _Integer, |
224 | typename _UnaryPredicate> |
225 | _GLIBCXX20_CONSTEXPR |
226 | _RandomAccessIter |
227 | __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last, |
228 | _Integer __count, _UnaryPredicate __unary_pred, |
229 | std::random_access_iterator_tag) |
230 | { |
231 | typedef typename std::iterator_traits<_RandomAccessIter>::difference_type |
232 | _DistanceType; |
233 | |
234 | _DistanceType __tailSize = __last - __first; |
235 | _DistanceType __remainder = __count; |
236 | |
237 | while (__remainder <= __tailSize) |
238 | { |
239 | __first += __remainder; |
240 | __tailSize -= __remainder; |
241 | |
242 | |
243 | _RandomAccessIter __backTrack = __first; |
244 | while (__unary_pred(--__backTrack)) |
245 | { |
246 | if (--__remainder == 0) |
247 | return (__first - __count); |
248 | } |
249 | __remainder = __count + 1 - (__first - __backTrack); |
250 | } |
251 | return __last; |
252 | } |
253 | |
254 | template<typename _ForwardIterator, typename _Integer, |
255 | typename _UnaryPredicate> |
256 | _GLIBCXX20_CONSTEXPR |
257 | _ForwardIterator |
258 | __search_n(_ForwardIterator __first, _ForwardIterator __last, |
259 | _Integer __count, |
260 | _UnaryPredicate __unary_pred) |
261 | { |
262 | if (__count <= 0) |
263 | return __first; |
264 | |
265 | if (__count == 1) |
266 | return std::__find_if(__first, __last, __unary_pred); |
267 | |
268 | return std::__search_n_aux(__first, __last, __count, __unary_pred, |
269 | std::__iterator_category(__first)); |
270 | } |
271 | |
272 | |
273 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
274 | typename _BinaryPredicate> |
275 | _GLIBCXX20_CONSTEXPR |
276 | _ForwardIterator1 |
277 | __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
278 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, |
279 | forward_iterator_tag, forward_iterator_tag, |
280 | _BinaryPredicate __comp) |
281 | { |
282 | if (__first2 == __last2) |
283 | return __last1; |
284 | |
285 | _ForwardIterator1 __result = __last1; |
286 | while (1) |
287 | { |
288 | _ForwardIterator1 __new_result |
289 | = std::__search(__first1, __last1, __first2, __last2, __comp); |
290 | if (__new_result == __last1) |
291 | return __result; |
292 | else |
293 | { |
294 | __result = __new_result; |
295 | __first1 = __new_result; |
296 | ++__first1; |
297 | } |
298 | } |
299 | } |
300 | |
301 | |
302 | template<typename _BidirectionalIterator1, typename _BidirectionalIterator2, |
303 | typename _BinaryPredicate> |
304 | _GLIBCXX20_CONSTEXPR |
305 | _BidirectionalIterator1 |
306 | __find_end(_BidirectionalIterator1 __first1, |
307 | _BidirectionalIterator1 __last1, |
308 | _BidirectionalIterator2 __first2, |
309 | _BidirectionalIterator2 __last2, |
310 | bidirectional_iterator_tag, bidirectional_iterator_tag, |
311 | _BinaryPredicate __comp) |
312 | { |
313 | |
314 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
315 | _BidirectionalIterator1>) |
316 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
317 | _BidirectionalIterator2>) |
318 | |
319 | typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1; |
320 | typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2; |
321 | |
322 | _RevIterator1 __rlast1(__first1); |
323 | _RevIterator2 __rlast2(__first2); |
324 | _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1, |
325 | _RevIterator2(__last2), __rlast2, |
326 | __comp); |
327 | |
328 | if (__rresult == __rlast1) |
329 | return __last1; |
330 | else |
331 | { |
332 | _BidirectionalIterator1 __result = __rresult.base(); |
333 | std::advance(__result, -std::distance(__first2, __last2)); |
334 | return __result; |
335 | } |
336 | } |
337 | |
338 | |
339 | |
340 | |
341 | |
342 | |
343 | |
344 | |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | |
351 | |
352 | |
353 | |
354 | |
355 | |
356 | |
357 | |
358 | |
359 | |
360 | |
361 | |
362 | |
363 | |
364 | template<typename _ForwardIterator1, typename _ForwardIterator2> |
365 | _GLIBCXX20_CONSTEXPR |
366 | inline _ForwardIterator1 |
367 | find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
368 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) |
369 | { |
370 | |
371 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) |
372 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) |
373 | __glibcxx_function_requires(_EqualOpConcept< |
374 | typename iterator_traits<_ForwardIterator1>::value_type, |
375 | typename iterator_traits<_ForwardIterator2>::value_type>) |
376 | __glibcxx_requires_valid_range(__first1, __last1); |
377 | __glibcxx_requires_valid_range(__first2, __last2); |
378 | |
379 | return std::__find_end(__first1, __last1, __first2, __last2, |
380 | std::__iterator_category(__first1), |
381 | std::__iterator_category(__first2), |
382 | __gnu_cxx::__ops::__iter_equal_to_iter()); |
383 | } |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | |
390 | |
391 | |
392 | |
393 | |
394 | |
395 | |
396 | |
397 | |
398 | |
399 | |
400 | |
401 | |
402 | |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
414 | typename _BinaryPredicate> |
415 | _GLIBCXX20_CONSTEXPR |
416 | inline _ForwardIterator1 |
417 | find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
418 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, |
419 | _BinaryPredicate __comp) |
420 | { |
421 | |
422 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) |
423 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) |
424 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
425 | typename iterator_traits<_ForwardIterator1>::value_type, |
426 | typename iterator_traits<_ForwardIterator2>::value_type>) |
427 | __glibcxx_requires_valid_range(__first1, __last1); |
428 | __glibcxx_requires_valid_range(__first2, __last2); |
429 | |
430 | return std::__find_end(__first1, __last1, __first2, __last2, |
431 | std::__iterator_category(__first1), |
432 | std::__iterator_category(__first2), |
433 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
434 | } |
435 | |
436 | #if __cplusplus >= 201103L |
437 | |
438 | |
439 | |
440 | |
441 | |
442 | |
443 | |
444 | |
445 | |
446 | |
447 | |
448 | |
449 | template<typename _InputIterator, typename _Predicate> |
450 | _GLIBCXX20_CONSTEXPR |
451 | inline bool |
452 | all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) |
453 | { return __last == std::find_if_not(__first, __last, __pred); } |
454 | |
455 | |
456 | |
457 | |
458 | |
459 | |
460 | |
461 | |
462 | |
463 | |
464 | |
465 | |
466 | |
467 | template<typename _InputIterator, typename _Predicate> |
468 | _GLIBCXX20_CONSTEXPR |
469 | inline bool |
470 | none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) |
471 | { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); } |
472 | |
473 | |
474 | |
475 | |
476 | |
477 | |
478 | |
479 | |
480 | |
481 | |
482 | |
483 | |
484 | |
485 | |
486 | template<typename _InputIterator, typename _Predicate> |
487 | _GLIBCXX20_CONSTEXPR |
488 | inline bool |
489 | any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) |
490 | { return !std::none_of(__first, __last, __pred); } |
491 | |
492 | |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | template<typename _InputIterator, typename _Predicate> |
503 | _GLIBCXX20_CONSTEXPR |
504 | inline _InputIterator |
505 | find_if_not(_InputIterator __first, _InputIterator __last, |
506 | _Predicate __pred) |
507 | { |
508 | |
509 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
510 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
511 | typename iterator_traits<_InputIterator>::value_type>) |
512 | __glibcxx_requires_valid_range(__first, __last); |
513 | return std::__find_if_not(__first, __last, |
514 | __gnu_cxx::__ops::__pred_iter(__pred)); |
515 | } |
516 | |
517 | |
518 | |
519 | |
520 | |
521 | |
522 | |
523 | |
524 | |
525 | |
526 | |
527 | template<typename _InputIterator, typename _Predicate> |
528 | _GLIBCXX20_CONSTEXPR |
529 | inline bool |
530 | is_partitioned(_InputIterator __first, _InputIterator __last, |
531 | _Predicate __pred) |
532 | { |
533 | __first = std::find_if_not(__first, __last, __pred); |
534 | if (__first == __last) |
535 | return true; |
536 | ++__first; |
537 | return std::none_of(__first, __last, __pred); |
538 | } |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | template<typename _ForwardIterator, typename _Predicate> |
550 | _GLIBCXX20_CONSTEXPR |
551 | _ForwardIterator |
552 | partition_point(_ForwardIterator __first, _ForwardIterator __last, |
553 | _Predicate __pred) |
554 | { |
555 | |
556 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
557 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
558 | typename iterator_traits<_ForwardIterator>::value_type>) |
559 | |
560 | |
561 | __glibcxx_requires_valid_range(__first, __last); |
562 | |
563 | typedef typename iterator_traits<_ForwardIterator>::difference_type |
564 | _DistanceType; |
565 | |
566 | _DistanceType __len = std::distance(__first, __last); |
567 | |
568 | while (__len > 0) |
569 | { |
570 | _DistanceType __half = __len >> 1; |
571 | _ForwardIterator __middle = __first; |
572 | std::advance(__middle, __half); |
573 | if (__pred(*__middle)) |
574 | { |
575 | __first = __middle; |
576 | ++__first; |
577 | __len = __len - __half - 1; |
578 | } |
579 | else |
580 | __len = __half; |
581 | } |
582 | return __first; |
583 | } |
584 | #endif |
585 | |
586 | template<typename _InputIterator, typename _OutputIterator, |
587 | typename _Predicate> |
588 | _GLIBCXX20_CONSTEXPR |
589 | _OutputIterator |
590 | __remove_copy_if(_InputIterator __first, _InputIterator __last, |
591 | _OutputIterator __result, _Predicate __pred) |
592 | { |
593 | for (; __first != __last; ++__first) |
594 | if (!__pred(__first)) |
595 | { |
596 | *__result = *__first; |
597 | ++__result; |
598 | } |
599 | return __result; |
600 | } |
601 | |
602 | |
603 | |
604 | |
605 | |
606 | |
607 | |
608 | |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | |
615 | |
616 | template<typename _InputIterator, typename _OutputIterator, typename _Tp> |
617 | _GLIBCXX20_CONSTEXPR |
618 | inline _OutputIterator |
619 | remove_copy(_InputIterator __first, _InputIterator __last, |
620 | _OutputIterator __result, const _Tp& __value) |
621 | { |
622 | |
623 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
624 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
625 | typename iterator_traits<_InputIterator>::value_type>) |
626 | __glibcxx_function_requires(_EqualOpConcept< |
627 | typename iterator_traits<_InputIterator>::value_type, _Tp>) |
628 | __glibcxx_requires_valid_range(__first, __last); |
629 | |
630 | return std::__remove_copy_if(__first, __last, __result, |
631 | __gnu_cxx::__ops::__iter_equals_val(__value)); |
632 | } |
633 | |
634 | |
635 | |
636 | |
637 | |
638 | |
639 | |
640 | |
641 | |
642 | |
643 | |
644 | |
645 | |
646 | |
647 | |
648 | |
649 | template<typename _InputIterator, typename _OutputIterator, |
650 | typename _Predicate> |
651 | _GLIBCXX20_CONSTEXPR |
652 | inline _OutputIterator |
653 | remove_copy_if(_InputIterator __first, _InputIterator __last, |
654 | _OutputIterator __result, _Predicate __pred) |
655 | { |
656 | |
657 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
658 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
659 | typename iterator_traits<_InputIterator>::value_type>) |
660 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
661 | typename iterator_traits<_InputIterator>::value_type>) |
662 | __glibcxx_requires_valid_range(__first, __last); |
663 | |
664 | return std::__remove_copy_if(__first, __last, __result, |
665 | __gnu_cxx::__ops::__pred_iter(__pred)); |
666 | } |
667 | |
668 | #if __cplusplus >= 201103L |
669 | |
670 | |
671 | |
672 | |
673 | |
674 | |
675 | |
676 | |
677 | |
678 | |
679 | |
680 | |
681 | |
682 | |
683 | |
684 | template<typename _InputIterator, typename _OutputIterator, |
685 | typename _Predicate> |
686 | _GLIBCXX20_CONSTEXPR |
687 | _OutputIterator |
688 | copy_if(_InputIterator __first, _InputIterator __last, |
689 | _OutputIterator __result, _Predicate __pred) |
690 | { |
691 | |
692 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
693 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
694 | typename iterator_traits<_InputIterator>::value_type>) |
695 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
696 | typename iterator_traits<_InputIterator>::value_type>) |
697 | __glibcxx_requires_valid_range(__first, __last); |
698 | |
699 | for (; __first != __last; ++__first) |
700 | if (__pred(*__first)) |
701 | { |
702 | *__result = *__first; |
703 | ++__result; |
704 | } |
705 | return __result; |
706 | } |
707 | |
708 | template<typename _InputIterator, typename _Size, typename _OutputIterator> |
709 | _GLIBCXX20_CONSTEXPR |
710 | _OutputIterator |
711 | __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result) |
712 | { |
713 | if (__n > 0) |
714 | { |
715 | while (true) |
716 | { |
717 | *__result = *__first; |
718 | ++__result; |
719 | if (--__n > 0) |
720 | ++__first; |
721 | else |
722 | break; |
723 | } |
724 | } |
725 | return __result; |
726 | } |
727 | |
728 | template<typename _CharT, typename _Size> |
729 | __enable_if_t<__is_char<_CharT>::__value, _CharT*> |
730 | __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>, |
731 | _Size, _CharT*); |
732 | |
733 | template<typename _InputIterator, typename _Size, typename _OutputIterator> |
734 | _GLIBCXX20_CONSTEXPR |
735 | _OutputIterator |
736 | __copy_n(_InputIterator __first, _Size __n, |
737 | _OutputIterator __result, input_iterator_tag) |
738 | { |
739 | return std::__niter_wrap(__result, |
740 | __copy_n_a(__first, __n, |
741 | std::__niter_base(__result))); |
742 | } |
743 | |
744 | template<typename _RandomAccessIterator, typename _Size, |
745 | typename _OutputIterator> |
746 | _GLIBCXX20_CONSTEXPR |
747 | inline _OutputIterator |
748 | __copy_n(_RandomAccessIterator __first, _Size __n, |
749 | _OutputIterator __result, random_access_iterator_tag) |
750 | { return std::copy(__first, __first + __n, __result); } |
751 | |
752 | |
753 | |
754 | |
755 | |
756 | |
757 | |
758 | |
759 | |
760 | |
761 | |
762 | |
763 | |
764 | |
765 | template<typename _InputIterator, typename _Size, typename _OutputIterator> |
766 | _GLIBCXX20_CONSTEXPR |
767 | inline _OutputIterator |
768 | copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) |
769 | { |
770 | |
771 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
772 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
773 | typename iterator_traits<_InputIterator>::value_type>) |
774 | __glibcxx_requires_can_increment(__first, __n); |
775 | __glibcxx_requires_can_increment(__result, __n); |
776 | |
777 | return std::__copy_n(__first, __n, __result, |
778 | std::__iterator_category(__first)); |
779 | } |
780 | |
781 | |
782 | |
783 | |
784 | |
785 | |
786 | |
787 | |
788 | |
789 | |
790 | |
791 | |
792 | |
793 | |
794 | |
795 | |
796 | template<typename _InputIterator, typename _OutputIterator1, |
797 | typename _OutputIterator2, typename _Predicate> |
798 | _GLIBCXX20_CONSTEXPR |
799 | pair<_OutputIterator1, _OutputIterator2> |
800 | partition_copy(_InputIterator __first, _InputIterator __last, |
801 | _OutputIterator1 __out_true, _OutputIterator2 __out_false, |
802 | _Predicate __pred) |
803 | { |
804 | |
805 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
806 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1, |
807 | typename iterator_traits<_InputIterator>::value_type>) |
808 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2, |
809 | typename iterator_traits<_InputIterator>::value_type>) |
810 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
811 | typename iterator_traits<_InputIterator>::value_type>) |
812 | __glibcxx_requires_valid_range(__first, __last); |
813 | |
814 | for (; __first != __last; ++__first) |
815 | if (__pred(*__first)) |
816 | { |
817 | *__out_true = *__first; |
818 | ++__out_true; |
819 | } |
820 | else |
821 | { |
822 | *__out_false = *__first; |
823 | ++__out_false; |
824 | } |
825 | |
826 | return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); |
827 | } |
828 | #endif // C++11 |
829 | |
830 | template<typename _ForwardIterator, typename _Predicate> |
831 | _GLIBCXX20_CONSTEXPR |
832 | _ForwardIterator |
833 | __remove_if(_ForwardIterator __first, _ForwardIterator __last, |
834 | _Predicate __pred) |
835 | { |
836 | __first = std::__find_if(__first, __last, __pred); |
837 | if (__first == __last) |
838 | return __first; |
839 | _ForwardIterator __result = __first; |
840 | ++__first; |
841 | for (; __first != __last; ++__first) |
842 | if (!__pred(__first)) |
843 | { |
844 | *__result = _GLIBCXX_MOVE(*__first); |
845 | ++__result; |
846 | } |
847 | return __result; |
848 | } |
849 | |
850 | |
851 | |
852 | |
853 | |
854 | |
855 | |
856 | |
857 | |
858 | |
859 | |
860 | |
861 | |
862 | |
863 | |
864 | |
865 | |
866 | |
867 | template<typename _ForwardIterator, typename _Tp> |
868 | _GLIBCXX20_CONSTEXPR |
869 | inline _ForwardIterator |
870 | remove(_ForwardIterator __first, _ForwardIterator __last, |
871 | const _Tp& __value) |
872 | { |
873 | |
874 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
875 | _ForwardIterator>) |
876 | __glibcxx_function_requires(_EqualOpConcept< |
877 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
878 | __glibcxx_requires_valid_range(__first, __last); |
879 | |
880 | return std::__remove_if(__first, __last, |
881 | __gnu_cxx::__ops::__iter_equals_val(__value)); |
882 | } |
883 | |
884 | |
885 | |
886 | |
887 | |
888 | |
889 | |
890 | |
891 | |
892 | |
893 | |
894 | |
895 | |
896 | |
897 | |
898 | |
899 | |
900 | |
901 | template<typename _ForwardIterator, typename _Predicate> |
902 | _GLIBCXX20_CONSTEXPR |
903 | inline _ForwardIterator |
904 | remove_if(_ForwardIterator __first, _ForwardIterator __last, |
905 | _Predicate __pred) |
906 | { |
907 | |
908 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
909 | _ForwardIterator>) |
910 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
911 | typename iterator_traits<_ForwardIterator>::value_type>) |
912 | __glibcxx_requires_valid_range(__first, __last); |
913 | |
914 | return std::__remove_if(__first, __last, |
915 | __gnu_cxx::__ops::__pred_iter(__pred)); |
916 | } |
917 | |
918 | template<typename _ForwardIterator, typename _BinaryPredicate> |
919 | _GLIBCXX20_CONSTEXPR |
920 | _ForwardIterator |
921 | __adjacent_find(_ForwardIterator __first, _ForwardIterator __last, |
922 | _BinaryPredicate __binary_pred) |
923 | { |
924 | if (__first == __last) |
925 | return __last; |
926 | _ForwardIterator __next = __first; |
927 | while (++__next != __last) |
928 | { |
929 | if (__binary_pred(__first, __next)) |
930 | return __first; |
931 | __first = __next; |
932 | } |
933 | return __last; |
934 | } |
935 | |
936 | template<typename _ForwardIterator, typename _BinaryPredicate> |
937 | _GLIBCXX20_CONSTEXPR |
938 | _ForwardIterator |
939 | __unique(_ForwardIterator __first, _ForwardIterator __last, |
940 | _BinaryPredicate __binary_pred) |
941 | { |
942 | |
943 | __first = std::__adjacent_find(__first, __last, __binary_pred); |
944 | if (__first == __last) |
945 | return __last; |
946 | |
947 | |
948 | _ForwardIterator __dest = __first; |
949 | ++__first; |
950 | while (++__first != __last) |
951 | if (!__binary_pred(__dest, __first)) |
952 | *++__dest = _GLIBCXX_MOVE(*__first); |
953 | return ++__dest; |
954 | } |
955 | |
956 | |
957 | |
958 | |
959 | |
960 | |
961 | |
962 | |
963 | |
964 | |
965 | |
966 | |
967 | |
968 | |
969 | |
970 | template<typename _ForwardIterator> |
971 | _GLIBCXX20_CONSTEXPR |
972 | inline _ForwardIterator |
973 | unique(_ForwardIterator __first, _ForwardIterator __last) |
974 | { |
975 | |
976 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
977 | _ForwardIterator>) |
978 | __glibcxx_function_requires(_EqualityComparableConcept< |
979 | typename iterator_traits<_ForwardIterator>::value_type>) |
980 | __glibcxx_requires_valid_range(__first, __last); |
981 | |
982 | return std::__unique(__first, __last, |
983 | __gnu_cxx::__ops::__iter_equal_to_iter()); |
984 | } |
985 | |
986 | |
987 | |
988 | |
989 | |
990 | |
991 | |
992 | |
993 | |
994 | |
995 | |
996 | |
997 | |
998 | |
999 | |
1000 | |
1001 | template<typename _ForwardIterator, typename _BinaryPredicate> |
1002 | _GLIBCXX20_CONSTEXPR |
1003 | inline _ForwardIterator |
1004 | unique(_ForwardIterator __first, _ForwardIterator __last, |
1005 | _BinaryPredicate __binary_pred) |
1006 | { |
1007 | |
1008 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
1009 | _ForwardIterator>) |
1010 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
1011 | typename iterator_traits<_ForwardIterator>::value_type, |
1012 | typename iterator_traits<_ForwardIterator>::value_type>) |
1013 | __glibcxx_requires_valid_range(__first, __last); |
1014 | |
1015 | return std::__unique(__first, __last, |
1016 | __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); |
1017 | } |
1018 | |
1019 | |
1020 | |
1021 | |
1022 | |
1023 | |
1024 | |
1025 | template<typename _ForwardIterator, typename _OutputIterator, |
1026 | typename _BinaryPredicate> |
1027 | _GLIBCXX20_CONSTEXPR |
1028 | _OutputIterator |
1029 | __unique_copy(_ForwardIterator __first, _ForwardIterator __last, |
1030 | _OutputIterator __result, _BinaryPredicate __binary_pred, |
1031 | forward_iterator_tag, output_iterator_tag) |
1032 | { |
1033 | |
1034 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
1035 | typename iterator_traits<_ForwardIterator>::value_type, |
1036 | typename iterator_traits<_ForwardIterator>::value_type>) |
1037 | |
1038 | _ForwardIterator __next = __first; |
1039 | *__result = *__first; |
1040 | while (++__next != __last) |
1041 | if (!__binary_pred(__first, __next)) |
1042 | { |
1043 | __first = __next; |
1044 | *++__result = *__first; |
1045 | } |
1046 | return ++__result; |
1047 | } |
1048 | |
1049 | |
1050 | |
1051 | |
1052 | |
1053 | |
1054 | |
1055 | template<typename _InputIterator, typename _OutputIterator, |
1056 | typename _BinaryPredicate> |
1057 | _GLIBCXX20_CONSTEXPR |
1058 | _OutputIterator |
1059 | __unique_copy(_InputIterator __first, _InputIterator __last, |
1060 | _OutputIterator __result, _BinaryPredicate __binary_pred, |
1061 | input_iterator_tag, output_iterator_tag) |
1062 | { |
1063 | |
1064 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
1065 | typename iterator_traits<_InputIterator>::value_type, |
1066 | typename iterator_traits<_InputIterator>::value_type>) |
1067 | |
1068 | typename iterator_traits<_InputIterator>::value_type __value = *__first; |
1069 | __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred)) |
1070 | __rebound_pred |
1071 | = __gnu_cxx::__ops::__iter_comp_val(__binary_pred); |
1072 | *__result = __value; |
1073 | while (++__first != __last) |
1074 | if (!__rebound_pred(__first, __value)) |
1075 | { |
1076 | __value = *__first; |
1077 | *++__result = __value; |
1078 | } |
1079 | return ++__result; |
1080 | } |
1081 | |
1082 | |
1083 | |
1084 | |
1085 | |
1086 | |
1087 | |
1088 | template<typename _InputIterator, typename _ForwardIterator, |
1089 | typename _BinaryPredicate> |
1090 | _GLIBCXX20_CONSTEXPR |
1091 | _ForwardIterator |
1092 | __unique_copy(_InputIterator __first, _InputIterator __last, |
1093 | _ForwardIterator __result, _BinaryPredicate __binary_pred, |
1094 | input_iterator_tag, forward_iterator_tag) |
1095 | { |
1096 | |
1097 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
1098 | typename iterator_traits<_ForwardIterator>::value_type, |
1099 | typename iterator_traits<_InputIterator>::value_type>) |
1100 | *__result = *__first; |
1101 | while (++__first != __last) |
1102 | if (!__binary_pred(__result, __first)) |
1103 | *++__result = *__first; |
1104 | return ++__result; |
1105 | } |
1106 | |
1107 | |
1108 | |
1109 | |
1110 | |
1111 | |
1112 | template<typename _BidirectionalIterator> |
1113 | _GLIBCXX20_CONSTEXPR |
1114 | void |
1115 | __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, |
1116 | bidirectional_iterator_tag) |
1117 | { |
1118 | while (true) |
1119 | if (__first == __last || __first == --__last) |
1120 | return; |
1121 | else |
1122 | { |
1123 | std::iter_swap(__first, __last); |
1124 | ++__first; |
1125 | } |
1126 | } |
1127 | |
1128 | |
1129 | |
1130 | |
1131 | |
1132 | |
1133 | template<typename _RandomAccessIterator> |
1134 | _GLIBCXX20_CONSTEXPR |
1135 | void |
1136 | __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, |
1137 | random_access_iterator_tag) |
1138 | { |
1139 | if (__first == __last) |
1140 | return; |
1141 | --__last; |
1142 | while (__first < __last) |
1143 | { |
1144 | std::iter_swap(__first, __last); |
1145 | ++__first; |
1146 | --__last; |
1147 | } |
1148 | } |
1149 | |
1150 | |
1151 | |
1152 | |
1153 | |
1154 | |
1155 | |
1156 | |
1157 | |
1158 | |
1159 | |
1160 | |
1161 | |
1162 | template<typename _BidirectionalIterator> |
1163 | _GLIBCXX20_CONSTEXPR |
1164 | inline void |
1165 | reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) |
1166 | { |
1167 | |
1168 | __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< |
1169 | _BidirectionalIterator>) |
1170 | __glibcxx_requires_valid_range(__first, __last); |
1171 | std::__reverse(__first, __last, std::__iterator_category(__first)); |
1172 | } |
1173 | |
1174 | |
1175 | |
1176 | |
1177 | |
1178 | |
1179 | |
1180 | |
1181 | |
1182 | |
1183 | |
1184 | |
1185 | |
1186 | |
1187 | |
1188 | |
1189 | |
1190 | template<typename _BidirectionalIterator, typename _OutputIterator> |
1191 | _GLIBCXX20_CONSTEXPR |
1192 | _OutputIterator |
1193 | reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, |
1194 | _OutputIterator __result) |
1195 | { |
1196 | |
1197 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
1198 | _BidirectionalIterator>) |
1199 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
1200 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
1201 | __glibcxx_requires_valid_range(__first, __last); |
1202 | |
1203 | while (__first != __last) |
1204 | { |
1205 | --__last; |
1206 | *__result = *__last; |
1207 | ++__result; |
1208 | } |
1209 | return __result; |
1210 | } |
1211 | |
1212 | |
1213 | |
1214 | |
1215 | |
1216 | template<typename _EuclideanRingElement> |
1217 | _GLIBCXX20_CONSTEXPR |
1218 | _EuclideanRingElement |
1219 | __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n) |
1220 | { |
1221 | while (__n != 0) |
1222 | { |
1223 | _EuclideanRingElement __t = __m % __n; |
1224 | __m = __n; |
1225 | __n = __t; |
1226 | } |
1227 | return __m; |
1228 | } |
1229 | |
1230 | inline namespace _V2 |
1231 | { |
1232 | |
1233 | |
1234 | template<typename _ForwardIterator> |
1235 | _GLIBCXX20_CONSTEXPR |
1236 | _ForwardIterator |
1237 | __rotate(_ForwardIterator __first, |
1238 | _ForwardIterator __middle, |
1239 | _ForwardIterator __last, |
1240 | forward_iterator_tag) |
1241 | { |
1242 | if (__first == __middle) |
1243 | return __last; |
1244 | else if (__last == __middle) |
1245 | return __first; |
1246 | |
1247 | _ForwardIterator __first2 = __middle; |
1248 | do |
1249 | { |
1250 | std::iter_swap(__first, __first2); |
1251 | ++__first; |
1252 | ++__first2; |
1253 | if (__first == __middle) |
1254 | __middle = __first2; |
1255 | } |
1256 | while (__first2 != __last); |
1257 | |
1258 | _ForwardIterator __ret = __first; |
1259 | |
1260 | __first2 = __middle; |
1261 | |
1262 | while (__first2 != __last) |
1263 | { |
1264 | std::iter_swap(__first, __first2); |
1265 | ++__first; |
1266 | ++__first2; |
1267 | if (__first == __middle) |
1268 | __middle = __first2; |
1269 | else if (__first2 == __last) |
1270 | __first2 = __middle; |
1271 | } |
1272 | return __ret; |
1273 | } |
1274 | |
1275 | |
1276 | template<typename _BidirectionalIterator> |
1277 | _GLIBCXX20_CONSTEXPR |
1278 | _BidirectionalIterator |
1279 | __rotate(_BidirectionalIterator __first, |
1280 | _BidirectionalIterator __middle, |
1281 | _BidirectionalIterator __last, |
1282 | bidirectional_iterator_tag) |
1283 | { |
1284 | |
1285 | __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< |
1286 | _BidirectionalIterator>) |
1287 | |
1288 | if (__first == __middle) |
1289 | return __last; |
1290 | else if (__last == __middle) |
1291 | return __first; |
1292 | |
1293 | std::__reverse(__first, __middle, bidirectional_iterator_tag()); |
1294 | std::__reverse(__middle, __last, bidirectional_iterator_tag()); |
1295 | |
1296 | while (__first != __middle && __middle != __last) |
1297 | { |
1298 | std::iter_swap(__first, --__last); |
1299 | ++__first; |
1300 | } |
1301 | |
1302 | if (__first == __middle) |
1303 | { |
1304 | std::__reverse(__middle, __last, bidirectional_iterator_tag()); |
1305 | return __last; |
1306 | } |
1307 | else |
1308 | { |
1309 | std::__reverse(__first, __middle, bidirectional_iterator_tag()); |
1310 | return __first; |
1311 | } |
1312 | } |
1313 | |
1314 | |
1315 | template<typename _RandomAccessIterator> |
1316 | _GLIBCXX20_CONSTEXPR |
1317 | _RandomAccessIterator |
1318 | __rotate(_RandomAccessIterator __first, |
1319 | _RandomAccessIterator __middle, |
1320 | _RandomAccessIterator __last, |
1321 | random_access_iterator_tag) |
1322 | { |
1323 | |
1324 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
1325 | _RandomAccessIterator>) |
1326 | |
1327 | if (__first == __middle) |
1328 | return __last; |
1329 | else if (__last == __middle) |
1330 | return __first; |
1331 | |
1332 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type |
1333 | _Distance; |
1334 | typedef typename iterator_traits<_RandomAccessIterator>::value_type |
1335 | _ValueType; |
1336 | |
1337 | _Distance __n = __last - __first; |
1338 | _Distance __k = __middle - __first; |
1339 | |
1340 | if (__k == __n - __k) |
1341 | { |
1342 | std::swap_ranges(__first, __middle, __middle); |
1343 | return __middle; |
1344 | } |
1345 | |
1346 | _RandomAccessIterator __p = __first; |
1347 | _RandomAccessIterator __ret = __first + (__last - __middle); |
1348 | |
1349 | for (;;) |
1350 | { |
1351 | if (__k < __n - __k) |
1352 | { |
1353 | if (__is_pod(_ValueType) && __k == 1) |
1354 | { |
1355 | _ValueType __t = _GLIBCXX_MOVE(*__p); |
1356 | _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); |
1357 | *(__p + __n - 1) = _GLIBCXX_MOVE(__t); |
1358 | return __ret; |
1359 | } |
1360 | _RandomAccessIterator __q = __p + __k; |
1361 | for (_Distance __i = 0; __i < __n - __k; ++ __i) |
1362 | { |
1363 | std::iter_swap(__p, __q); |
1364 | ++__p; |
1365 | ++__q; |
1366 | } |
1367 | __n %= __k; |
1368 | if (__n == 0) |
1369 | return __ret; |
1370 | std::swap(__n, __k); |
1371 | __k = __n - __k; |
1372 | } |
1373 | else |
1374 | { |
1375 | __k = __n - __k; |
1376 | if (__is_pod(_ValueType) && __k == 1) |
1377 | { |
1378 | _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); |
1379 | _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); |
1380 | *__p = _GLIBCXX_MOVE(__t); |
1381 | return __ret; |
1382 | } |
1383 | _RandomAccessIterator __q = __p + __n; |
1384 | __p = __q - __k; |
1385 | for (_Distance __i = 0; __i < __n - __k; ++ __i) |
1386 | { |
1387 | --__p; |
1388 | --__q; |
1389 | std::iter_swap(__p, __q); |
1390 | } |
1391 | __n %= __k; |
1392 | if (__n == 0) |
1393 | return __ret; |
1394 | std::swap(__n, __k); |
1395 | } |
1396 | } |
1397 | } |
1398 | |
1399 | |
1400 | |
1401 | |
1402 | |
1403 | |
1404 | |
1405 | |
1406 | |
1407 | |
1408 | |
1409 | |
1410 | |
1411 | |
1412 | |
1413 | |
1414 | |
1415 | |
1416 | |
1417 | |
1418 | |
1419 | |
1420 | |
1421 | |
1422 | template<typename _ForwardIterator> |
1423 | _GLIBCXX20_CONSTEXPR |
1424 | inline _ForwardIterator |
1425 | rotate(_ForwardIterator __first, _ForwardIterator __middle, |
1426 | _ForwardIterator __last) |
1427 | { |
1428 | |
1429 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
1430 | _ForwardIterator>) |
1431 | __glibcxx_requires_valid_range(__first, __middle); |
1432 | __glibcxx_requires_valid_range(__middle, __last); |
1433 | |
1434 | return std::__rotate(__first, __middle, __last, |
1435 | std::__iterator_category(__first)); |
1436 | } |
1437 | |
1438 | } |
1439 | |
1440 | |
1441 | |
1442 | |
1443 | |
1444 | |
1445 | |
1446 | |
1447 | |
1448 | |
1449 | |
1450 | |
1451 | |
1452 | |
1453 | |
1454 | |
1455 | |
1456 | |
1457 | |
1458 | |
1459 | |
1460 | template<typename _ForwardIterator, typename _OutputIterator> |
1461 | _GLIBCXX20_CONSTEXPR |
1462 | inline _OutputIterator |
1463 | rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, |
1464 | _ForwardIterator __last, _OutputIterator __result) |
1465 | { |
1466 | |
1467 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
1468 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
1469 | typename iterator_traits<_ForwardIterator>::value_type>) |
1470 | __glibcxx_requires_valid_range(__first, __middle); |
1471 | __glibcxx_requires_valid_range(__middle, __last); |
1472 | |
1473 | return std::copy(__first, __middle, |
1474 | std::copy(__middle, __last, __result)); |
1475 | } |
1476 | |
1477 | |
1478 | template<typename _ForwardIterator, typename _Predicate> |
1479 | _GLIBCXX20_CONSTEXPR |
1480 | _ForwardIterator |
1481 | __partition(_ForwardIterator __first, _ForwardIterator __last, |
1482 | _Predicate __pred, forward_iterator_tag) |
1483 | { |
1484 | if (__first == __last) |
1485 | return __first; |
1486 | |
1487 | while (__pred(*__first)) |
1488 | if (++__first == __last) |
1489 | return __first; |
1490 | |
1491 | _ForwardIterator __next = __first; |
1492 | |
1493 | while (++__next != __last) |
1494 | if (__pred(*__next)) |
1495 | { |
1496 | std::iter_swap(__first, __next); |
1497 | ++__first; |
1498 | } |
1499 | |
1500 | return __first; |
1501 | } |
1502 | |
1503 | |
1504 | template<typename _BidirectionalIterator, typename _Predicate> |
1505 | _GLIBCXX20_CONSTEXPR |
1506 | _BidirectionalIterator |
1507 | __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, |
1508 | _Predicate __pred, bidirectional_iterator_tag) |
1509 | { |
1510 | while (true) |
1511 | { |
1512 | while (true) |
1513 | if (__first == __last) |
1514 | return __first; |
1515 | else if (__pred(*__first)) |
1516 | ++__first; |
1517 | else |
1518 | break; |
1519 | --__last; |
1520 | while (true) |
1521 | if (__first == __last) |
1522 | return __first; |
1523 | else if (!bool(__pred(*__last))) |
1524 | --__last; |
1525 | else |
1526 | break; |
1527 | std::iter_swap(__first, __last); |
1528 | ++__first; |
1529 | } |
1530 | } |
1531 | |
1532 | |
1533 | |
1534 | |
1535 | |
1536 | |
1537 | |
1538 | |
1539 | |
1540 | template<typename _ForwardIterator, typename _Pointer, typename _Predicate, |
1541 | typename _Distance> |
1542 | _ForwardIterator |
1543 | __stable_partition_adaptive(_ForwardIterator __first, |
1544 | _ForwardIterator __last, |
1545 | _Predicate __pred, _Distance __len, |
1546 | _Pointer __buffer, |
1547 | _Distance __buffer_size) |
1548 | { |
1549 | if (__len == 1) |
1550 | return __first; |
1551 | |
1552 | if (__len <= __buffer_size) |
1553 | { |
1554 | _ForwardIterator __result1 = __first; |
1555 | _Pointer __result2 = __buffer; |
1556 | |
1557 | |
1558 | |
1559 | |
1560 | *__result2 = _GLIBCXX_MOVE(*__first); |
1561 | ++__result2; |
1562 | ++__first; |
1563 | for (; __first != __last; ++__first) |
1564 | if (__pred(__first)) |
1565 | { |
1566 | *__result1 = _GLIBCXX_MOVE(*__first); |
1567 | ++__result1; |
1568 | } |
1569 | else |
1570 | { |
1571 | *__result2 = _GLIBCXX_MOVE(*__first); |
1572 | ++__result2; |
1573 | } |
1574 | |
1575 | _GLIBCXX_MOVE3(__buffer, __result2, __result1); |
1576 | return __result1; |
1577 | } |
1578 | |
1579 | _ForwardIterator __middle = __first; |
1580 | std::advance(__middle, __len / 2); |
1581 | _ForwardIterator __left_split = |
1582 | std::__stable_partition_adaptive(__first, __middle, __pred, |
1583 | __len / 2, __buffer, |
1584 | __buffer_size); |
1585 | |
1586 | |
1587 | |
1588 | _Distance __right_len = __len - __len / 2; |
1589 | _ForwardIterator __right_split = |
1590 | std::__find_if_not_n(__middle, __right_len, __pred); |
1591 | |
1592 | if (__right_len) |
1593 | __right_split = |
1594 | std::__stable_partition_adaptive(__right_split, __last, __pred, |
1595 | __right_len, |
1596 | __buffer, __buffer_size); |
1597 | |
1598 | return std::rotate(__left_split, __middle, __right_split); |
1599 | } |
1600 | |
1601 | template<typename _ForwardIterator, typename _Predicate> |
1602 | _ForwardIterator |
1603 | __stable_partition(_ForwardIterator __first, _ForwardIterator __last, |
1604 | _Predicate __pred) |
1605 | { |
1606 | __first = std::__find_if_not(__first, __last, __pred); |
1607 | |
1608 | if (__first == __last) |
1609 | return __first; |
1610 | |
1611 | typedef typename iterator_traits<_ForwardIterator>::value_type |
1612 | _ValueType; |
1613 | typedef typename iterator_traits<_ForwardIterator>::difference_type |
1614 | _DistanceType; |
1615 | |
1616 | _Temporary_buffer<_ForwardIterator, _ValueType> |
1617 | __buf(__first, std::distance(__first, __last)); |
1618 | return |
1619 | std::__stable_partition_adaptive(__first, __last, __pred, |
1620 | _DistanceType(__buf.requested_size()), |
1621 | __buf.begin(), |
1622 | _DistanceType(__buf.size())); |
1623 | } |
1624 | |
1625 | |
1626 | |
1627 | |
1628 | |
1629 | |
1630 | |
1631 | |
1632 | |
1633 | |
1634 | |
1635 | |
1636 | |
1637 | |
1638 | |
1639 | |
1640 | |
1641 | |
1642 | template<typename _ForwardIterator, typename _Predicate> |
1643 | inline _ForwardIterator |
1644 | stable_partition(_ForwardIterator __first, _ForwardIterator __last, |
1645 | _Predicate __pred) |
1646 | { |
1647 | |
1648 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
1649 | _ForwardIterator>) |
1650 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
1651 | typename iterator_traits<_ForwardIterator>::value_type>) |
1652 | __glibcxx_requires_valid_range(__first, __last); |
1653 | |
1654 | return std::__stable_partition(__first, __last, |
1655 | __gnu_cxx::__ops::__pred_iter(__pred)); |
1656 | } |
1657 | |
1658 | |
1659 | template<typename _RandomAccessIterator, typename _Compare> |
1660 | _GLIBCXX20_CONSTEXPR |
1661 | void |
1662 | __heap_select(_RandomAccessIterator __first, |
1663 | _RandomAccessIterator __middle, |
1664 | _RandomAccessIterator __last, _Compare __comp) |
1665 | { |
1666 | std::__make_heap(__first, __middle, __comp); |
1667 | for (_RandomAccessIterator __i = __middle; __i < __last; ++__i) |
1668 | if (__comp(__i, __first)) |
1669 | std::__pop_heap(__first, __middle, __i, __comp); |
1670 | } |
1671 | |
1672 | |
1673 | |
1674 | template<typename _InputIterator, typename _RandomAccessIterator, |
1675 | typename _Compare> |
1676 | _GLIBCXX20_CONSTEXPR |
1677 | _RandomAccessIterator |
1678 | __partial_sort_copy(_InputIterator __first, _InputIterator __last, |
1679 | _RandomAccessIterator __result_first, |
1680 | _RandomAccessIterator __result_last, |
1681 | _Compare __comp) |
1682 | { |
1683 | typedef typename iterator_traits<_InputIterator>::value_type |
1684 | _InputValueType; |
1685 | typedef iterator_traits<_RandomAccessIterator> _RItTraits; |
1686 | typedef typename _RItTraits::difference_type _DistanceType; |
1687 | |
1688 | if (__result_first == __result_last) |
1689 | return __result_last; |
1690 | _RandomAccessIterator __result_real_last = __result_first; |
1691 | while (__first != __last && __result_real_last != __result_last) |
1692 | { |
1693 | *__result_real_last = *__first; |
1694 | ++__result_real_last; |
1695 | ++__first; |
1696 | } |
1697 | |
1698 | std::__make_heap(__result_first, __result_real_last, __comp); |
1699 | while (__first != __last) |
1700 | { |
1701 | if (__comp(__first, __result_first)) |
1702 | std::__adjust_heap(__result_first, _DistanceType(0), |
1703 | _DistanceType(__result_real_last |
1704 | - __result_first), |
1705 | _InputValueType(*__first), __comp); |
1706 | ++__first; |
1707 | } |
1708 | std::__sort_heap(__result_first, __result_real_last, __comp); |
1709 | return __result_real_last; |
1710 | } |
1711 | |
1712 | |
1713 | |
1714 | |
1715 | |
1716 | |
1717 | |
1718 | |
1719 | |
1720 | |
1721 | |
1722 | |
1723 | |
1724 | |
1725 | |
1726 | |
1727 | |
1728 | |
1729 | |
1730 | template<typename _InputIterator, typename _RandomAccessIterator> |
1731 | _GLIBCXX20_CONSTEXPR |
1732 | inline _RandomAccessIterator |
1733 | partial_sort_copy(_InputIterator __first, _InputIterator __last, |
1734 | _RandomAccessIterator __result_first, |
1735 | _RandomAccessIterator __result_last) |
1736 | { |
1737 | #ifdef _GLIBCXX_CONCEPT_CHECKS |
1738 | typedef typename iterator_traits<_InputIterator>::value_type |
1739 | _InputValueType; |
1740 | typedef typename iterator_traits<_RandomAccessIterator>::value_type |
1741 | _OutputValueType; |
1742 | #endif |
1743 | |
1744 | |
1745 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
1746 | __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, |
1747 | _OutputValueType>) |
1748 | __glibcxx_function_requires(_LessThanOpConcept<_InputValueType, |
1749 | _OutputValueType>) |
1750 | __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>) |
1751 | __glibcxx_requires_valid_range(__first, __last); |
1752 | __glibcxx_requires_irreflexive(__first, __last); |
1753 | __glibcxx_requires_valid_range(__result_first, __result_last); |
1754 | |
1755 | return std::__partial_sort_copy(__first, __last, |
1756 | __result_first, __result_last, |
1757 | __gnu_cxx::__ops::__iter_less_iter()); |
1758 | } |
1759 | |
1760 | |
1761 | |
1762 | |
1763 | |
1764 | |
1765 | |
1766 | |
1767 | |
1768 | |
1769 | |
1770 | |
1771 | |
1772 | |
1773 | |
1774 | |
1775 | |
1776 | |
1777 | |
1778 | |
1779 | |
1780 | template<typename _InputIterator, typename _RandomAccessIterator, |
1781 | typename _Compare> |
1782 | _GLIBCXX20_CONSTEXPR |
1783 | inline _RandomAccessIterator |
1784 | partial_sort_copy(_InputIterator __first, _InputIterator __last, |
1785 | _RandomAccessIterator __result_first, |
1786 | _RandomAccessIterator __result_last, |
1787 | _Compare __comp) |
1788 | { |
1789 | #ifdef _GLIBCXX_CONCEPT_CHECKS |
1790 | typedef typename iterator_traits<_InputIterator>::value_type |
1791 | _InputValueType; |
1792 | typedef typename iterator_traits<_RandomAccessIterator>::value_type |
1793 | _OutputValueType; |
1794 | #endif |
1795 | |
1796 | |
1797 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
1798 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
1799 | _RandomAccessIterator>) |
1800 | __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, |
1801 | _OutputValueType>) |
1802 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
1803 | _InputValueType, _OutputValueType>) |
1804 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
1805 | _OutputValueType, _OutputValueType>) |
1806 | __glibcxx_requires_valid_range(__first, __last); |
1807 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
1808 | __glibcxx_requires_valid_range(__result_first, __result_last); |
1809 | |
1810 | return std::__partial_sort_copy(__first, __last, |
1811 | __result_first, __result_last, |
1812 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
1813 | } |
1814 | |
1815 | |
1816 | template<typename _RandomAccessIterator, typename _Compare> |
1817 | _GLIBCXX20_CONSTEXPR |
1818 | void |
1819 | __unguarded_linear_insert(_RandomAccessIterator __last, |
1820 | _Compare __comp) |
1821 | { |
1822 | typename iterator_traits<_RandomAccessIterator>::value_type |
1823 | __val = _GLIBCXX_MOVE(*__last); |
1824 | _RandomAccessIterator __next = __last; |
1825 | --__next; |
1826 | while (__comp(__val, __next)) |
1827 | { |
1828 | *__last = _GLIBCXX_MOVE(*__next); |
1829 | __last = __next; |
1830 | --__next; |
1831 | } |
1832 | *__last = _GLIBCXX_MOVE(__val); |
1833 | } |
1834 | |
1835 | |
1836 | template<typename _RandomAccessIterator, typename _Compare> |
1837 | _GLIBCXX20_CONSTEXPR |
1838 | void |
1839 | __insertion_sort(_RandomAccessIterator __first, |
1840 | _RandomAccessIterator __last, _Compare __comp) |
1841 | { |
1842 | if (__first == __last) return; |
| |
1843 | |
1844 | for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) |
| 61 | | Loop condition is true. Entering loop body | |
|
1845 | { |
1846 | if (__comp(__i, __first)) |
| 62 | | Calling '_Iter_less_iter::operator()' | |
|
1847 | { |
1848 | typename iterator_traits<_RandomAccessIterator>::value_type |
1849 | __val = _GLIBCXX_MOVE(*__i); |
1850 | _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1); |
1851 | *__first = _GLIBCXX_MOVE(__val); |
1852 | } |
1853 | else |
1854 | std::__unguarded_linear_insert(__i, |
1855 | __gnu_cxx::__ops::__val_comp_iter(__comp)); |
1856 | } |
1857 | } |
1858 | |
1859 | |
1860 | template<typename _RandomAccessIterator, typename _Compare> |
1861 | _GLIBCXX20_CONSTEXPR |
1862 | inline void |
1863 | __unguarded_insertion_sort(_RandomAccessIterator __first, |
1864 | _RandomAccessIterator __last, _Compare __comp) |
1865 | { |
1866 | for (_RandomAccessIterator __i = __first; __i != __last; ++__i) |
1867 | std::__unguarded_linear_insert(__i, |
1868 | __gnu_cxx::__ops::__val_comp_iter(__comp)); |
1869 | } |
1870 | |
1871 | |
1872 | |
1873 | |
1874 | |
1875 | enum { _S_threshold = 16 }; |
1876 | |
1877 | |
1878 | template<typename _RandomAccessIterator, typename _Compare> |
1879 | _GLIBCXX20_CONSTEXPR |
1880 | void |
1881 | __final_insertion_sort(_RandomAccessIterator __first, |
1882 | _RandomAccessIterator __last, _Compare __comp) |
1883 | { |
1884 | if (__last - __first > int(_S_threshold)) |
| |
1885 | { |
1886 | std::__insertion_sort(__first, __first + int(_S_threshold), __comp); |
1887 | std::__unguarded_insertion_sort(__first + int(_S_threshold), __last, |
1888 | __comp); |
1889 | } |
1890 | else |
1891 | std::__insertion_sort(__first, __last, __comp); |
| 59 | | Calling '__insertion_sort<unsigned int *, __gnu_cxx::__ops::_Iter_less_iter>' | |
|
1892 | } |
1893 | |
1894 | |
1895 | template<typename _RandomAccessIterator, typename _Compare> |
1896 | _GLIBCXX20_CONSTEXPR |
1897 | _RandomAccessIterator |
1898 | __unguarded_partition(_RandomAccessIterator __first, |
1899 | _RandomAccessIterator __last, |
1900 | _RandomAccessIterator __pivot, _Compare __comp) |
1901 | { |
1902 | while (true) |
1903 | { |
1904 | while (__comp(__first, __pivot)) |
1905 | ++__first; |
1906 | --__last; |
1907 | while (__comp(__pivot, __last)) |
1908 | --__last; |
1909 | if (!(__first < __last)) |
1910 | return __first; |
1911 | std::iter_swap(__first, __last); |
1912 | ++__first; |
1913 | } |
1914 | } |
1915 | |
1916 | |
1917 | template<typename _RandomAccessIterator, typename _Compare> |
1918 | _GLIBCXX20_CONSTEXPR |
1919 | inline _RandomAccessIterator |
1920 | __unguarded_partition_pivot(_RandomAccessIterator __first, |
1921 | _RandomAccessIterator __last, _Compare __comp) |
1922 | { |
1923 | _RandomAccessIterator __mid = __first + (__last - __first) / 2; |
1924 | std::__move_median_to_first(__first, __first + 1, __mid, __last - 1, |
1925 | __comp); |
1926 | return std::__unguarded_partition(__first + 1, __last, __first, __comp); |
1927 | } |
1928 | |
1929 | template<typename _RandomAccessIterator, typename _Compare> |
1930 | _GLIBCXX20_CONSTEXPR |
1931 | inline void |
1932 | __partial_sort(_RandomAccessIterator __first, |
1933 | _RandomAccessIterator __middle, |
1934 | _RandomAccessIterator __last, |
1935 | _Compare __comp) |
1936 | { |
1937 | std::__heap_select(__first, __middle, __last, __comp); |
1938 | std::__sort_heap(__first, __middle, __comp); |
1939 | } |
1940 | |
1941 | |
1942 | template<typename _RandomAccessIterator, typename _Size, typename _Compare> |
1943 | _GLIBCXX20_CONSTEXPR |
1944 | void |
1945 | __introsort_loop(_RandomAccessIterator __first, |
1946 | _RandomAccessIterator __last, |
1947 | _Size __depth_limit, _Compare __comp) |
1948 | { |
1949 | while (__last - __first > int(_S_threshold)) |
1950 | { |
1951 | if (__depth_limit == 0) |
1952 | { |
1953 | std::__partial_sort(__first, __last, __last, __comp); |
1954 | return; |
1955 | } |
1956 | --__depth_limit; |
1957 | _RandomAccessIterator __cut = |
1958 | std::__unguarded_partition_pivot(__first, __last, __comp); |
1959 | std::__introsort_loop(__cut, __last, __depth_limit, __comp); |
1960 | __last = __cut; |
1961 | } |
1962 | } |
1963 | |
1964 | |
1965 | |
1966 | template<typename _RandomAccessIterator, typename _Compare> |
1967 | _GLIBCXX20_CONSTEXPR |
1968 | inline void |
1969 | __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, |
1970 | _Compare __comp) |
1971 | { |
1972 | if (__first != __last) |
| |
1973 | { |
1974 | std::__introsort_loop(__first, __last, |
1975 | std::__lg(__last - __first) * 2, |
1976 | __comp); |
1977 | std::__final_insertion_sort(__first, __last, __comp); |
| 57 | | Calling '__final_insertion_sort<unsigned int *, __gnu_cxx::__ops::_Iter_less_iter>' | |
|
1978 | } |
1979 | } |
1980 | |
1981 | template<typename _RandomAccessIterator, typename _Size, typename _Compare> |
1982 | _GLIBCXX20_CONSTEXPR |
1983 | void |
1984 | __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth, |
1985 | _RandomAccessIterator __last, _Size __depth_limit, |
1986 | _Compare __comp) |
1987 | { |
1988 | while (__last - __first > 3) |
1989 | { |
1990 | if (__depth_limit == 0) |
1991 | { |
1992 | std::__heap_select(__first, __nth + 1, __last, __comp); |
1993 | |
1994 | std::iter_swap(__first, __nth); |
1995 | return; |
1996 | } |
1997 | --__depth_limit; |
1998 | _RandomAccessIterator __cut = |
1999 | std::__unguarded_partition_pivot(__first, __last, __comp); |
2000 | if (__cut <= __nth) |
2001 | __first = __cut; |
2002 | else |
2003 | __last = __cut; |
2004 | } |
2005 | std::__insertion_sort(__first, __last, __comp); |
2006 | } |
2007 | |
2008 | |
2009 | |
2010 | |
2011 | |
2012 | |
2013 | |
2014 | |
2015 | |
2016 | |
2017 | |
2018 | |
2019 | |
2020 | |
2021 | |
2022 | |
2023 | |
2024 | |
2025 | |
2026 | |
2027 | |
2028 | template<typename _ForwardIterator, typename _Tp, typename _Compare> |
2029 | _GLIBCXX20_CONSTEXPR |
2030 | inline _ForwardIterator |
2031 | lower_bound(_ForwardIterator __first, _ForwardIterator __last, |
2032 | const _Tp& __val, _Compare __comp) |
2033 | { |
2034 | |
2035 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2036 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2037 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
2038 | __glibcxx_requires_partitioned_lower_pred(__first, __last, |
2039 | __val, __comp); |
2040 | |
2041 | return std::__lower_bound(__first, __last, __val, |
2042 | __gnu_cxx::__ops::__iter_comp_val(__comp)); |
2043 | } |
2044 | |
2045 | template<typename _ForwardIterator, typename _Tp, typename _Compare> |
2046 | _GLIBCXX20_CONSTEXPR |
2047 | _ForwardIterator |
2048 | __upper_bound(_ForwardIterator __first, _ForwardIterator __last, |
2049 | const _Tp& __val, _Compare __comp) |
2050 | { |
2051 | typedef typename iterator_traits<_ForwardIterator>::difference_type |
2052 | _DistanceType; |
2053 | |
2054 | _DistanceType __len = std::distance(__first, __last); |
2055 | |
2056 | while (__len > 0) |
2057 | { |
2058 | _DistanceType __half = __len >> 1; |
2059 | _ForwardIterator __middle = __first; |
2060 | std::advance(__middle, __half); |
2061 | if (__comp(__val, __middle)) |
2062 | __len = __half; |
2063 | else |
2064 | { |
2065 | __first = __middle; |
2066 | ++__first; |
2067 | __len = __len - __half - 1; |
2068 | } |
2069 | } |
2070 | return __first; |
2071 | } |
2072 | |
2073 | |
2074 | |
2075 | |
2076 | |
2077 | |
2078 | |
2079 | |
2080 | |
2081 | |
2082 | |
2083 | |
2084 | template<typename _ForwardIterator, typename _Tp> |
2085 | _GLIBCXX20_CONSTEXPR |
2086 | inline _ForwardIterator |
2087 | upper_bound(_ForwardIterator __first, _ForwardIterator __last, |
2088 | const _Tp& __val) |
2089 | { |
2090 | |
2091 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2092 | __glibcxx_function_requires(_LessThanOpConcept< |
2093 | _Tp, typename iterator_traits<_ForwardIterator>::value_type>) |
2094 | __glibcxx_requires_partitioned_upper(__first, __last, __val); |
2095 | |
2096 | return std::__upper_bound(__first, __last, __val, |
2097 | __gnu_cxx::__ops::__val_less_iter()); |
2098 | } |
2099 | |
2100 | |
2101 | |
2102 | |
2103 | |
2104 | |
2105 | |
2106 | |
2107 | |
2108 | |
2109 | |
2110 | |
2111 | |
2112 | |
2113 | |
2114 | |
2115 | template<typename _ForwardIterator, typename _Tp, typename _Compare> |
2116 | _GLIBCXX20_CONSTEXPR |
2117 | inline _ForwardIterator |
2118 | upper_bound(_ForwardIterator __first, _ForwardIterator __last, |
2119 | const _Tp& __val, _Compare __comp) |
2120 | { |
2121 | |
2122 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2123 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2124 | _Tp, typename iterator_traits<_ForwardIterator>::value_type>) |
2125 | __glibcxx_requires_partitioned_upper_pred(__first, __last, |
2126 | __val, __comp); |
2127 | |
2128 | return std::__upper_bound(__first, __last, __val, |
2129 | __gnu_cxx::__ops::__val_comp_iter(__comp)); |
2130 | } |
2131 | |
2132 | template<typename _ForwardIterator, typename _Tp, |
2133 | typename _CompareItTp, typename _CompareTpIt> |
2134 | _GLIBCXX20_CONSTEXPR |
2135 | pair<_ForwardIterator, _ForwardIterator> |
2136 | __equal_range(_ForwardIterator __first, _ForwardIterator __last, |
2137 | const _Tp& __val, |
2138 | _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it) |
2139 | { |
2140 | typedef typename iterator_traits<_ForwardIterator>::difference_type |
2141 | _DistanceType; |
2142 | |
2143 | _DistanceType __len = std::distance(__first, __last); |
2144 | |
2145 | while (__len > 0) |
2146 | { |
2147 | _DistanceType __half = __len >> 1; |
2148 | _ForwardIterator __middle = __first; |
2149 | std::advance(__middle, __half); |
2150 | if (__comp_it_val(__middle, __val)) |
2151 | { |
2152 | __first = __middle; |
2153 | ++__first; |
2154 | __len = __len - __half - 1; |
2155 | } |
2156 | else if (__comp_val_it(__val, __middle)) |
2157 | __len = __half; |
2158 | else |
2159 | { |
2160 | _ForwardIterator __left |
2161 | = std::__lower_bound(__first, __middle, __val, __comp_it_val); |
2162 | std::advance(__first, __len); |
2163 | _ForwardIterator __right |
2164 | = std::__upper_bound(++__middle, __first, __val, __comp_val_it); |
2165 | return pair<_ForwardIterator, _ForwardIterator>(__left, __right); |
2166 | } |
2167 | } |
2168 | return pair<_ForwardIterator, _ForwardIterator>(__first, __first); |
2169 | } |
2170 | |
2171 | |
2172 | |
2173 | |
2174 | |
2175 | |
2176 | |
2177 | |
2178 | |
2179 | |
2180 | |
2181 | |
2182 | |
2183 | |
2184 | |
2185 | |
2186 | |
2187 | |
2188 | template<typename _ForwardIterator, typename _Tp> |
2189 | _GLIBCXX20_CONSTEXPR |
2190 | inline pair<_ForwardIterator, _ForwardIterator> |
2191 | equal_range(_ForwardIterator __first, _ForwardIterator __last, |
2192 | const _Tp& __val) |
2193 | { |
2194 | |
2195 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2196 | __glibcxx_function_requires(_LessThanOpConcept< |
2197 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
2198 | __glibcxx_function_requires(_LessThanOpConcept< |
2199 | _Tp, typename iterator_traits<_ForwardIterator>::value_type>) |
2200 | __glibcxx_requires_partitioned_lower(__first, __last, __val); |
2201 | __glibcxx_requires_partitioned_upper(__first, __last, __val); |
2202 | |
2203 | return std::__equal_range(__first, __last, __val, |
2204 | __gnu_cxx::__ops::__iter_less_val(), |
2205 | __gnu_cxx::__ops::__val_less_iter()); |
2206 | } |
2207 | |
2208 | |
2209 | |
2210 | |
2211 | |
2212 | |
2213 | |
2214 | |
2215 | |
2216 | |
2217 | |
2218 | |
2219 | |
2220 | |
2221 | |
2222 | |
2223 | |
2224 | |
2225 | template<typename _ForwardIterator, typename _Tp, typename _Compare> |
2226 | _GLIBCXX20_CONSTEXPR |
2227 | inline pair<_ForwardIterator, _ForwardIterator> |
2228 | equal_range(_ForwardIterator __first, _ForwardIterator __last, |
2229 | const _Tp& __val, _Compare __comp) |
2230 | { |
2231 | |
2232 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2233 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2234 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
2235 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2236 | _Tp, typename iterator_traits<_ForwardIterator>::value_type>) |
2237 | __glibcxx_requires_partitioned_lower_pred(__first, __last, |
2238 | __val, __comp); |
2239 | __glibcxx_requires_partitioned_upper_pred(__first, __last, |
2240 | __val, __comp); |
2241 | |
2242 | return std::__equal_range(__first, __last, __val, |
2243 | __gnu_cxx::__ops::__iter_comp_val(__comp), |
2244 | __gnu_cxx::__ops::__val_comp_iter(__comp)); |
2245 | } |
2246 | |
2247 | |
2248 | |
2249 | |
2250 | |
2251 | |
2252 | |
2253 | |
2254 | |
2255 | |
2256 | |
2257 | |
2258 | |
2259 | template<typename _ForwardIterator, typename _Tp> |
2260 | _GLIBCXX20_CONSTEXPR |
2261 | bool |
2262 | binary_search(_ForwardIterator __first, _ForwardIterator __last, |
2263 | const _Tp& __val) |
2264 | { |
2265 | |
2266 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2267 | __glibcxx_function_requires(_LessThanOpConcept< |
2268 | _Tp, typename iterator_traits<_ForwardIterator>::value_type>) |
2269 | __glibcxx_requires_partitioned_lower(__first, __last, __val); |
2270 | __glibcxx_requires_partitioned_upper(__first, __last, __val); |
2271 | |
2272 | _ForwardIterator __i |
2273 | = std::__lower_bound(__first, __last, __val, |
2274 | __gnu_cxx::__ops::__iter_less_val()); |
2275 | return __i != __last && !(__val < *__i); |
2276 | } |
2277 | |
2278 | |
2279 | |
2280 | |
2281 | |
2282 | |
2283 | |
2284 | |
2285 | |
2286 | |
2287 | |
2288 | |
2289 | |
2290 | |
2291 | |
2292 | |
2293 | template<typename _ForwardIterator, typename _Tp, typename _Compare> |
2294 | _GLIBCXX20_CONSTEXPR |
2295 | bool |
2296 | binary_search(_ForwardIterator __first, _ForwardIterator __last, |
2297 | const _Tp& __val, _Compare __comp) |
2298 | { |
2299 | |
2300 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
2301 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2302 | _Tp, typename iterator_traits<_ForwardIterator>::value_type>) |
2303 | __glibcxx_requires_partitioned_lower_pred(__first, __last, |
2304 | __val, __comp); |
2305 | __glibcxx_requires_partitioned_upper_pred(__first, __last, |
2306 | __val, __comp); |
2307 | |
2308 | _ForwardIterator __i |
2309 | = std::__lower_bound(__first, __last, __val, |
2310 | __gnu_cxx::__ops::__iter_comp_val(__comp)); |
2311 | return __i != __last && !bool(__comp(__val, *__i)); |
2312 | } |
2313 | |
2314 | |
2315 | |
2316 | |
2317 | template<typename _InputIterator1, typename _InputIterator2, |
2318 | typename _OutputIterator, typename _Compare> |
2319 | void |
2320 | __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, |
2321 | _InputIterator2 __first2, _InputIterator2 __last2, |
2322 | _OutputIterator __result, _Compare __comp) |
2323 | { |
2324 | while (__first1 != __last1 && __first2 != __last2) |
2325 | { |
2326 | if (__comp(__first2, __first1)) |
2327 | { |
2328 | *__result = _GLIBCXX_MOVE(*__first2); |
2329 | ++__first2; |
2330 | } |
2331 | else |
2332 | { |
2333 | *__result = _GLIBCXX_MOVE(*__first1); |
2334 | ++__first1; |
2335 | } |
2336 | ++__result; |
2337 | } |
2338 | if (__first1 != __last1) |
2339 | _GLIBCXX_MOVE3(__first1, __last1, __result); |
2340 | } |
2341 | |
2342 | |
2343 | template<typename _BidirectionalIterator1, typename _BidirectionalIterator2, |
2344 | typename _BidirectionalIterator3, typename _Compare> |
2345 | void |
2346 | __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, |
2347 | _BidirectionalIterator1 __last1, |
2348 | _BidirectionalIterator2 __first2, |
2349 | _BidirectionalIterator2 __last2, |
2350 | _BidirectionalIterator3 __result, |
2351 | _Compare __comp) |
2352 | { |
2353 | if (__first1 == __last1) |
2354 | { |
2355 | _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); |
2356 | return; |
2357 | } |
2358 | else if (__first2 == __last2) |
2359 | return; |
2360 | |
2361 | --__last1; |
2362 | --__last2; |
2363 | while (true) |
2364 | { |
2365 | if (__comp(__last2, __last1)) |
2366 | { |
2367 | *--__result = _GLIBCXX_MOVE(*__last1); |
2368 | if (__first1 == __last1) |
2369 | { |
2370 | _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); |
2371 | return; |
2372 | } |
2373 | --__last1; |
2374 | } |
2375 | else |
2376 | { |
2377 | *--__result = _GLIBCXX_MOVE(*__last2); |
2378 | if (__first2 == __last2) |
2379 | return; |
2380 | --__last2; |
2381 | } |
2382 | } |
2383 | } |
2384 | |
2385 | |
2386 | template<typename _BidirectionalIterator1, typename _BidirectionalIterator2, |
2387 | typename _Distance> |
2388 | _BidirectionalIterator1 |
2389 | __rotate_adaptive(_BidirectionalIterator1 __first, |
2390 | _BidirectionalIterator1 __middle, |
2391 | _BidirectionalIterator1 __last, |
2392 | _Distance __len1, _Distance __len2, |
2393 | _BidirectionalIterator2 __buffer, |
2394 | _Distance __buffer_size) |
2395 | { |
2396 | _BidirectionalIterator2 __buffer_end; |
2397 | if (__len1 > __len2 && __len2 <= __buffer_size) |
2398 | { |
2399 | if (__len2) |
2400 | { |
2401 | __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); |
2402 | _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); |
2403 | return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); |
2404 | } |
2405 | else |
2406 | return __first; |
2407 | } |
2408 | else if (__len1 <= __buffer_size) |
2409 | { |
2410 | if (__len1) |
2411 | { |
2412 | __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); |
2413 | _GLIBCXX_MOVE3(__middle, __last, __first); |
2414 | return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); |
2415 | } |
2416 | else |
2417 | return __last; |
2418 | } |
2419 | else |
2420 | return std::rotate(__first, __middle, __last); |
2421 | } |
2422 | |
2423 | |
2424 | template<typename _BidirectionalIterator, typename _Distance, |
2425 | typename _Pointer, typename _Compare> |
2426 | void |
2427 | __merge_adaptive(_BidirectionalIterator __first, |
2428 | _BidirectionalIterator __middle, |
2429 | _BidirectionalIterator __last, |
2430 | _Distance __len1, _Distance __len2, |
2431 | _Pointer __buffer, _Distance __buffer_size, |
2432 | _Compare __comp) |
2433 | { |
2434 | if (__len1 <= __len2 && __len1 <= __buffer_size) |
2435 | { |
2436 | _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); |
2437 | std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, |
2438 | __first, __comp); |
2439 | } |
2440 | else if (__len2 <= __buffer_size) |
2441 | { |
2442 | _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); |
2443 | std::__move_merge_adaptive_backward(__first, __middle, __buffer, |
2444 | __buffer_end, __last, __comp); |
2445 | } |
2446 | else |
2447 | { |
2448 | _BidirectionalIterator __first_cut = __first; |
2449 | _BidirectionalIterator __second_cut = __middle; |
2450 | _Distance __len11 = 0; |
2451 | _Distance __len22 = 0; |
2452 | if (__len1 > __len2) |
2453 | { |
2454 | __len11 = __len1 / 2; |
2455 | std::advance(__first_cut, __len11); |
2456 | __second_cut |
2457 | = std::__lower_bound(__middle, __last, *__first_cut, |
2458 | __gnu_cxx::__ops::__iter_comp_val(__comp)); |
2459 | __len22 = std::distance(__middle, __second_cut); |
2460 | } |
2461 | else |
2462 | { |
2463 | __len22 = __len2 / 2; |
2464 | std::advance(__second_cut, __len22); |
2465 | __first_cut |
2466 | = std::__upper_bound(__first, __middle, *__second_cut, |
2467 | __gnu_cxx::__ops::__val_comp_iter(__comp)); |
2468 | __len11 = std::distance(__first, __first_cut); |
2469 | } |
2470 | |
2471 | _BidirectionalIterator __new_middle |
2472 | = std::__rotate_adaptive(__first_cut, __middle, __second_cut, |
2473 | __len1 - __len11, __len22, __buffer, |
2474 | __buffer_size); |
2475 | std::__merge_adaptive(__first, __first_cut, __new_middle, __len11, |
2476 | __len22, __buffer, __buffer_size, __comp); |
2477 | std::__merge_adaptive(__new_middle, __second_cut, __last, |
2478 | __len1 - __len11, |
2479 | __len2 - __len22, __buffer, |
2480 | __buffer_size, __comp); |
2481 | } |
2482 | } |
2483 | |
2484 | |
2485 | template<typename _BidirectionalIterator, typename _Distance, |
2486 | typename _Compare> |
2487 | void |
2488 | __merge_without_buffer(_BidirectionalIterator __first, |
2489 | _BidirectionalIterator __middle, |
2490 | _BidirectionalIterator __last, |
2491 | _Distance __len1, _Distance __len2, |
2492 | _Compare __comp) |
2493 | { |
2494 | if (__len1 == 0 || __len2 == 0) |
2495 | return; |
2496 | |
2497 | if (__len1 + __len2 == 2) |
2498 | { |
2499 | if (__comp(__middle, __first)) |
2500 | std::iter_swap(__first, __middle); |
2501 | return; |
2502 | } |
2503 | |
2504 | _BidirectionalIterator __first_cut = __first; |
2505 | _BidirectionalIterator __second_cut = __middle; |
2506 | _Distance __len11 = 0; |
2507 | _Distance __len22 = 0; |
2508 | if (__len1 > __len2) |
2509 | { |
2510 | __len11 = __len1 / 2; |
2511 | std::advance(__first_cut, __len11); |
2512 | __second_cut |
2513 | = std::__lower_bound(__middle, __last, *__first_cut, |
2514 | __gnu_cxx::__ops::__iter_comp_val(__comp)); |
2515 | __len22 = std::distance(__middle, __second_cut); |
2516 | } |
2517 | else |
2518 | { |
2519 | __len22 = __len2 / 2; |
2520 | std::advance(__second_cut, __len22); |
2521 | __first_cut |
2522 | = std::__upper_bound(__first, __middle, *__second_cut, |
2523 | __gnu_cxx::__ops::__val_comp_iter(__comp)); |
2524 | __len11 = std::distance(__first, __first_cut); |
2525 | } |
2526 | |
2527 | _BidirectionalIterator __new_middle |
2528 | = std::rotate(__first_cut, __middle, __second_cut); |
2529 | std::__merge_without_buffer(__first, __first_cut, __new_middle, |
2530 | __len11, __len22, __comp); |
2531 | std::__merge_without_buffer(__new_middle, __second_cut, __last, |
2532 | __len1 - __len11, __len2 - __len22, __comp); |
2533 | } |
2534 | |
2535 | template<typename _BidirectionalIterator, typename _Compare> |
2536 | void |
2537 | __inplace_merge(_BidirectionalIterator __first, |
2538 | _BidirectionalIterator __middle, |
2539 | _BidirectionalIterator __last, |
2540 | _Compare __comp) |
2541 | { |
2542 | typedef typename iterator_traits<_BidirectionalIterator>::value_type |
2543 | _ValueType; |
2544 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type |
2545 | _DistanceType; |
2546 | |
2547 | if (__first == __middle || __middle == __last) |
2548 | return; |
2549 | |
2550 | const _DistanceType __len1 = std::distance(__first, __middle); |
2551 | const _DistanceType __len2 = std::distance(__middle, __last); |
2552 | |
2553 | typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf; |
2554 | _TmpBuf __buf(__first, __len1 + __len2); |
2555 | |
2556 | if (__buf.begin() == 0) |
2557 | std::__merge_without_buffer |
2558 | (__first, __middle, __last, __len1, __len2, __comp); |
2559 | else |
2560 | std::__merge_adaptive |
2561 | (__first, __middle, __last, __len1, __len2, __buf.begin(), |
2562 | _DistanceType(__buf.size()), __comp); |
2563 | } |
2564 | |
2565 | |
2566 | |
2567 | |
2568 | |
2569 | |
2570 | |
2571 | |
2572 | |
2573 | |
2574 | |
2575 | |
2576 | |
2577 | |
2578 | |
2579 | |
2580 | |
2581 | |
2582 | |
2583 | template<typename _BidirectionalIterator> |
2584 | inline void |
2585 | inplace_merge(_BidirectionalIterator __first, |
2586 | _BidirectionalIterator __middle, |
2587 | _BidirectionalIterator __last) |
2588 | { |
2589 | |
2590 | __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< |
2591 | _BidirectionalIterator>) |
2592 | __glibcxx_function_requires(_LessThanComparableConcept< |
2593 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
2594 | __glibcxx_requires_sorted(__first, __middle); |
2595 | __glibcxx_requires_sorted(__middle, __last); |
2596 | __glibcxx_requires_irreflexive(__first, __last); |
2597 | |
2598 | std::__inplace_merge(__first, __middle, __last, |
2599 | __gnu_cxx::__ops::__iter_less_iter()); |
2600 | } |
2601 | |
2602 | |
2603 | |
2604 | |
2605 | |
2606 | |
2607 | |
2608 | |
2609 | |
2610 | |
2611 | |
2612 | |
2613 | |
2614 | |
2615 | |
2616 | |
2617 | |
2618 | |
2619 | |
2620 | |
2621 | |
2622 | |
2623 | |
2624 | template<typename _BidirectionalIterator, typename _Compare> |
2625 | inline void |
2626 | inplace_merge(_BidirectionalIterator __first, |
2627 | _BidirectionalIterator __middle, |
2628 | _BidirectionalIterator __last, |
2629 | _Compare __comp) |
2630 | { |
2631 | |
2632 | __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< |
2633 | _BidirectionalIterator>) |
2634 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2635 | typename iterator_traits<_BidirectionalIterator>::value_type, |
2636 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
2637 | __glibcxx_requires_sorted_pred(__first, __middle, __comp); |
2638 | __glibcxx_requires_sorted_pred(__middle, __last, __comp); |
2639 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
2640 | |
2641 | std::__inplace_merge(__first, __middle, __last, |
2642 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
2643 | } |
2644 | |
2645 | |
2646 | |
2647 | template<typename _InputIterator, typename _OutputIterator, |
2648 | typename _Compare> |
2649 | _OutputIterator |
2650 | __move_merge(_InputIterator __first1, _InputIterator __last1, |
2651 | _InputIterator __first2, _InputIterator __last2, |
2652 | _OutputIterator __result, _Compare __comp) |
2653 | { |
2654 | while (__first1 != __last1 && __first2 != __last2) |
2655 | { |
2656 | if (__comp(__first2, __first1)) |
2657 | { |
2658 | *__result = _GLIBCXX_MOVE(*__first2); |
2659 | ++__first2; |
2660 | } |
2661 | else |
2662 | { |
2663 | *__result = _GLIBCXX_MOVE(*__first1); |
2664 | ++__first1; |
2665 | } |
2666 | ++__result; |
2667 | } |
2668 | return _GLIBCXX_MOVE3(__first2, __last2, |
2669 | _GLIBCXX_MOVE3(__first1, __last1, |
2670 | __result)); |
2671 | } |
2672 | |
2673 | template<typename _RandomAccessIterator1, typename _RandomAccessIterator2, |
2674 | typename _Distance, typename _Compare> |
2675 | void |
2676 | __merge_sort_loop(_RandomAccessIterator1 __first, |
2677 | _RandomAccessIterator1 __last, |
2678 | _RandomAccessIterator2 __result, _Distance __step_size, |
2679 | _Compare __comp) |
2680 | { |
2681 | const _Distance __two_step = 2 * __step_size; |
2682 | |
2683 | while (__last - __first >= __two_step) |
2684 | { |
2685 | __result = std::__move_merge(__first, __first + __step_size, |
2686 | __first + __step_size, |
2687 | __first + __two_step, |
2688 | __result, __comp); |
2689 | __first += __two_step; |
2690 | } |
2691 | __step_size = std::min(_Distance(__last - __first), __step_size); |
2692 | |
2693 | std::__move_merge(__first, __first + __step_size, |
2694 | __first + __step_size, __last, __result, __comp); |
2695 | } |
2696 | |
2697 | template<typename _RandomAccessIterator, typename _Distance, |
2698 | typename _Compare> |
2699 | _GLIBCXX20_CONSTEXPR |
2700 | void |
2701 | __chunk_insertion_sort(_RandomAccessIterator __first, |
2702 | _RandomAccessIterator __last, |
2703 | _Distance __chunk_size, _Compare __comp) |
2704 | { |
2705 | while (__last - __first >= __chunk_size) |
2706 | { |
2707 | std::__insertion_sort(__first, __first + __chunk_size, __comp); |
2708 | __first += __chunk_size; |
2709 | } |
2710 | std::__insertion_sort(__first, __last, __comp); |
2711 | } |
2712 | |
2713 | enum { _S_chunk_size = 7 }; |
2714 | |
2715 | template<typename _RandomAccessIterator, typename _Pointer, typename _Compare> |
2716 | void |
2717 | __merge_sort_with_buffer(_RandomAccessIterator __first, |
2718 | _RandomAccessIterator __last, |
2719 | _Pointer __buffer, _Compare __comp) |
2720 | { |
2721 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type |
2722 | _Distance; |
2723 | |
2724 | const _Distance __len = __last - __first; |
2725 | const _Pointer __buffer_last = __buffer + __len; |
2726 | |
2727 | _Distance __step_size = _S_chunk_size; |
2728 | std::__chunk_insertion_sort(__first, __last, __step_size, __comp); |
2729 | |
2730 | while (__step_size < __len) |
2731 | { |
2732 | std::__merge_sort_loop(__first, __last, __buffer, |
2733 | __step_size, __comp); |
2734 | __step_size *= 2; |
2735 | std::__merge_sort_loop(__buffer, __buffer_last, __first, |
2736 | __step_size, __comp); |
2737 | __step_size *= 2; |
2738 | } |
2739 | } |
2740 | |
2741 | template<typename _RandomAccessIterator, typename _Pointer, |
2742 | typename _Distance, typename _Compare> |
2743 | void |
2744 | __stable_sort_adaptive(_RandomAccessIterator __first, |
2745 | _RandomAccessIterator __last, |
2746 | _Pointer __buffer, _Distance __buffer_size, |
2747 | _Compare __comp) |
2748 | { |
2749 | const _Distance __len = (__last - __first + 1) / 2; |
2750 | const _RandomAccessIterator __middle = __first + __len; |
2751 | if (__len > __buffer_size) |
2752 | { |
2753 | std::__stable_sort_adaptive(__first, __middle, __buffer, |
2754 | __buffer_size, __comp); |
2755 | std::__stable_sort_adaptive(__middle, __last, __buffer, |
2756 | __buffer_size, __comp); |
2757 | } |
2758 | else |
2759 | { |
2760 | std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp); |
2761 | std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp); |
2762 | } |
2763 | std::__merge_adaptive(__first, __middle, __last, |
2764 | _Distance(__middle - __first), |
2765 | _Distance(__last - __middle), |
2766 | __buffer, __buffer_size, |
2767 | __comp); |
2768 | } |
2769 | |
2770 | |
2771 | template<typename _RandomAccessIterator, typename _Compare> |
2772 | void |
2773 | __inplace_stable_sort(_RandomAccessIterator __first, |
2774 | _RandomAccessIterator __last, _Compare __comp) |
2775 | { |
2776 | if (__last - __first < 15) |
2777 | { |
2778 | std::__insertion_sort(__first, __last, __comp); |
2779 | return; |
2780 | } |
2781 | _RandomAccessIterator __middle = __first + (__last - __first) / 2; |
2782 | std::__inplace_stable_sort(__first, __middle, __comp); |
2783 | std::__inplace_stable_sort(__middle, __last, __comp); |
2784 | std::__merge_without_buffer(__first, __middle, __last, |
2785 | __middle - __first, |
2786 | __last - __middle, |
2787 | __comp); |
2788 | } |
2789 | |
2790 | |
2791 | |
2792 | |
2793 | |
2794 | |
2795 | |
2796 | |
2797 | template<typename _InputIterator1, typename _InputIterator2, |
2798 | typename _Compare> |
2799 | _GLIBCXX20_CONSTEXPR |
2800 | bool |
2801 | __includes(_InputIterator1 __first1, _InputIterator1 __last1, |
2802 | _InputIterator2 __first2, _InputIterator2 __last2, |
2803 | _Compare __comp) |
2804 | { |
2805 | while (__first1 != __last1 && __first2 != __last2) |
2806 | if (__comp(__first2, __first1)) |
2807 | return false; |
2808 | else if (__comp(__first1, __first2)) |
2809 | ++__first1; |
2810 | else |
2811 | { |
2812 | ++__first1; |
2813 | ++__first2; |
2814 | } |
2815 | |
2816 | return __first2 == __last2; |
2817 | } |
2818 | |
2819 | |
2820 | |
2821 | |
2822 | |
2823 | |
2824 | |
2825 | |
2826 | |
2827 | |
2828 | |
2829 | |
2830 | |
2831 | |
2832 | |
2833 | |
2834 | |
2835 | |
2836 | |
2837 | template<typename _InputIterator1, typename _InputIterator2> |
2838 | _GLIBCXX20_CONSTEXPR |
2839 | inline bool |
2840 | includes(_InputIterator1 __first1, _InputIterator1 __last1, |
2841 | _InputIterator2 __first2, _InputIterator2 __last2) |
2842 | { |
2843 | |
2844 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
2845 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
2846 | __glibcxx_function_requires(_LessThanOpConcept< |
2847 | typename iterator_traits<_InputIterator1>::value_type, |
2848 | typename iterator_traits<_InputIterator2>::value_type>) |
2849 | __glibcxx_function_requires(_LessThanOpConcept< |
2850 | typename iterator_traits<_InputIterator2>::value_type, |
2851 | typename iterator_traits<_InputIterator1>::value_type>) |
2852 | __glibcxx_requires_sorted_set(__first1, __last1, __first2); |
2853 | __glibcxx_requires_sorted_set(__first2, __last2, __first1); |
2854 | __glibcxx_requires_irreflexive2(__first1, __last1); |
2855 | __glibcxx_requires_irreflexive2(__first2, __last2); |
2856 | |
2857 | return std::__includes(__first1, __last1, __first2, __last2, |
2858 | __gnu_cxx::__ops::__iter_less_iter()); |
2859 | } |
2860 | |
2861 | |
2862 | |
2863 | |
2864 | |
2865 | |
2866 | |
2867 | |
2868 | |
2869 | |
2870 | |
2871 | |
2872 | |
2873 | |
2874 | |
2875 | |
2876 | |
2877 | |
2878 | |
2879 | |
2880 | |
2881 | |
2882 | template<typename _InputIterator1, typename _InputIterator2, |
2883 | typename _Compare> |
2884 | _GLIBCXX20_CONSTEXPR |
2885 | inline bool |
2886 | includes(_InputIterator1 __first1, _InputIterator1 __last1, |
2887 | _InputIterator2 __first2, _InputIterator2 __last2, |
2888 | _Compare __comp) |
2889 | { |
2890 | |
2891 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
2892 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
2893 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2894 | typename iterator_traits<_InputIterator1>::value_type, |
2895 | typename iterator_traits<_InputIterator2>::value_type>) |
2896 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
2897 | typename iterator_traits<_InputIterator2>::value_type, |
2898 | typename iterator_traits<_InputIterator1>::value_type>) |
2899 | __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); |
2900 | __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); |
2901 | __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); |
2902 | __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); |
2903 | |
2904 | return std::__includes(__first1, __last1, __first2, __last2, |
2905 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
2906 | } |
2907 | |
2908 | |
2909 | |
2910 | |
2911 | |
2912 | |
2913 | |
2914 | |
2915 | |
2916 | |
2917 | |
2918 | template<typename _BidirectionalIterator, typename _Compare> |
2919 | _GLIBCXX20_CONSTEXPR |
2920 | bool |
2921 | __next_permutation(_BidirectionalIterator __first, |
2922 | _BidirectionalIterator __last, _Compare __comp) |
2923 | { |
2924 | if (__first == __last) |
2925 | return false; |
2926 | _BidirectionalIterator __i = __first; |
2927 | ++__i; |
2928 | if (__i == __last) |
2929 | return false; |
2930 | __i = __last; |
2931 | --__i; |
2932 | |
2933 | for(;;) |
2934 | { |
2935 | _BidirectionalIterator __ii = __i; |
2936 | --__i; |
2937 | if (__comp(__i, __ii)) |
2938 | { |
2939 | _BidirectionalIterator __j = __last; |
2940 | while (!__comp(__i, --__j)) |
2941 | {} |
2942 | std::iter_swap(__i, __j); |
2943 | std::__reverse(__ii, __last, |
2944 | std::__iterator_category(__first)); |
2945 | return true; |
2946 | } |
2947 | if (__i == __first) |
2948 | { |
2949 | std::__reverse(__first, __last, |
2950 | std::__iterator_category(__first)); |
2951 | return false; |
2952 | } |
2953 | } |
2954 | } |
2955 | |
2956 | |
2957 | |
2958 | |
2959 | |
2960 | |
2961 | |
2962 | |
2963 | |
2964 | |
2965 | |
2966 | |
2967 | |
2968 | template<typename _BidirectionalIterator> |
2969 | _GLIBCXX20_CONSTEXPR |
2970 | inline bool |
2971 | next_permutation(_BidirectionalIterator __first, |
2972 | _BidirectionalIterator __last) |
2973 | { |
2974 | |
2975 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
2976 | _BidirectionalIterator>) |
2977 | __glibcxx_function_requires(_LessThanComparableConcept< |
2978 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
2979 | __glibcxx_requires_valid_range(__first, __last); |
2980 | __glibcxx_requires_irreflexive(__first, __last); |
2981 | |
2982 | return std::__next_permutation |
2983 | (__first, __last, __gnu_cxx::__ops::__iter_less_iter()); |
2984 | } |
2985 | |
2986 | |
2987 | |
2988 | |
2989 | |
2990 | |
2991 | |
2992 | |
2993 | |
2994 | |
2995 | |
2996 | |
2997 | |
2998 | |
2999 | |
3000 | |
3001 | template<typename _BidirectionalIterator, typename _Compare> |
3002 | _GLIBCXX20_CONSTEXPR |
3003 | inline bool |
3004 | next_permutation(_BidirectionalIterator __first, |
3005 | _BidirectionalIterator __last, _Compare __comp) |
3006 | { |
3007 | |
3008 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
3009 | _BidirectionalIterator>) |
3010 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
3011 | typename iterator_traits<_BidirectionalIterator>::value_type, |
3012 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
3013 | __glibcxx_requires_valid_range(__first, __last); |
3014 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
3015 | |
3016 | return std::__next_permutation |
3017 | (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
3018 | } |
3019 | |
3020 | template<typename _BidirectionalIterator, typename _Compare> |
3021 | _GLIBCXX20_CONSTEXPR |
3022 | bool |
3023 | __prev_permutation(_BidirectionalIterator __first, |
3024 | _BidirectionalIterator __last, _Compare __comp) |
3025 | { |
3026 | if (__first == __last) |
3027 | return false; |
3028 | _BidirectionalIterator __i = __first; |
3029 | ++__i; |
3030 | if (__i == __last) |
3031 | return false; |
3032 | __i = __last; |
3033 | --__i; |
3034 | |
3035 | for(;;) |
3036 | { |
3037 | _BidirectionalIterator __ii = __i; |
3038 | --__i; |
3039 | if (__comp(__ii, __i)) |
3040 | { |
3041 | _BidirectionalIterator __j = __last; |
3042 | while (!__comp(--__j, __i)) |
3043 | {} |
3044 | std::iter_swap(__i, __j); |
3045 | std::__reverse(__ii, __last, |
3046 | std::__iterator_category(__first)); |
3047 | return true; |
3048 | } |
3049 | if (__i == __first) |
3050 | { |
3051 | std::__reverse(__first, __last, |
3052 | std::__iterator_category(__first)); |
3053 | return false; |
3054 | } |
3055 | } |
3056 | } |
3057 | |
3058 | |
3059 | |
3060 | |
3061 | |
3062 | |
3063 | |
3064 | |
3065 | |
3066 | |
3067 | |
3068 | |
3069 | |
3070 | |
3071 | template<typename _BidirectionalIterator> |
3072 | _GLIBCXX20_CONSTEXPR |
3073 | inline bool |
3074 | prev_permutation(_BidirectionalIterator __first, |
3075 | _BidirectionalIterator __last) |
3076 | { |
3077 | |
3078 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
3079 | _BidirectionalIterator>) |
3080 | __glibcxx_function_requires(_LessThanComparableConcept< |
3081 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
3082 | __glibcxx_requires_valid_range(__first, __last); |
3083 | __glibcxx_requires_irreflexive(__first, __last); |
3084 | |
3085 | return std::__prev_permutation(__first, __last, |
3086 | __gnu_cxx::__ops::__iter_less_iter()); |
3087 | } |
3088 | |
3089 | |
3090 | |
3091 | |
3092 | |
3093 | |
3094 | |
3095 | |
3096 | |
3097 | |
3098 | |
3099 | |
3100 | |
3101 | |
3102 | |
3103 | |
3104 | template<typename _BidirectionalIterator, typename _Compare> |
3105 | _GLIBCXX20_CONSTEXPR |
3106 | inline bool |
3107 | prev_permutation(_BidirectionalIterator __first, |
3108 | _BidirectionalIterator __last, _Compare __comp) |
3109 | { |
3110 | |
3111 | __glibcxx_function_requires(_BidirectionalIteratorConcept< |
3112 | _BidirectionalIterator>) |
3113 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
3114 | typename iterator_traits<_BidirectionalIterator>::value_type, |
3115 | typename iterator_traits<_BidirectionalIterator>::value_type>) |
3116 | __glibcxx_requires_valid_range(__first, __last); |
3117 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
3118 | |
3119 | return std::__prev_permutation(__first, __last, |
3120 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
3121 | } |
3122 | |
3123 | |
3124 | |
3125 | |
3126 | template<typename _InputIterator, typename _OutputIterator, |
3127 | typename _Predicate, typename _Tp> |
3128 | _GLIBCXX20_CONSTEXPR |
3129 | _OutputIterator |
3130 | __replace_copy_if(_InputIterator __first, _InputIterator __last, |
3131 | _OutputIterator __result, |
3132 | _Predicate __pred, const _Tp& __new_value) |
3133 | { |
3134 | for (; __first != __last; ++__first, (void)++__result) |
3135 | if (__pred(__first)) |
3136 | *__result = __new_value; |
3137 | else |
3138 | *__result = *__first; |
3139 | return __result; |
3140 | } |
3141 | |
3142 | |
3143 | |
3144 | |
3145 | |
3146 | |
3147 | |
3148 | |
3149 | |
3150 | |
3151 | |
3152 | |
3153 | |
3154 | |
3155 | |
3156 | template<typename _InputIterator, typename _OutputIterator, typename _Tp> |
3157 | _GLIBCXX20_CONSTEXPR |
3158 | inline _OutputIterator |
3159 | replace_copy(_InputIterator __first, _InputIterator __last, |
3160 | _OutputIterator __result, |
3161 | const _Tp& __old_value, const _Tp& __new_value) |
3162 | { |
3163 | |
3164 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3165 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
3166 | typename iterator_traits<_InputIterator>::value_type>) |
3167 | __glibcxx_function_requires(_EqualOpConcept< |
3168 | typename iterator_traits<_InputIterator>::value_type, _Tp>) |
3169 | __glibcxx_requires_valid_range(__first, __last); |
3170 | |
3171 | return std::__replace_copy_if(__first, __last, __result, |
3172 | __gnu_cxx::__ops::__iter_equals_val(__old_value), |
3173 | __new_value); |
3174 | } |
3175 | |
3176 | |
3177 | |
3178 | |
3179 | |
3180 | |
3181 | |
3182 | |
3183 | |
3184 | |
3185 | |
3186 | |
3187 | |
3188 | |
3189 | |
3190 | |
3191 | template<typename _InputIterator, typename _OutputIterator, |
3192 | typename _Predicate, typename _Tp> |
3193 | _GLIBCXX20_CONSTEXPR |
3194 | inline _OutputIterator |
3195 | replace_copy_if(_InputIterator __first, _InputIterator __last, |
3196 | _OutputIterator __result, |
3197 | _Predicate __pred, const _Tp& __new_value) |
3198 | { |
3199 | |
3200 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3201 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
3202 | typename iterator_traits<_InputIterator>::value_type>) |
3203 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
3204 | typename iterator_traits<_InputIterator>::value_type>) |
3205 | __glibcxx_requires_valid_range(__first, __last); |
3206 | |
3207 | return std::__replace_copy_if(__first, __last, __result, |
3208 | __gnu_cxx::__ops::__pred_iter(__pred), |
3209 | __new_value); |
3210 | } |
3211 | |
3212 | #if __cplusplus >= 201103L |
3213 | |
3214 | |
3215 | |
3216 | |
3217 | |
3218 | |
3219 | |
3220 | template<typename _ForwardIterator> |
3221 | _GLIBCXX20_CONSTEXPR |
3222 | inline bool |
3223 | is_sorted(_ForwardIterator __first, _ForwardIterator __last) |
3224 | { return std::is_sorted_until(__first, __last) == __last; } |
3225 | |
3226 | |
3227 | |
3228 | |
3229 | |
3230 | |
3231 | |
3232 | |
3233 | |
3234 | |
3235 | template<typename _ForwardIterator, typename _Compare> |
3236 | _GLIBCXX20_CONSTEXPR |
3237 | inline bool |
3238 | is_sorted(_ForwardIterator __first, _ForwardIterator __last, |
3239 | _Compare __comp) |
3240 | { return std::is_sorted_until(__first, __last, __comp) == __last; } |
3241 | |
3242 | template<typename _ForwardIterator, typename _Compare> |
3243 | _GLIBCXX20_CONSTEXPR |
3244 | _ForwardIterator |
3245 | __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, |
3246 | _Compare __comp) |
3247 | { |
3248 | if (__first == __last) |
3249 | return __last; |
3250 | |
3251 | _ForwardIterator __next = __first; |
3252 | for (++__next; __next != __last; __first = __next, (void)++__next) |
3253 | if (__comp(__next, __first)) |
3254 | return __next; |
3255 | return __next; |
3256 | } |
3257 | |
3258 | |
3259 | |
3260 | |
3261 | |
3262 | |
3263 | |
3264 | |
3265 | |
3266 | template<typename _ForwardIterator> |
3267 | _GLIBCXX20_CONSTEXPR |
3268 | inline _ForwardIterator |
3269 | is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) |
3270 | { |
3271 | |
3272 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
3273 | __glibcxx_function_requires(_LessThanComparableConcept< |
3274 | typename iterator_traits<_ForwardIterator>::value_type>) |
3275 | __glibcxx_requires_valid_range(__first, __last); |
3276 | __glibcxx_requires_irreflexive(__first, __last); |
3277 | |
3278 | return std::__is_sorted_until(__first, __last, |
3279 | __gnu_cxx::__ops::__iter_less_iter()); |
3280 | } |
3281 | |
3282 | |
3283 | |
3284 | |
3285 | |
3286 | |
3287 | |
3288 | |
3289 | |
3290 | |
3291 | template<typename _ForwardIterator, typename _Compare> |
3292 | _GLIBCXX20_CONSTEXPR |
3293 | inline _ForwardIterator |
3294 | is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, |
3295 | _Compare __comp) |
3296 | { |
3297 | |
3298 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
3299 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
3300 | typename iterator_traits<_ForwardIterator>::value_type, |
3301 | typename iterator_traits<_ForwardIterator>::value_type>) |
3302 | __glibcxx_requires_valid_range(__first, __last); |
3303 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
3304 | |
3305 | return std::__is_sorted_until(__first, __last, |
3306 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
3307 | } |
3308 | |
3309 | |
3310 | |
3311 | |
3312 | |
3313 | |
3314 | |
3315 | |
3316 | |
3317 | template<typename _Tp> |
3318 | _GLIBCXX14_CONSTEXPR |
3319 | inline pair<const _Tp&, const _Tp&> |
3320 | minmax(const _Tp& __a, const _Tp& __b) |
3321 | { |
3322 | |
3323 | __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) |
3324 | |
3325 | return __b < __a ? pair<const _Tp&, const _Tp&>(__b, __a) |
3326 | : pair<const _Tp&, const _Tp&>(__a, __b); |
3327 | } |
3328 | |
3329 | |
3330 | |
3331 | |
3332 | |
3333 | |
3334 | |
3335 | |
3336 | |
3337 | |
3338 | template<typename _Tp, typename _Compare> |
3339 | _GLIBCXX14_CONSTEXPR |
3340 | inline pair<const _Tp&, const _Tp&> |
3341 | minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) |
3342 | { |
3343 | return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) |
3344 | : pair<const _Tp&, const _Tp&>(__a, __b); |
3345 | } |
3346 | |
3347 | template<typename _ForwardIterator, typename _Compare> |
3348 | _GLIBCXX14_CONSTEXPR |
3349 | pair<_ForwardIterator, _ForwardIterator> |
3350 | __minmax_element(_ForwardIterator __first, _ForwardIterator __last, |
3351 | _Compare __comp) |
3352 | { |
3353 | _ForwardIterator __next = __first; |
3354 | if (__first == __last |
3355 | || ++__next == __last) |
3356 | return std::make_pair(__first, __first); |
3357 | |
3358 | _ForwardIterator __min{}, __max{}; |
3359 | if (__comp(__next, __first)) |
3360 | { |
3361 | __min = __next; |
3362 | __max = __first; |
3363 | } |
3364 | else |
3365 | { |
3366 | __min = __first; |
3367 | __max = __next; |
3368 | } |
3369 | |
3370 | __first = __next; |
3371 | ++__first; |
3372 | |
3373 | while (__first != __last) |
3374 | { |
3375 | __next = __first; |
3376 | if (++__next == __last) |
3377 | { |
3378 | if (__comp(__first, __min)) |
3379 | __min = __first; |
3380 | else if (!__comp(__first, __max)) |
3381 | __max = __first; |
3382 | break; |
3383 | } |
3384 | |
3385 | if (__comp(__next, __first)) |
3386 | { |
3387 | if (__comp(__next, __min)) |
3388 | __min = __next; |
3389 | if (!__comp(__first, __max)) |
3390 | __max = __first; |
3391 | } |
3392 | else |
3393 | { |
3394 | if (__comp(__first, __min)) |
3395 | __min = __first; |
3396 | if (!__comp(__next, __max)) |
3397 | __max = __next; |
3398 | } |
3399 | |
3400 | __first = __next; |
3401 | ++__first; |
3402 | } |
3403 | |
3404 | return std::make_pair(__min, __max); |
3405 | } |
3406 | |
3407 | |
3408 | |
3409 | |
3410 | |
3411 | |
3412 | |
3413 | |
3414 | |
3415 | |
3416 | |
3417 | |
3418 | template<typename _ForwardIterator> |
3419 | _GLIBCXX14_CONSTEXPR |
3420 | inline pair<_ForwardIterator, _ForwardIterator> |
3421 | minmax_element(_ForwardIterator __first, _ForwardIterator __last) |
3422 | { |
3423 | |
3424 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
3425 | __glibcxx_function_requires(_LessThanComparableConcept< |
3426 | typename iterator_traits<_ForwardIterator>::value_type>) |
3427 | __glibcxx_requires_valid_range(__first, __last); |
3428 | __glibcxx_requires_irreflexive(__first, __last); |
3429 | |
3430 | return std::__minmax_element(__first, __last, |
3431 | __gnu_cxx::__ops::__iter_less_iter()); |
3432 | } |
3433 | |
3434 | |
3435 | |
3436 | |
3437 | |
3438 | |
3439 | |
3440 | |
3441 | |
3442 | |
3443 | |
3444 | |
3445 | |
3446 | template<typename _ForwardIterator, typename _Compare> |
3447 | _GLIBCXX14_CONSTEXPR |
3448 | inline pair<_ForwardIterator, _ForwardIterator> |
3449 | minmax_element(_ForwardIterator __first, _ForwardIterator __last, |
3450 | _Compare __comp) |
3451 | { |
3452 | |
3453 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
3454 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
3455 | typename iterator_traits<_ForwardIterator>::value_type, |
3456 | typename iterator_traits<_ForwardIterator>::value_type>) |
3457 | __glibcxx_requires_valid_range(__first, __last); |
3458 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
3459 | |
3460 | return std::__minmax_element(__first, __last, |
3461 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
3462 | } |
3463 | |
3464 | |
3465 | template<typename _Tp> |
3466 | _GLIBCXX14_CONSTEXPR |
3467 | inline _Tp |
3468 | min(initializer_list<_Tp> __l) |
3469 | { return *std::min_element(__l.begin(), __l.end()); } |
3470 | |
3471 | template<typename _Tp, typename _Compare> |
3472 | _GLIBCXX14_CONSTEXPR |
3473 | inline _Tp |
3474 | min(initializer_list<_Tp> __l, _Compare __comp) |
3475 | { return *std::min_element(__l.begin(), __l.end(), __comp); } |
3476 | |
3477 | template<typename _Tp> |
3478 | _GLIBCXX14_CONSTEXPR |
3479 | inline _Tp |
3480 | max(initializer_list<_Tp> __l) |
3481 | { return *std::max_element(__l.begin(), __l.end()); } |
3482 | |
3483 | template<typename _Tp, typename _Compare> |
3484 | _GLIBCXX14_CONSTEXPR |
3485 | inline _Tp |
3486 | max(initializer_list<_Tp> __l, _Compare __comp) |
3487 | { return *std::max_element(__l.begin(), __l.end(), __comp); } |
3488 | |
3489 | template<typename _Tp> |
3490 | _GLIBCXX14_CONSTEXPR |
3491 | inline pair<_Tp, _Tp> |
3492 | minmax(initializer_list<_Tp> __l) |
3493 | { |
3494 | pair<const _Tp*, const _Tp*> __p = |
3495 | std::minmax_element(__l.begin(), __l.end()); |
3496 | return std::make_pair(*__p.first, *__p.second); |
3497 | } |
3498 | |
3499 | template<typename _Tp, typename _Compare> |
3500 | _GLIBCXX14_CONSTEXPR |
3501 | inline pair<_Tp, _Tp> |
3502 | minmax(initializer_list<_Tp> __l, _Compare __comp) |
3503 | { |
3504 | pair<const _Tp*, const _Tp*> __p = |
3505 | std::minmax_element(__l.begin(), __l.end(), __comp); |
3506 | return std::make_pair(*__p.first, *__p.second); |
3507 | } |
3508 | |
3509 | |
3510 | |
3511 | |
3512 | |
3513 | |
3514 | |
3515 | |
3516 | |
3517 | |
3518 | |
3519 | |
3520 | |
3521 | |
3522 | |
3523 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
3524 | typename _BinaryPredicate> |
3525 | _GLIBCXX20_CONSTEXPR |
3526 | inline bool |
3527 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
3528 | _ForwardIterator2 __first2, _BinaryPredicate __pred) |
3529 | { |
3530 | |
3531 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) |
3532 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) |
3533 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
3534 | typename iterator_traits<_ForwardIterator1>::value_type, |
3535 | typename iterator_traits<_ForwardIterator2>::value_type>) |
3536 | __glibcxx_requires_valid_range(__first1, __last1); |
3537 | |
3538 | return std::__is_permutation(__first1, __last1, __first2, |
3539 | __gnu_cxx::__ops::__iter_comp_iter(__pred)); |
3540 | } |
3541 | |
3542 | #if __cplusplus > 201103L |
3543 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
3544 | typename _BinaryPredicate> |
3545 | _GLIBCXX20_CONSTEXPR |
3546 | bool |
3547 | __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
3548 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, |
3549 | _BinaryPredicate __pred) |
3550 | { |
3551 | using _Cat1 |
3552 | = typename iterator_traits<_ForwardIterator1>::iterator_category; |
3553 | using _Cat2 |
3554 | = typename iterator_traits<_ForwardIterator2>::iterator_category; |
3555 | using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; |
3556 | using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; |
3557 | constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA(); |
3558 | if (__ra_iters) |
3559 | { |
3560 | auto __d1 = std::distance(__first1, __last1); |
3561 | auto __d2 = std::distance(__first2, __last2); |
3562 | if (__d1 != __d2) |
3563 | return false; |
3564 | } |
3565 | |
3566 | |
3567 | |
3568 | for (; __first1 != __last1 && __first2 != __last2; |
3569 | ++__first1, (void)++__first2) |
3570 | if (!__pred(__first1, __first2)) |
3571 | break; |
3572 | |
3573 | if (__ra_iters) |
3574 | { |
3575 | if (__first1 == __last1) |
3576 | return true; |
3577 | } |
3578 | else |
3579 | { |
3580 | auto __d1 = std::distance(__first1, __last1); |
3581 | auto __d2 = std::distance(__first2, __last2); |
3582 | if (__d1 == 0 && __d2 == 0) |
3583 | return true; |
3584 | if (__d1 != __d2) |
3585 | return false; |
3586 | } |
3587 | |
3588 | for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) |
3589 | { |
3590 | if (__scan != std::__find_if(__first1, __scan, |
3591 | __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) |
3592 | continue; |
3593 | |
3594 | auto __matches = std::__count_if(__first2, __last2, |
3595 | __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); |
3596 | if (0 == __matches |
3597 | || std::__count_if(__scan, __last1, |
3598 | __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) |
3599 | != __matches) |
3600 | return false; |
3601 | } |
3602 | return true; |
3603 | } |
3604 | |
3605 | |
3606 | |
3607 | |
3608 | |
3609 | |
3610 | |
3611 | |
3612 | |
3613 | |
3614 | |
3615 | |
3616 | |
3617 | |
3618 | template<typename _ForwardIterator1, typename _ForwardIterator2> |
3619 | _GLIBCXX20_CONSTEXPR |
3620 | inline bool |
3621 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
3622 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) |
3623 | { |
3624 | __glibcxx_requires_valid_range(__first1, __last1); |
3625 | __glibcxx_requires_valid_range(__first2, __last2); |
3626 | |
3627 | return |
3628 | std::__is_permutation(__first1, __last1, __first2, __last2, |
3629 | __gnu_cxx::__ops::__iter_equal_to_iter()); |
3630 | } |
3631 | |
3632 | |
3633 | |
3634 | |
3635 | |
3636 | |
3637 | |
3638 | |
3639 | |
3640 | |
3641 | |
3642 | |
3643 | |
3644 | |
3645 | |
3646 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
3647 | typename _BinaryPredicate> |
3648 | _GLIBCXX20_CONSTEXPR |
3649 | inline bool |
3650 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
3651 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, |
3652 | _BinaryPredicate __pred) |
3653 | { |
3654 | __glibcxx_requires_valid_range(__first1, __last1); |
3655 | __glibcxx_requires_valid_range(__first2, __last2); |
3656 | |
3657 | return std::__is_permutation(__first1, __last1, __first2, __last2, |
3658 | __gnu_cxx::__ops::__iter_comp_iter(__pred)); |
3659 | } |
3660 | |
3661 | #if __cplusplus > 201402L |
3662 | |
3663 | #define __cpp_lib_clamp 201603 |
3664 | |
3665 | |
3666 | |
3667 | |
3668 | |
3669 | |
3670 | |
3671 | |
3672 | |
3673 | template<typename _Tp> |
3674 | constexpr const _Tp& |
3675 | clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) |
3676 | { |
3677 | __glibcxx_assert(!(__hi < __lo)); |
3678 | return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val; |
3679 | } |
3680 | |
3681 | |
3682 | |
3683 | |
3684 | |
3685 | |
3686 | |
3687 | |
3688 | |
3689 | |
3690 | |
3691 | template<typename _Tp, typename _Compare> |
3692 | constexpr const _Tp& |
3693 | clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp) |
3694 | { |
3695 | __glibcxx_assert(!__comp(__hi, __lo)); |
3696 | return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val; |
3697 | } |
3698 | #endif // C++17 |
3699 | #endif // C++14 |
3700 | |
3701 | #ifdef _GLIBCXX_USE_C99_STDINT_TR1 |
3702 | |
3703 | |
3704 | |
3705 | |
3706 | |
3707 | |
3708 | |
3709 | |
3710 | |
3711 | |
3712 | |
3713 | |
3714 | |
3715 | |
3716 | |
3717 | |
3718 | |
3719 | |
3720 | |
3721 | |
3722 | |
3723 | template<typename _IntType, typename _UniformRandomBitGenerator> |
3724 | pair<_IntType, _IntType> |
3725 | __gen_two_uniform_ints(_IntType __b0, _IntType __b1, |
3726 | _UniformRandomBitGenerator&& __g) |
3727 | { |
3728 | _IntType __x |
3729 | = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g); |
3730 | return std::make_pair(__x / __b1, __x % __b1); |
3731 | } |
3732 | |
3733 | |
3734 | |
3735 | |
3736 | |
3737 | |
3738 | |
3739 | |
3740 | |
3741 | |
3742 | |
3743 | |
3744 | |
3745 | template<typename _RandomAccessIterator, |
3746 | typename _UniformRandomNumberGenerator> |
3747 | void |
3748 | shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, |
3749 | _UniformRandomNumberGenerator&& __g) |
3750 | { |
3751 | |
3752 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
3753 | _RandomAccessIterator>) |
3754 | __glibcxx_requires_valid_range(__first, __last); |
3755 | |
3756 | if (__first == __last) |
3757 | return; |
3758 | |
3759 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type |
3760 | _DistanceType; |
3761 | |
3762 | typedef typename std::make_unsigned<_DistanceType>::type __ud_type; |
3763 | typedef typename std::uniform_int_distribution<__ud_type> __distr_type; |
3764 | typedef typename __distr_type::param_type __p_type; |
3765 | |
3766 | typedef typename remove_reference<_UniformRandomNumberGenerator>::type |
3767 | _Gen; |
3768 | typedef typename common_type<typename _Gen::result_type, __ud_type>::type |
3769 | __uc_type; |
3770 | |
3771 | const __uc_type __urngrange = __g.max() - __g.min(); |
3772 | const __uc_type __urange = __uc_type(__last - __first); |
3773 | |
3774 | if (__urngrange / __urange >= __urange) |
3775 | |
3776 | { |
3777 | _RandomAccessIterator __i = __first + 1; |
3778 | |
3779 | |
3780 | |
3781 | |
3782 | |
3783 | if ((__urange % 2) == 0) |
3784 | { |
3785 | __distr_type __d{0, 1}; |
3786 | std::iter_swap(__i++, __first + __d(__g)); |
3787 | } |
3788 | |
3789 | |
3790 | |
3791 | |
3792 | |
3793 | while (__i != __last) |
3794 | { |
3795 | const __uc_type __swap_range = __uc_type(__i - __first) + 1; |
3796 | |
3797 | const pair<__uc_type, __uc_type> __pospos = |
3798 | __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); |
3799 | |
3800 | std::iter_swap(__i++, __first + __pospos.first); |
3801 | std::iter_swap(__i++, __first + __pospos.second); |
3802 | } |
3803 | |
3804 | return; |
3805 | } |
3806 | |
3807 | __distr_type __d; |
3808 | |
3809 | for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) |
3810 | std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first))); |
3811 | } |
3812 | #endif |
3813 | |
3814 | #endif // C++11 |
3815 | |
3816 | _GLIBCXX_BEGIN_NAMESPACE_ALGO |
3817 | |
3818 | |
3819 | |
3820 | |
3821 | |
3822 | |
3823 | |
3824 | |
3825 | |
3826 | |
3827 | |
3828 | |
3829 | |
3830 | template<typename _InputIterator, typename _Function> |
3831 | _GLIBCXX20_CONSTEXPR |
3832 | _Function |
3833 | for_each(_InputIterator __first, _InputIterator __last, _Function __f) |
3834 | { |
3835 | |
3836 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3837 | __glibcxx_requires_valid_range(__first, __last); |
3838 | for (; __first != __last; ++__first) |
3839 | __f(*__first); |
3840 | return __f; |
3841 | } |
3842 | |
3843 | #if __cplusplus >= 201703L |
3844 | |
3845 | |
3846 | |
3847 | |
3848 | |
3849 | |
3850 | |
3851 | |
3852 | |
3853 | |
3854 | |
3855 | |
3856 | template<typename _InputIterator, typename _Size, typename _Function> |
3857 | _InputIterator |
3858 | for_each_n(_InputIterator __first, _Size __n, _Function __f) |
3859 | { |
3860 | auto __n2 = std::__size_to_integer(__n); |
3861 | using _Cat = typename iterator_traits<_InputIterator>::iterator_category; |
3862 | if constexpr (is_base_of_v<random_access_iterator_tag, _Cat>) |
3863 | { |
3864 | if (__n2 <= 0) |
3865 | return __first; |
3866 | auto __last = __first + __n2; |
3867 | std::for_each(__first, __last, std::move(__f)); |
3868 | return __last; |
3869 | } |
3870 | else |
3871 | { |
3872 | while (__n2-->0) |
3873 | { |
3874 | __f(*__first); |
3875 | ++__first; |
3876 | } |
3877 | return __first; |
3878 | } |
3879 | } |
3880 | #endif // C++17 |
3881 | |
3882 | |
3883 | |
3884 | |
3885 | |
3886 | |
3887 | |
3888 | |
3889 | |
3890 | |
3891 | template<typename _InputIterator, typename _Tp> |
3892 | _GLIBCXX20_CONSTEXPR |
3893 | inline _InputIterator |
3894 | find(_InputIterator __first, _InputIterator __last, |
3895 | const _Tp& __val) |
3896 | { |
3897 | |
3898 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3899 | __glibcxx_function_requires(_EqualOpConcept< |
3900 | typename iterator_traits<_InputIterator>::value_type, _Tp>) |
3901 | __glibcxx_requires_valid_range(__first, __last); |
3902 | return std::__find_if(__first, __last, |
3903 | __gnu_cxx::__ops::__iter_equals_val(__val)); |
3904 | } |
3905 | |
3906 | |
3907 | |
3908 | |
3909 | |
3910 | |
3911 | |
3912 | |
3913 | |
3914 | |
3915 | |
3916 | template<typename _InputIterator, typename _Predicate> |
3917 | _GLIBCXX20_CONSTEXPR |
3918 | inline _InputIterator |
3919 | find_if(_InputIterator __first, _InputIterator __last, |
3920 | _Predicate __pred) |
3921 | { |
3922 | |
3923 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3924 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
3925 | typename iterator_traits<_InputIterator>::value_type>) |
3926 | __glibcxx_requires_valid_range(__first, __last); |
3927 | |
3928 | return std::__find_if(__first, __last, |
3929 | __gnu_cxx::__ops::__pred_iter(__pred)); |
3930 | } |
3931 | |
3932 | |
3933 | |
3934 | |
3935 | |
3936 | |
3937 | |
3938 | |
3939 | |
3940 | |
3941 | |
3942 | |
3943 | |
3944 | |
3945 | |
3946 | |
3947 | |
3948 | template<typename _InputIterator, typename _ForwardIterator> |
3949 | _GLIBCXX20_CONSTEXPR |
3950 | _InputIterator |
3951 | find_first_of(_InputIterator __first1, _InputIterator __last1, |
3952 | _ForwardIterator __first2, _ForwardIterator __last2) |
3953 | { |
3954 | |
3955 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3956 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
3957 | __glibcxx_function_requires(_EqualOpConcept< |
3958 | typename iterator_traits<_InputIterator>::value_type, |
3959 | typename iterator_traits<_ForwardIterator>::value_type>) |
3960 | __glibcxx_requires_valid_range(__first1, __last1); |
3961 | __glibcxx_requires_valid_range(__first2, __last2); |
3962 | |
3963 | for (; __first1 != __last1; ++__first1) |
3964 | for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) |
3965 | if (*__first1 == *__iter) |
3966 | return __first1; |
3967 | return __last1; |
3968 | } |
3969 | |
3970 | |
3971 | |
3972 | |
3973 | |
3974 | |
3975 | |
3976 | |
3977 | |
3978 | |
3979 | |
3980 | |
3981 | |
3982 | |
3983 | |
3984 | |
3985 | |
3986 | |
3987 | |
3988 | |
3989 | template<typename _InputIterator, typename _ForwardIterator, |
3990 | typename _BinaryPredicate> |
3991 | _GLIBCXX20_CONSTEXPR |
3992 | _InputIterator |
3993 | find_first_of(_InputIterator __first1, _InputIterator __last1, |
3994 | _ForwardIterator __first2, _ForwardIterator __last2, |
3995 | _BinaryPredicate __comp) |
3996 | { |
3997 | |
3998 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
3999 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
4000 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
4001 | typename iterator_traits<_InputIterator>::value_type, |
4002 | typename iterator_traits<_ForwardIterator>::value_type>) |
4003 | __glibcxx_requires_valid_range(__first1, __last1); |
4004 | __glibcxx_requires_valid_range(__first2, __last2); |
4005 | |
4006 | for (; __first1 != __last1; ++__first1) |
4007 | for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) |
4008 | if (__comp(*__first1, *__iter)) |
4009 | return __first1; |
4010 | return __last1; |
4011 | } |
4012 | |
4013 | |
4014 | |
4015 | |
4016 | |
4017 | |
4018 | |
4019 | |
4020 | |
4021 | |
4022 | template<typename _ForwardIterator> |
4023 | _GLIBCXX20_CONSTEXPR |
4024 | inline _ForwardIterator |
4025 | adjacent_find(_ForwardIterator __first, _ForwardIterator __last) |
4026 | { |
4027 | |
4028 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
4029 | __glibcxx_function_requires(_EqualityComparableConcept< |
4030 | typename iterator_traits<_ForwardIterator>::value_type>) |
4031 | __glibcxx_requires_valid_range(__first, __last); |
4032 | |
4033 | return std::__adjacent_find(__first, __last, |
4034 | __gnu_cxx::__ops::__iter_equal_to_iter()); |
4035 | } |
4036 | |
4037 | |
4038 | |
4039 | |
4040 | |
4041 | |
4042 | |
4043 | |
4044 | |
4045 | |
4046 | |
4047 | |
4048 | template<typename _ForwardIterator, typename _BinaryPredicate> |
4049 | _GLIBCXX20_CONSTEXPR |
4050 | inline _ForwardIterator |
4051 | adjacent_find(_ForwardIterator __first, _ForwardIterator __last, |
4052 | _BinaryPredicate __binary_pred) |
4053 | { |
4054 | |
4055 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
4056 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
4057 | typename iterator_traits<_ForwardIterator>::value_type, |
4058 | typename iterator_traits<_ForwardIterator>::value_type>) |
4059 | __glibcxx_requires_valid_range(__first, __last); |
4060 | |
4061 | return std::__adjacent_find(__first, __last, |
4062 | __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); |
4063 | } |
4064 | |
4065 | |
4066 | |
4067 | |
4068 | |
4069 | |
4070 | |
4071 | |
4072 | |
4073 | |
4074 | template<typename _InputIterator, typename _Tp> |
4075 | _GLIBCXX20_CONSTEXPR |
4076 | inline typename iterator_traits<_InputIterator>::difference_type |
4077 | count(_InputIterator __first, _InputIterator __last, const _Tp& __value) |
4078 | { |
4079 | |
4080 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
4081 | __glibcxx_function_requires(_EqualOpConcept< |
4082 | typename iterator_traits<_InputIterator>::value_type, _Tp>) |
4083 | __glibcxx_requires_valid_range(__first, __last); |
4084 | |
4085 | return std::__count_if(__first, __last, |
4086 | __gnu_cxx::__ops::__iter_equals_val(__value)); |
4087 | } |
4088 | |
4089 | |
4090 | |
4091 | |
4092 | |
4093 | |
4094 | |
4095 | |
4096 | |
4097 | |
4098 | template<typename _InputIterator, typename _Predicate> |
4099 | _GLIBCXX20_CONSTEXPR |
4100 | inline typename iterator_traits<_InputIterator>::difference_type |
4101 | count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) |
4102 | { |
4103 | |
4104 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
4105 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
4106 | typename iterator_traits<_InputIterator>::value_type>) |
4107 | __glibcxx_requires_valid_range(__first, __last); |
4108 | |
4109 | return std::__count_if(__first, __last, |
4110 | __gnu_cxx::__ops::__pred_iter(__pred)); |
4111 | } |
4112 | |
4113 | |
4114 | |
4115 | |
4116 | |
4117 | |
4118 | |
4119 | |
4120 | |
4121 | |
4122 | |
4123 | |
4124 | |
4125 | |
4126 | |
4127 | |
4128 | |
4129 | |
4130 | |
4131 | |
4132 | |
4133 | |
4134 | |
4135 | |
4136 | |
4137 | |
4138 | |
4139 | template<typename _ForwardIterator1, typename _ForwardIterator2> |
4140 | _GLIBCXX20_CONSTEXPR |
4141 | inline _ForwardIterator1 |
4142 | search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
4143 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) |
4144 | { |
4145 | |
4146 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) |
4147 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) |
4148 | __glibcxx_function_requires(_EqualOpConcept< |
4149 | typename iterator_traits<_ForwardIterator1>::value_type, |
4150 | typename iterator_traits<_ForwardIterator2>::value_type>) |
4151 | __glibcxx_requires_valid_range(__first1, __last1); |
4152 | __glibcxx_requires_valid_range(__first2, __last2); |
4153 | |
4154 | return std::__search(__first1, __last1, __first2, __last2, |
4155 | __gnu_cxx::__ops::__iter_equal_to_iter()); |
4156 | } |
4157 | |
4158 | |
4159 | |
4160 | |
4161 | |
4162 | |
4163 | |
4164 | |
4165 | |
4166 | |
4167 | |
4168 | |
4169 | |
4170 | |
4171 | |
4172 | |
4173 | |
4174 | |
4175 | |
4176 | |
4177 | |
4178 | |
4179 | template<typename _ForwardIterator1, typename _ForwardIterator2, |
4180 | typename _BinaryPredicate> |
4181 | _GLIBCXX20_CONSTEXPR |
4182 | inline _ForwardIterator1 |
4183 | search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, |
4184 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, |
4185 | _BinaryPredicate __predicate) |
4186 | { |
4187 | |
4188 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) |
4189 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) |
4190 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
4191 | typename iterator_traits<_ForwardIterator1>::value_type, |
4192 | typename iterator_traits<_ForwardIterator2>::value_type>) |
4193 | __glibcxx_requires_valid_range(__first1, __last1); |
4194 | __glibcxx_requires_valid_range(__first2, __last2); |
4195 | |
4196 | return std::__search(__first1, __last1, __first2, __last2, |
4197 | __gnu_cxx::__ops::__iter_comp_iter(__predicate)); |
4198 | } |
4199 | |
4200 | |
4201 | |
4202 | |
4203 | |
4204 | |
4205 | |
4206 | |
4207 | |
4208 | |
4209 | |
4210 | |
4211 | |
4212 | |
4213 | |
4214 | |
4215 | template<typename _ForwardIterator, typename _Integer, typename _Tp> |
4216 | _GLIBCXX20_CONSTEXPR |
4217 | inline _ForwardIterator |
4218 | search_n(_ForwardIterator __first, _ForwardIterator __last, |
4219 | _Integer __count, const _Tp& __val) |
4220 | { |
4221 | |
4222 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
4223 | __glibcxx_function_requires(_EqualOpConcept< |
4224 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
4225 | __glibcxx_requires_valid_range(__first, __last); |
4226 | |
4227 | return std::__search_n(__first, __last, __count, |
4228 | __gnu_cxx::__ops::__iter_equals_val(__val)); |
4229 | } |
4230 | |
4231 | |
4232 | |
4233 | |
4234 | |
4235 | |
4236 | |
4237 | |
4238 | |
4239 | |
4240 | |
4241 | |
4242 | |
4243 | |
4244 | |
4245 | |
4246 | |
4247 | |
4248 | |
4249 | template<typename _ForwardIterator, typename _Integer, typename _Tp, |
4250 | typename _BinaryPredicate> |
4251 | _GLIBCXX20_CONSTEXPR |
4252 | inline _ForwardIterator |
4253 | search_n(_ForwardIterator __first, _ForwardIterator __last, |
4254 | _Integer __count, const _Tp& __val, |
4255 | _BinaryPredicate __binary_pred) |
4256 | { |
4257 | |
4258 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
4259 | __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, |
4260 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
4261 | __glibcxx_requires_valid_range(__first, __last); |
4262 | |
4263 | return std::__search_n(__first, __last, __count, |
4264 | __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val)); |
4265 | } |
4266 | |
4267 | #if __cplusplus > 201402L |
4268 | |
4269 | |
4270 | |
4271 | |
4272 | |
4273 | |
4274 | |
4275 | template<typename _ForwardIterator, typename _Searcher> |
4276 | inline _ForwardIterator |
4277 | search(_ForwardIterator __first, _ForwardIterator __last, |
4278 | const _Searcher& __searcher) |
4279 | { return __searcher(__first, __last).first; } |
4280 | #endif |
4281 | |
4282 | |
4283 | |
4284 | |
4285 | |
4286 | |
4287 | |
4288 | |
4289 | |
4290 | |
4291 | |
4292 | |
4293 | |
4294 | |
4295 | |
4296 | |
4297 | |
4298 | template<typename _InputIterator, typename _OutputIterator, |
4299 | typename _UnaryOperation> |
4300 | _GLIBCXX20_CONSTEXPR |
4301 | _OutputIterator |
4302 | transform(_InputIterator __first, _InputIterator __last, |
4303 | _OutputIterator __result, _UnaryOperation __unary_op) |
4304 | { |
4305 | |
4306 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
4307 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4308 | |
4309 | __typeof__(__unary_op(*__first))>) |
4310 | __glibcxx_requires_valid_range(__first, __last); |
4311 | |
4312 | for (; __first != __last; ++__first, (void)++__result) |
4313 | *__result = __unary_op(*__first); |
4314 | return __result; |
4315 | } |
4316 | |
4317 | |
4318 | |
4319 | |
4320 | |
4321 | |
4322 | |
4323 | |
4324 | |
4325 | |
4326 | |
4327 | |
4328 | |
4329 | |
4330 | |
4331 | |
4332 | |
4333 | |
4334 | |
4335 | |
4336 | template<typename _InputIterator1, typename _InputIterator2, |
4337 | typename _OutputIterator, typename _BinaryOperation> |
4338 | _GLIBCXX20_CONSTEXPR |
4339 | _OutputIterator |
4340 | transform(_InputIterator1 __first1, _InputIterator1 __last1, |
4341 | _InputIterator2 __first2, _OutputIterator __result, |
4342 | _BinaryOperation __binary_op) |
4343 | { |
4344 | |
4345 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
4346 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
4347 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4348 | |
4349 | __typeof__(__binary_op(*__first1,*__first2))>) |
4350 | __glibcxx_requires_valid_range(__first1, __last1); |
4351 | |
4352 | for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result) |
4353 | *__result = __binary_op(*__first1, *__first2); |
4354 | return __result; |
4355 | } |
4356 | |
4357 | |
4358 | |
4359 | |
4360 | |
4361 | |
4362 | |
4363 | |
4364 | |
4365 | |
4366 | |
4367 | |
4368 | |
4369 | |
4370 | template<typename _ForwardIterator, typename _Tp> |
4371 | _GLIBCXX20_CONSTEXPR |
4372 | void |
4373 | replace(_ForwardIterator __first, _ForwardIterator __last, |
4374 | const _Tp& __old_value, const _Tp& __new_value) |
4375 | { |
4376 | |
4377 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
4378 | _ForwardIterator>) |
4379 | __glibcxx_function_requires(_EqualOpConcept< |
4380 | typename iterator_traits<_ForwardIterator>::value_type, _Tp>) |
4381 | __glibcxx_function_requires(_ConvertibleConcept<_Tp, |
4382 | typename iterator_traits<_ForwardIterator>::value_type>) |
4383 | __glibcxx_requires_valid_range(__first, __last); |
4384 | |
4385 | for (; __first != __last; ++__first) |
4386 | if (*__first == __old_value) |
4387 | *__first = __new_value; |
4388 | } |
4389 | |
4390 | |
4391 | |
4392 | |
4393 | |
4394 | |
4395 | |
4396 | |
4397 | |
4398 | |
4399 | |
4400 | |
4401 | |
4402 | |
4403 | template<typename _ForwardIterator, typename _Predicate, typename _Tp> |
4404 | _GLIBCXX20_CONSTEXPR |
4405 | void |
4406 | replace_if(_ForwardIterator __first, _ForwardIterator __last, |
4407 | _Predicate __pred, const _Tp& __new_value) |
4408 | { |
4409 | |
4410 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
4411 | _ForwardIterator>) |
4412 | __glibcxx_function_requires(_ConvertibleConcept<_Tp, |
4413 | typename iterator_traits<_ForwardIterator>::value_type>) |
4414 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
4415 | typename iterator_traits<_ForwardIterator>::value_type>) |
4416 | __glibcxx_requires_valid_range(__first, __last); |
4417 | |
4418 | for (; __first != __last; ++__first) |
4419 | if (__pred(*__first)) |
4420 | *__first = __new_value; |
4421 | } |
4422 | |
4423 | |
4424 | |
4425 | |
4426 | |
4427 | |
4428 | |
4429 | |
4430 | |
4431 | |
4432 | |
4433 | |
4434 | |
4435 | |
4436 | template<typename _ForwardIterator, typename _Generator> |
4437 | _GLIBCXX20_CONSTEXPR |
4438 | void |
4439 | generate(_ForwardIterator __first, _ForwardIterator __last, |
4440 | _Generator __gen) |
4441 | { |
4442 | |
4443 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
4444 | __glibcxx_function_requires(_GeneratorConcept<_Generator, |
4445 | typename iterator_traits<_ForwardIterator>::value_type>) |
4446 | __glibcxx_requires_valid_range(__first, __last); |
4447 | |
4448 | for (; __first != __last; ++__first) |
4449 | *__first = __gen(); |
4450 | } |
4451 | |
4452 | |
4453 | |
4454 | |
4455 | |
4456 | |
4457 | |
4458 | |
4459 | |
4460 | |
4461 | |
4462 | |
4463 | |
4464 | |
4465 | |
4466 | |
4467 | |
4468 | |
4469 | |
4470 | template<typename _OutputIterator, typename _Size, typename _Generator> |
4471 | _GLIBCXX20_CONSTEXPR |
4472 | _OutputIterator |
4473 | generate_n(_OutputIterator __first, _Size __n, _Generator __gen) |
4474 | { |
4475 | |
4476 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4477 | |
4478 | __typeof__(__gen())>) |
4479 | |
4480 | typedef __decltype(std::__size_to_integer(__n)) _IntSize; |
4481 | for (_IntSize __niter = std::__size_to_integer(__n); |
4482 | __niter > 0; --__niter, (void) ++__first) |
4483 | *__first = __gen(); |
4484 | return __first; |
4485 | } |
4486 | |
4487 | |
4488 | |
4489 | |
4490 | |
4491 | |
4492 | |
4493 | |
4494 | |
4495 | |
4496 | |
4497 | |
4498 | |
4499 | |
4500 | |
4501 | |
4502 | |
4503 | |
4504 | |
4505 | |
4506 | |
4507 | |
4508 | template<typename _InputIterator, typename _OutputIterator> |
4509 | _GLIBCXX20_CONSTEXPR |
4510 | inline _OutputIterator |
4511 | unique_copy(_InputIterator __first, _InputIterator __last, |
4512 | _OutputIterator __result) |
4513 | { |
4514 | |
4515 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
4516 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4517 | typename iterator_traits<_InputIterator>::value_type>) |
4518 | __glibcxx_function_requires(_EqualityComparableConcept< |
4519 | typename iterator_traits<_InputIterator>::value_type>) |
4520 | __glibcxx_requires_valid_range(__first, __last); |
4521 | |
4522 | if (__first == __last) |
4523 | return __result; |
4524 | return std::__unique_copy(__first, __last, __result, |
4525 | __gnu_cxx::__ops::__iter_equal_to_iter(), |
4526 | std::__iterator_category(__first), |
4527 | std::__iterator_category(__result)); |
4528 | } |
4529 | |
4530 | |
4531 | |
4532 | |
4533 | |
4534 | |
4535 | |
4536 | |
4537 | |
4538 | |
4539 | |
4540 | |
4541 | |
4542 | |
4543 | |
4544 | |
4545 | |
4546 | |
4547 | |
4548 | |
4549 | template<typename _InputIterator, typename _OutputIterator, |
4550 | typename _BinaryPredicate> |
4551 | _GLIBCXX20_CONSTEXPR |
4552 | inline _OutputIterator |
4553 | unique_copy(_InputIterator __first, _InputIterator __last, |
4554 | _OutputIterator __result, |
4555 | _BinaryPredicate __binary_pred) |
4556 | { |
4557 | |
4558 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) |
4559 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4560 | typename iterator_traits<_InputIterator>::value_type>) |
4561 | __glibcxx_requires_valid_range(__first, __last); |
4562 | |
4563 | if (__first == __last) |
4564 | return __result; |
4565 | return std::__unique_copy(__first, __last, __result, |
4566 | __gnu_cxx::__ops::__iter_comp_iter(__binary_pred), |
4567 | std::__iterator_category(__first), |
4568 | std::__iterator_category(__result)); |
4569 | } |
4570 | |
4571 | #if _GLIBCXX_HOSTED |
4572 | |
4573 | |
4574 | |
4575 | |
4576 | |
4577 | |
4578 | |
4579 | |
4580 | |
4581 | |
4582 | |
4583 | template<typename _RandomAccessIterator> |
4584 | inline void |
4585 | random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) |
4586 | { |
4587 | |
4588 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4589 | _RandomAccessIterator>) |
4590 | __glibcxx_requires_valid_range(__first, __last); |
4591 | |
4592 | if (__first != __last) |
4593 | for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) |
4594 | { |
4595 | |
4596 | _RandomAccessIterator __j = __first |
4597 | + std::rand() % ((__i - __first) + 1); |
4598 | if (__i != __j) |
4599 | std::iter_swap(__i, __j); |
4600 | } |
4601 | } |
4602 | #endif |
4603 | |
4604 | |
4605 | |
4606 | |
4607 | |
4608 | |
4609 | |
4610 | |
4611 | |
4612 | |
4613 | |
4614 | |
4615 | |
4616 | |
4617 | |
4618 | template<typename _RandomAccessIterator, typename _RandomNumberGenerator> |
4619 | void |
4620 | random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, |
4621 | #if __cplusplus >= 201103L |
4622 | _RandomNumberGenerator&& __rand) |
4623 | #else |
4624 | _RandomNumberGenerator& __rand) |
4625 | #endif |
4626 | { |
4627 | |
4628 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4629 | _RandomAccessIterator>) |
4630 | __glibcxx_requires_valid_range(__first, __last); |
4631 | |
4632 | if (__first == __last) |
4633 | return; |
4634 | for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) |
4635 | { |
4636 | _RandomAccessIterator __j = __first + __rand((__i - __first) + 1); |
4637 | if (__i != __j) |
4638 | std::iter_swap(__i, __j); |
4639 | } |
4640 | } |
4641 | |
4642 | |
4643 | |
4644 | |
4645 | |
4646 | |
4647 | |
4648 | |
4649 | |
4650 | |
4651 | |
4652 | |
4653 | |
4654 | |
4655 | |
4656 | |
4657 | |
4658 | template<typename _ForwardIterator, typename _Predicate> |
4659 | _GLIBCXX20_CONSTEXPR |
4660 | inline _ForwardIterator |
4661 | partition(_ForwardIterator __first, _ForwardIterator __last, |
4662 | _Predicate __pred) |
4663 | { |
4664 | |
4665 | __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< |
4666 | _ForwardIterator>) |
4667 | __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, |
4668 | typename iterator_traits<_ForwardIterator>::value_type>) |
4669 | __glibcxx_requires_valid_range(__first, __last); |
4670 | |
4671 | return std::__partition(__first, __last, __pred, |
4672 | std::__iterator_category(__first)); |
4673 | } |
4674 | |
4675 | |
4676 | |
4677 | |
4678 | |
4679 | |
4680 | |
4681 | |
4682 | |
4683 | |
4684 | |
4685 | |
4686 | |
4687 | |
4688 | |
4689 | |
4690 | |
4691 | |
4692 | template<typename _RandomAccessIterator> |
4693 | _GLIBCXX20_CONSTEXPR |
4694 | inline void |
4695 | partial_sort(_RandomAccessIterator __first, |
4696 | _RandomAccessIterator __middle, |
4697 | _RandomAccessIterator __last) |
4698 | { |
4699 | |
4700 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4701 | _RandomAccessIterator>) |
4702 | __glibcxx_function_requires(_LessThanComparableConcept< |
4703 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
4704 | __glibcxx_requires_valid_range(__first, __middle); |
4705 | __glibcxx_requires_valid_range(__middle, __last); |
4706 | __glibcxx_requires_irreflexive(__first, __last); |
4707 | |
4708 | std::__partial_sort(__first, __middle, __last, |
4709 | __gnu_cxx::__ops::__iter_less_iter()); |
4710 | } |
4711 | |
4712 | |
4713 | |
4714 | |
4715 | |
4716 | |
4717 | |
4718 | |
4719 | |
4720 | |
4721 | |
4722 | |
4723 | |
4724 | |
4725 | |
4726 | |
4727 | |
4728 | |
4729 | |
4730 | |
4731 | template<typename _RandomAccessIterator, typename _Compare> |
4732 | _GLIBCXX20_CONSTEXPR |
4733 | inline void |
4734 | partial_sort(_RandomAccessIterator __first, |
4735 | _RandomAccessIterator __middle, |
4736 | _RandomAccessIterator __last, |
4737 | _Compare __comp) |
4738 | { |
4739 | |
4740 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4741 | _RandomAccessIterator>) |
4742 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
4743 | typename iterator_traits<_RandomAccessIterator>::value_type, |
4744 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
4745 | __glibcxx_requires_valid_range(__first, __middle); |
4746 | __glibcxx_requires_valid_range(__middle, __last); |
4747 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
4748 | |
4749 | std::__partial_sort(__first, __middle, __last, |
4750 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
4751 | } |
4752 | |
4753 | |
4754 | |
4755 | |
4756 | |
4757 | |
4758 | |
4759 | |
4760 | |
4761 | |
4762 | |
4763 | |
4764 | |
4765 | |
4766 | |
4767 | |
4768 | template<typename _RandomAccessIterator> |
4769 | _GLIBCXX20_CONSTEXPR |
4770 | inline void |
4771 | nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, |
4772 | _RandomAccessIterator __last) |
4773 | { |
4774 | |
4775 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4776 | _RandomAccessIterator>) |
4777 | __glibcxx_function_requires(_LessThanComparableConcept< |
4778 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
4779 | __glibcxx_requires_valid_range(__first, __nth); |
4780 | __glibcxx_requires_valid_range(__nth, __last); |
4781 | __glibcxx_requires_irreflexive(__first, __last); |
4782 | |
4783 | if (__first == __last || __nth == __last) |
4784 | return; |
4785 | |
4786 | std::__introselect(__first, __nth, __last, |
4787 | std::__lg(__last - __first) * 2, |
4788 | __gnu_cxx::__ops::__iter_less_iter()); |
4789 | } |
4790 | |
4791 | |
4792 | |
4793 | |
4794 | |
4795 | |
4796 | |
4797 | |
4798 | |
4799 | |
4800 | |
4801 | |
4802 | |
4803 | |
4804 | |
4805 | |
4806 | |
4807 | |
4808 | template<typename _RandomAccessIterator, typename _Compare> |
4809 | _GLIBCXX20_CONSTEXPR |
4810 | inline void |
4811 | nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, |
4812 | _RandomAccessIterator __last, _Compare __comp) |
4813 | { |
4814 | |
4815 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4816 | _RandomAccessIterator>) |
4817 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
4818 | typename iterator_traits<_RandomAccessIterator>::value_type, |
4819 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
4820 | __glibcxx_requires_valid_range(__first, __nth); |
4821 | __glibcxx_requires_valid_range(__nth, __last); |
4822 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
4823 | |
4824 | if (__first == __last || __nth == __last) |
4825 | return; |
4826 | |
4827 | std::__introselect(__first, __nth, __last, |
4828 | std::__lg(__last - __first) * 2, |
4829 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
4830 | } |
4831 | |
4832 | |
4833 | |
4834 | |
4835 | |
4836 | |
4837 | |
4838 | |
4839 | |
4840 | |
4841 | |
4842 | |
4843 | |
4844 | |
4845 | |
4846 | template<typename _RandomAccessIterator> |
4847 | _GLIBCXX20_CONSTEXPR |
4848 | inline void |
4849 | sort(_RandomAccessIterator __first, _RandomAccessIterator __last) |
4850 | { |
4851 | |
4852 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4853 | _RandomAccessIterator>) |
4854 | __glibcxx_function_requires(_LessThanComparableConcept< |
4855 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
4856 | __glibcxx_requires_valid_range(__first, __last); |
4857 | __glibcxx_requires_irreflexive(__first, __last); |
4858 | |
4859 | std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter()); |
| 55 | | Calling '__sort<unsigned int *, __gnu_cxx::__ops::_Iter_less_iter>' | |
|
4860 | } |
4861 | |
4862 | |
4863 | |
4864 | |
4865 | |
4866 | |
4867 | |
4868 | |
4869 | |
4870 | |
4871 | |
4872 | |
4873 | |
4874 | |
4875 | |
4876 | |
4877 | template<typename _RandomAccessIterator, typename _Compare> |
4878 | _GLIBCXX20_CONSTEXPR |
4879 | inline void |
4880 | sort(_RandomAccessIterator __first, _RandomAccessIterator __last, |
4881 | _Compare __comp) |
4882 | { |
4883 | |
4884 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
4885 | _RandomAccessIterator>) |
4886 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
4887 | typename iterator_traits<_RandomAccessIterator>::value_type, |
4888 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
4889 | __glibcxx_requires_valid_range(__first, __last); |
4890 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
4891 | |
4892 | std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
4893 | } |
4894 | |
4895 | template<typename _InputIterator1, typename _InputIterator2, |
4896 | typename _OutputIterator, typename _Compare> |
4897 | _GLIBCXX20_CONSTEXPR |
4898 | _OutputIterator |
4899 | __merge(_InputIterator1 __first1, _InputIterator1 __last1, |
4900 | _InputIterator2 __first2, _InputIterator2 __last2, |
4901 | _OutputIterator __result, _Compare __comp) |
4902 | { |
4903 | while (__first1 != __last1 && __first2 != __last2) |
4904 | { |
4905 | if (__comp(__first2, __first1)) |
4906 | { |
4907 | *__result = *__first2; |
4908 | ++__first2; |
4909 | } |
4910 | else |
4911 | { |
4912 | *__result = *__first1; |
4913 | ++__first1; |
4914 | } |
4915 | ++__result; |
4916 | } |
4917 | return std::copy(__first2, __last2, |
4918 | std::copy(__first1, __last1, __result)); |
4919 | } |
4920 | |
4921 | |
4922 | |
4923 | |
4924 | |
4925 | |
4926 | |
4927 | |
4928 | |
4929 | |
4930 | |
4931 | |
4932 | |
4933 | |
4934 | |
4935 | |
4936 | |
4937 | |
4938 | |
4939 | |
4940 | template<typename _InputIterator1, typename _InputIterator2, |
4941 | typename _OutputIterator> |
4942 | _GLIBCXX20_CONSTEXPR |
4943 | inline _OutputIterator |
4944 | merge(_InputIterator1 __first1, _InputIterator1 __last1, |
4945 | _InputIterator2 __first2, _InputIterator2 __last2, |
4946 | _OutputIterator __result) |
4947 | { |
4948 | |
4949 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
4950 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
4951 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4952 | typename iterator_traits<_InputIterator1>::value_type>) |
4953 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
4954 | typename iterator_traits<_InputIterator2>::value_type>) |
4955 | __glibcxx_function_requires(_LessThanOpConcept< |
4956 | typename iterator_traits<_InputIterator2>::value_type, |
4957 | typename iterator_traits<_InputIterator1>::value_type>) |
4958 | __glibcxx_requires_sorted_set(__first1, __last1, __first2); |
4959 | __glibcxx_requires_sorted_set(__first2, __last2, __first1); |
4960 | __glibcxx_requires_irreflexive2(__first1, __last1); |
4961 | __glibcxx_requires_irreflexive2(__first2, __last2); |
4962 | |
4963 | return _GLIBCXX_STD_A::__merge(__first1, __last1, |
4964 | __first2, __last2, __result, |
4965 | __gnu_cxx::__ops::__iter_less_iter()); |
4966 | } |
4967 | |
4968 | |
4969 | |
4970 | |
4971 | |
4972 | |
4973 | |
4974 | |
4975 | |
4976 | |
4977 | |
4978 | |
4979 | |
4980 | |
4981 | |
4982 | |
4983 | |
4984 | |
4985 | |
4986 | |
4987 | |
4988 | |
4989 | |
4990 | |
4991 | template<typename _InputIterator1, typename _InputIterator2, |
4992 | typename _OutputIterator, typename _Compare> |
4993 | _GLIBCXX20_CONSTEXPR |
4994 | inline _OutputIterator |
4995 | merge(_InputIterator1 __first1, _InputIterator1 __last1, |
4996 | _InputIterator2 __first2, _InputIterator2 __last2, |
4997 | _OutputIterator __result, _Compare __comp) |
4998 | { |
4999 | |
5000 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5001 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5002 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5003 | typename iterator_traits<_InputIterator1>::value_type>) |
5004 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5005 | typename iterator_traits<_InputIterator2>::value_type>) |
5006 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5007 | typename iterator_traits<_InputIterator2>::value_type, |
5008 | typename iterator_traits<_InputIterator1>::value_type>) |
5009 | __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); |
5010 | __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); |
5011 | __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); |
5012 | __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); |
5013 | |
5014 | return _GLIBCXX_STD_A::__merge(__first1, __last1, |
5015 | __first2, __last2, __result, |
5016 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5017 | } |
5018 | |
5019 | template<typename _RandomAccessIterator, typename _Compare> |
5020 | inline void |
5021 | __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, |
5022 | _Compare __comp) |
5023 | { |
5024 | typedef typename iterator_traits<_RandomAccessIterator>::value_type |
5025 | _ValueType; |
5026 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type |
5027 | _DistanceType; |
5028 | |
5029 | typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf; |
5030 | _TmpBuf __buf(__first, std::distance(__first, __last)); |
5031 | |
5032 | if (__buf.begin() == 0) |
5033 | std::__inplace_stable_sort(__first, __last, __comp); |
5034 | else |
5035 | std::__stable_sort_adaptive(__first, __last, __buf.begin(), |
5036 | _DistanceType(__buf.size()), __comp); |
5037 | } |
5038 | |
5039 | |
5040 | |
5041 | |
5042 | |
5043 | |
5044 | |
5045 | |
5046 | |
5047 | |
5048 | |
5049 | |
5050 | |
5051 | |
5052 | |
5053 | |
5054 | |
5055 | |
5056 | template<typename _RandomAccessIterator> |
5057 | inline void |
5058 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) |
5059 | { |
5060 | |
5061 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
5062 | _RandomAccessIterator>) |
5063 | __glibcxx_function_requires(_LessThanComparableConcept< |
5064 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
5065 | __glibcxx_requires_valid_range(__first, __last); |
5066 | __glibcxx_requires_irreflexive(__first, __last); |
5067 | |
5068 | _GLIBCXX_STD_A::__stable_sort(__first, __last, |
5069 | __gnu_cxx::__ops::__iter_less_iter()); |
5070 | } |
5071 | |
5072 | |
5073 | |
5074 | |
5075 | |
5076 | |
5077 | |
5078 | |
5079 | |
5080 | |
5081 | |
5082 | |
5083 | |
5084 | |
5085 | |
5086 | |
5087 | |
5088 | |
5089 | |
5090 | template<typename _RandomAccessIterator, typename _Compare> |
5091 | inline void |
5092 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, |
5093 | _Compare __comp) |
5094 | { |
5095 | |
5096 | __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< |
5097 | _RandomAccessIterator>) |
5098 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5099 | typename iterator_traits<_RandomAccessIterator>::value_type, |
5100 | typename iterator_traits<_RandomAccessIterator>::value_type>) |
5101 | __glibcxx_requires_valid_range(__first, __last); |
5102 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
5103 | |
5104 | _GLIBCXX_STD_A::__stable_sort(__first, __last, |
5105 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5106 | } |
5107 | |
5108 | template<typename _InputIterator1, typename _InputIterator2, |
5109 | typename _OutputIterator, |
5110 | typename _Compare> |
5111 | _GLIBCXX20_CONSTEXPR |
5112 | _OutputIterator |
5113 | __set_union(_InputIterator1 __first1, _InputIterator1 __last1, |
5114 | _InputIterator2 __first2, _InputIterator2 __last2, |
5115 | _OutputIterator __result, _Compare __comp) |
5116 | { |
5117 | while (__first1 != __last1 && __first2 != __last2) |
5118 | { |
5119 | if (__comp(__first1, __first2)) |
5120 | { |
5121 | *__result = *__first1; |
5122 | ++__first1; |
5123 | } |
5124 | else if (__comp(__first2, __first1)) |
5125 | { |
5126 | *__result = *__first2; |
5127 | ++__first2; |
5128 | } |
5129 | else |
5130 | { |
5131 | *__result = *__first1; |
5132 | ++__first1; |
5133 | ++__first2; |
5134 | } |
5135 | ++__result; |
5136 | } |
5137 | return std::copy(__first2, __last2, |
5138 | std::copy(__first1, __last1, __result)); |
5139 | } |
5140 | |
5141 | |
5142 | |
5143 | |
5144 | |
5145 | |
5146 | |
5147 | |
5148 | |
5149 | |
5150 | |
5151 | |
5152 | |
5153 | |
5154 | |
5155 | |
5156 | |
5157 | |
5158 | |
5159 | |
5160 | template<typename _InputIterator1, typename _InputIterator2, |
5161 | typename _OutputIterator> |
5162 | _GLIBCXX20_CONSTEXPR |
5163 | inline _OutputIterator |
5164 | set_union(_InputIterator1 __first1, _InputIterator1 __last1, |
5165 | _InputIterator2 __first2, _InputIterator2 __last2, |
5166 | _OutputIterator __result) |
5167 | { |
5168 | |
5169 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5170 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5171 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5172 | typename iterator_traits<_InputIterator1>::value_type>) |
5173 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5174 | typename iterator_traits<_InputIterator2>::value_type>) |
5175 | __glibcxx_function_requires(_LessThanOpConcept< |
5176 | typename iterator_traits<_InputIterator1>::value_type, |
5177 | typename iterator_traits<_InputIterator2>::value_type>) |
5178 | __glibcxx_function_requires(_LessThanOpConcept< |
5179 | typename iterator_traits<_InputIterator2>::value_type, |
5180 | typename iterator_traits<_InputIterator1>::value_type>) |
5181 | __glibcxx_requires_sorted_set(__first1, __last1, __first2); |
5182 | __glibcxx_requires_sorted_set(__first2, __last2, __first1); |
5183 | __glibcxx_requires_irreflexive2(__first1, __last1); |
5184 | __glibcxx_requires_irreflexive2(__first2, __last2); |
5185 | |
5186 | return _GLIBCXX_STD_A::__set_union(__first1, __last1, |
5187 | __first2, __last2, __result, |
5188 | __gnu_cxx::__ops::__iter_less_iter()); |
5189 | } |
5190 | |
5191 | |
5192 | |
5193 | |
5194 | |
5195 | |
5196 | |
5197 | |
5198 | |
5199 | |
5200 | |
5201 | |
5202 | |
5203 | |
5204 | |
5205 | |
5206 | |
5207 | |
5208 | |
5209 | |
5210 | |
5211 | template<typename _InputIterator1, typename _InputIterator2, |
5212 | typename _OutputIterator, typename _Compare> |
5213 | _GLIBCXX20_CONSTEXPR |
5214 | inline _OutputIterator |
5215 | set_union(_InputIterator1 __first1, _InputIterator1 __last1, |
5216 | _InputIterator2 __first2, _InputIterator2 __last2, |
5217 | _OutputIterator __result, _Compare __comp) |
5218 | { |
5219 | |
5220 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5221 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5222 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5223 | typename iterator_traits<_InputIterator1>::value_type>) |
5224 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5225 | typename iterator_traits<_InputIterator2>::value_type>) |
5226 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5227 | typename iterator_traits<_InputIterator1>::value_type, |
5228 | typename iterator_traits<_InputIterator2>::value_type>) |
5229 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5230 | typename iterator_traits<_InputIterator2>::value_type, |
5231 | typename iterator_traits<_InputIterator1>::value_type>) |
5232 | __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); |
5233 | __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); |
5234 | __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); |
5235 | __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); |
5236 | |
5237 | return _GLIBCXX_STD_A::__set_union(__first1, __last1, |
5238 | __first2, __last2, __result, |
5239 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5240 | } |
5241 | |
5242 | template<typename _InputIterator1, typename _InputIterator2, |
5243 | typename _OutputIterator, |
5244 | typename _Compare> |
5245 | _GLIBCXX20_CONSTEXPR |
5246 | _OutputIterator |
5247 | __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, |
5248 | _InputIterator2 __first2, _InputIterator2 __last2, |
5249 | _OutputIterator __result, _Compare __comp) |
5250 | { |
5251 | while (__first1 != __last1 && __first2 != __last2) |
5252 | if (__comp(__first1, __first2)) |
5253 | ++__first1; |
5254 | else if (__comp(__first2, __first1)) |
5255 | ++__first2; |
5256 | else |
5257 | { |
5258 | *__result = *__first1; |
5259 | ++__first1; |
5260 | ++__first2; |
5261 | ++__result; |
5262 | } |
5263 | return __result; |
5264 | } |
5265 | |
5266 | |
5267 | |
5268 | |
5269 | |
5270 | |
5271 | |
5272 | |
5273 | |
5274 | |
5275 | |
5276 | |
5277 | |
5278 | |
5279 | |
5280 | |
5281 | |
5282 | |
5283 | |
5284 | template<typename _InputIterator1, typename _InputIterator2, |
5285 | typename _OutputIterator> |
5286 | _GLIBCXX20_CONSTEXPR |
5287 | inline _OutputIterator |
5288 | set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, |
5289 | _InputIterator2 __first2, _InputIterator2 __last2, |
5290 | _OutputIterator __result) |
5291 | { |
5292 | |
5293 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5294 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5295 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5296 | typename iterator_traits<_InputIterator1>::value_type>) |
5297 | __glibcxx_function_requires(_LessThanOpConcept< |
5298 | typename iterator_traits<_InputIterator1>::value_type, |
5299 | typename iterator_traits<_InputIterator2>::value_type>) |
5300 | __glibcxx_function_requires(_LessThanOpConcept< |
5301 | typename iterator_traits<_InputIterator2>::value_type, |
5302 | typename iterator_traits<_InputIterator1>::value_type>) |
5303 | __glibcxx_requires_sorted_set(__first1, __last1, __first2); |
5304 | __glibcxx_requires_sorted_set(__first2, __last2, __first1); |
5305 | __glibcxx_requires_irreflexive2(__first1, __last1); |
5306 | __glibcxx_requires_irreflexive2(__first2, __last2); |
5307 | |
5308 | return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, |
5309 | __first2, __last2, __result, |
5310 | __gnu_cxx::__ops::__iter_less_iter()); |
5311 | } |
5312 | |
5313 | |
5314 | |
5315 | |
5316 | |
5317 | |
5318 | |
5319 | |
5320 | |
5321 | |
5322 | |
5323 | |
5324 | |
5325 | |
5326 | |
5327 | |
5328 | |
5329 | |
5330 | |
5331 | |
5332 | |
5333 | |
5334 | template<typename _InputIterator1, typename _InputIterator2, |
5335 | typename _OutputIterator, typename _Compare> |
5336 | _GLIBCXX20_CONSTEXPR |
5337 | inline _OutputIterator |
5338 | set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, |
5339 | _InputIterator2 __first2, _InputIterator2 __last2, |
5340 | _OutputIterator __result, _Compare __comp) |
5341 | { |
5342 | |
5343 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5344 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5345 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5346 | typename iterator_traits<_InputIterator1>::value_type>) |
5347 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5348 | typename iterator_traits<_InputIterator1>::value_type, |
5349 | typename iterator_traits<_InputIterator2>::value_type>) |
5350 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5351 | typename iterator_traits<_InputIterator2>::value_type, |
5352 | typename iterator_traits<_InputIterator1>::value_type>) |
5353 | __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); |
5354 | __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); |
5355 | __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); |
5356 | __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); |
5357 | |
5358 | return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, |
5359 | __first2, __last2, __result, |
5360 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5361 | } |
5362 | |
5363 | template<typename _InputIterator1, typename _InputIterator2, |
5364 | typename _OutputIterator, |
5365 | typename _Compare> |
5366 | _GLIBCXX20_CONSTEXPR |
5367 | _OutputIterator |
5368 | __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, |
5369 | _InputIterator2 __first2, _InputIterator2 __last2, |
5370 | _OutputIterator __result, _Compare __comp) |
5371 | { |
5372 | while (__first1 != __last1 && __first2 != __last2) |
5373 | if (__comp(__first1, __first2)) |
5374 | { |
5375 | *__result = *__first1; |
5376 | ++__first1; |
5377 | ++__result; |
5378 | } |
5379 | else if (__comp(__first2, __first1)) |
5380 | ++__first2; |
5381 | else |
5382 | { |
5383 | ++__first1; |
5384 | ++__first2; |
5385 | } |
5386 | return std::copy(__first1, __last1, __result); |
5387 | } |
5388 | |
5389 | |
5390 | |
5391 | |
5392 | |
5393 | |
5394 | |
5395 | |
5396 | |
5397 | |
5398 | |
5399 | |
5400 | |
5401 | |
5402 | |
5403 | |
5404 | |
5405 | |
5406 | |
5407 | |
5408 | |
5409 | template<typename _InputIterator1, typename _InputIterator2, |
5410 | typename _OutputIterator> |
5411 | _GLIBCXX20_CONSTEXPR |
5412 | inline _OutputIterator |
5413 | set_difference(_InputIterator1 __first1, _InputIterator1 __last1, |
5414 | _InputIterator2 __first2, _InputIterator2 __last2, |
5415 | _OutputIterator __result) |
5416 | { |
5417 | |
5418 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5419 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5420 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5421 | typename iterator_traits<_InputIterator1>::value_type>) |
5422 | __glibcxx_function_requires(_LessThanOpConcept< |
5423 | typename iterator_traits<_InputIterator1>::value_type, |
5424 | typename iterator_traits<_InputIterator2>::value_type>) |
5425 | __glibcxx_function_requires(_LessThanOpConcept< |
5426 | typename iterator_traits<_InputIterator2>::value_type, |
5427 | typename iterator_traits<_InputIterator1>::value_type>) |
5428 | __glibcxx_requires_sorted_set(__first1, __last1, __first2); |
5429 | __glibcxx_requires_sorted_set(__first2, __last2, __first1); |
5430 | __glibcxx_requires_irreflexive2(__first1, __last1); |
5431 | __glibcxx_requires_irreflexive2(__first2, __last2); |
5432 | |
5433 | return _GLIBCXX_STD_A::__set_difference(__first1, __last1, |
5434 | __first2, __last2, __result, |
5435 | __gnu_cxx::__ops::__iter_less_iter()); |
5436 | } |
5437 | |
5438 | |
5439 | |
5440 | |
5441 | |
5442 | |
5443 | |
5444 | |
5445 | |
5446 | |
5447 | |
5448 | |
5449 | |
5450 | |
5451 | |
5452 | |
5453 | |
5454 | |
5455 | |
5456 | |
5457 | |
5458 | |
5459 | |
5460 | |
5461 | template<typename _InputIterator1, typename _InputIterator2, |
5462 | typename _OutputIterator, typename _Compare> |
5463 | _GLIBCXX20_CONSTEXPR |
5464 | inline _OutputIterator |
5465 | set_difference(_InputIterator1 __first1, _InputIterator1 __last1, |
5466 | _InputIterator2 __first2, _InputIterator2 __last2, |
5467 | _OutputIterator __result, _Compare __comp) |
5468 | { |
5469 | |
5470 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5471 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5472 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5473 | typename iterator_traits<_InputIterator1>::value_type>) |
5474 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5475 | typename iterator_traits<_InputIterator1>::value_type, |
5476 | typename iterator_traits<_InputIterator2>::value_type>) |
5477 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5478 | typename iterator_traits<_InputIterator2>::value_type, |
5479 | typename iterator_traits<_InputIterator1>::value_type>) |
5480 | __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); |
5481 | __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); |
5482 | __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); |
5483 | __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); |
5484 | |
5485 | return _GLIBCXX_STD_A::__set_difference(__first1, __last1, |
5486 | __first2, __last2, __result, |
5487 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5488 | } |
5489 | |
5490 | template<typename _InputIterator1, typename _InputIterator2, |
5491 | typename _OutputIterator, |
5492 | typename _Compare> |
5493 | _GLIBCXX20_CONSTEXPR |
5494 | _OutputIterator |
5495 | __set_symmetric_difference(_InputIterator1 __first1, |
5496 | _InputIterator1 __last1, |
5497 | _InputIterator2 __first2, |
5498 | _InputIterator2 __last2, |
5499 | _OutputIterator __result, |
5500 | _Compare __comp) |
5501 | { |
5502 | while (__first1 != __last1 && __first2 != __last2) |
5503 | if (__comp(__first1, __first2)) |
5504 | { |
5505 | *__result = *__first1; |
5506 | ++__first1; |
5507 | ++__result; |
5508 | } |
5509 | else if (__comp(__first2, __first1)) |
5510 | { |
5511 | *__result = *__first2; |
5512 | ++__first2; |
5513 | ++__result; |
5514 | } |
5515 | else |
5516 | { |
5517 | ++__first1; |
5518 | ++__first2; |
5519 | } |
5520 | return std::copy(__first2, __last2, |
5521 | std::copy(__first1, __last1, __result)); |
5522 | } |
5523 | |
5524 | |
5525 | |
5526 | |
5527 | |
5528 | |
5529 | |
5530 | |
5531 | |
5532 | |
5533 | |
5534 | |
5535 | |
5536 | |
5537 | |
5538 | |
5539 | |
5540 | |
5541 | |
5542 | template<typename _InputIterator1, typename _InputIterator2, |
5543 | typename _OutputIterator> |
5544 | _GLIBCXX20_CONSTEXPR |
5545 | inline _OutputIterator |
5546 | set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, |
5547 | _InputIterator2 __first2, _InputIterator2 __last2, |
5548 | _OutputIterator __result) |
5549 | { |
5550 | |
5551 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5552 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5553 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5554 | typename iterator_traits<_InputIterator1>::value_type>) |
5555 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5556 | typename iterator_traits<_InputIterator2>::value_type>) |
5557 | __glibcxx_function_requires(_LessThanOpConcept< |
5558 | typename iterator_traits<_InputIterator1>::value_type, |
5559 | typename iterator_traits<_InputIterator2>::value_type>) |
5560 | __glibcxx_function_requires(_LessThanOpConcept< |
5561 | typename iterator_traits<_InputIterator2>::value_type, |
5562 | typename iterator_traits<_InputIterator1>::value_type>) |
5563 | __glibcxx_requires_sorted_set(__first1, __last1, __first2); |
5564 | __glibcxx_requires_sorted_set(__first2, __last2, __first1); |
5565 | __glibcxx_requires_irreflexive2(__first1, __last1); |
5566 | __glibcxx_requires_irreflexive2(__first2, __last2); |
5567 | |
5568 | return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, |
5569 | __first2, __last2, __result, |
5570 | __gnu_cxx::__ops::__iter_less_iter()); |
5571 | } |
5572 | |
5573 | |
5574 | |
5575 | |
5576 | |
5577 | |
5578 | |
5579 | |
5580 | |
5581 | |
5582 | |
5583 | |
5584 | |
5585 | |
5586 | |
5587 | |
5588 | |
5589 | |
5590 | |
5591 | |
5592 | |
5593 | |
5594 | template<typename _InputIterator1, typename _InputIterator2, |
5595 | typename _OutputIterator, typename _Compare> |
5596 | _GLIBCXX20_CONSTEXPR |
5597 | inline _OutputIterator |
5598 | set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, |
5599 | _InputIterator2 __first2, _InputIterator2 __last2, |
5600 | _OutputIterator __result, |
5601 | _Compare __comp) |
5602 | { |
5603 | |
5604 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) |
5605 | __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) |
5606 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5607 | typename iterator_traits<_InputIterator1>::value_type>) |
5608 | __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, |
5609 | typename iterator_traits<_InputIterator2>::value_type>) |
5610 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5611 | typename iterator_traits<_InputIterator1>::value_type, |
5612 | typename iterator_traits<_InputIterator2>::value_type>) |
5613 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5614 | typename iterator_traits<_InputIterator2>::value_type, |
5615 | typename iterator_traits<_InputIterator1>::value_type>) |
5616 | __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); |
5617 | __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); |
5618 | __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); |
5619 | __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); |
5620 | |
5621 | return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, |
5622 | __first2, __last2, __result, |
5623 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5624 | } |
5625 | |
5626 | template<typename _ForwardIterator, typename _Compare> |
5627 | _GLIBCXX14_CONSTEXPR |
5628 | _ForwardIterator |
5629 | __min_element(_ForwardIterator __first, _ForwardIterator __last, |
5630 | _Compare __comp) |
5631 | { |
5632 | if (__first == __last) |
5633 | return __first; |
5634 | _ForwardIterator __result = __first; |
5635 | while (++__first != __last) |
5636 | if (__comp(__first, __result)) |
5637 | __result = __first; |
5638 | return __result; |
5639 | } |
5640 | |
5641 | |
5642 | |
5643 | |
5644 | |
5645 | |
5646 | |
5647 | |
5648 | template<typename _ForwardIterator> |
5649 | _GLIBCXX14_CONSTEXPR |
5650 | _ForwardIterator |
5651 | inline min_element(_ForwardIterator __first, _ForwardIterator __last) |
5652 | { |
5653 | |
5654 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
5655 | __glibcxx_function_requires(_LessThanComparableConcept< |
5656 | typename iterator_traits<_ForwardIterator>::value_type>) |
5657 | __glibcxx_requires_valid_range(__first, __last); |
5658 | __glibcxx_requires_irreflexive(__first, __last); |
5659 | |
5660 | return _GLIBCXX_STD_A::__min_element(__first, __last, |
5661 | __gnu_cxx::__ops::__iter_less_iter()); |
5662 | } |
5663 | |
5664 | |
5665 | |
5666 | |
5667 | |
5668 | |
5669 | |
5670 | |
5671 | |
5672 | |
5673 | template<typename _ForwardIterator, typename _Compare> |
5674 | _GLIBCXX14_CONSTEXPR |
5675 | inline _ForwardIterator |
5676 | min_element(_ForwardIterator __first, _ForwardIterator __last, |
5677 | _Compare __comp) |
5678 | { |
5679 | |
5680 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
5681 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5682 | typename iterator_traits<_ForwardIterator>::value_type, |
5683 | typename iterator_traits<_ForwardIterator>::value_type>) |
5684 | __glibcxx_requires_valid_range(__first, __last); |
5685 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
5686 | |
5687 | return _GLIBCXX_STD_A::__min_element(__first, __last, |
5688 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5689 | } |
5690 | |
5691 | template<typename _ForwardIterator, typename _Compare> |
5692 | _GLIBCXX14_CONSTEXPR |
5693 | _ForwardIterator |
5694 | __max_element(_ForwardIterator __first, _ForwardIterator __last, |
5695 | _Compare __comp) |
5696 | { |
5697 | if (__first == __last) return __first; |
5698 | _ForwardIterator __result = __first; |
5699 | while (++__first != __last) |
5700 | if (__comp(__result, __first)) |
5701 | __result = __first; |
5702 | return __result; |
5703 | } |
5704 | |
5705 | |
5706 | |
5707 | |
5708 | |
5709 | |
5710 | |
5711 | |
5712 | template<typename _ForwardIterator> |
5713 | _GLIBCXX14_CONSTEXPR |
5714 | inline _ForwardIterator |
5715 | max_element(_ForwardIterator __first, _ForwardIterator __last) |
5716 | { |
5717 | |
5718 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
5719 | __glibcxx_function_requires(_LessThanComparableConcept< |
5720 | typename iterator_traits<_ForwardIterator>::value_type>) |
5721 | __glibcxx_requires_valid_range(__first, __last); |
5722 | __glibcxx_requires_irreflexive(__first, __last); |
5723 | |
5724 | return _GLIBCXX_STD_A::__max_element(__first, __last, |
5725 | __gnu_cxx::__ops::__iter_less_iter()); |
5726 | } |
5727 | |
5728 | |
5729 | |
5730 | |
5731 | |
5732 | |
5733 | |
5734 | |
5735 | |
5736 | |
5737 | template<typename _ForwardIterator, typename _Compare> |
5738 | _GLIBCXX14_CONSTEXPR |
5739 | inline _ForwardIterator |
5740 | max_element(_ForwardIterator __first, _ForwardIterator __last, |
5741 | _Compare __comp) |
5742 | { |
5743 | |
5744 | __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) |
5745 | __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, |
5746 | typename iterator_traits<_ForwardIterator>::value_type, |
5747 | typename iterator_traits<_ForwardIterator>::value_type>) |
5748 | __glibcxx_requires_valid_range(__first, __last); |
5749 | __glibcxx_requires_irreflexive_pred(__first, __last, __comp); |
5750 | |
5751 | return _GLIBCXX_STD_A::__max_element(__first, __last, |
5752 | __gnu_cxx::__ops::__iter_comp_iter(__comp)); |
5753 | } |
5754 | |
5755 | #if __cplusplus >= 201402L |
5756 | |
5757 | template<typename _InputIterator, typename _RandomAccessIterator, |
5758 | typename _Size, typename _UniformRandomBitGenerator> |
5759 | _RandomAccessIterator |
5760 | __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag, |
5761 | _RandomAccessIterator __out, random_access_iterator_tag, |
5762 | _Size __n, _UniformRandomBitGenerator&& __g) |
5763 | { |
5764 | using __distrib_type = uniform_int_distribution<_Size>; |
5765 | using __param_type = typename __distrib_type::param_type; |
5766 | __distrib_type __d{}; |
5767 | _Size __sample_sz = 0; |
5768 | while (__first != __last && __sample_sz != __n) |
5769 | { |
5770 | __out[__sample_sz++] = *__first; |
5771 | ++__first; |
5772 | } |
5773 | for (auto __pop_sz = __sample_sz; __first != __last; |
5774 | ++__first, (void) ++__pop_sz) |
5775 | { |
5776 | const auto __k = __d(__g, __param_type{0, __pop_sz}); |
5777 | if (__k < __n) |
5778 | __out[__k] = *__first; |
5779 | } |
5780 | return __out + __sample_sz; |
5781 | } |
5782 | |
5783 | |
5784 | template<typename _ForwardIterator, typename _OutputIterator, typename _Cat, |
5785 | typename _Size, typename _UniformRandomBitGenerator> |
5786 | _OutputIterator |
5787 | __sample(_ForwardIterator __first, _ForwardIterator __last, |
5788 | forward_iterator_tag, |
5789 | _OutputIterator __out, _Cat, |
5790 | _Size __n, _UniformRandomBitGenerator&& __g) |
5791 | { |
5792 | using __distrib_type = uniform_int_distribution<_Size>; |
5793 | using __param_type = typename __distrib_type::param_type; |
5794 | using _USize = make_unsigned_t<_Size>; |
5795 | using _Gen = remove_reference_t<_UniformRandomBitGenerator>; |
5796 | using __uc_type = common_type_t<typename _Gen::result_type, _USize>; |
5797 | |
5798 | __distrib_type __d{}; |
5799 | _Size __unsampled_sz = std::distance(__first, __last); |
5800 | __n = std::min(__n, __unsampled_sz); |
5801 | |
5802 | |
5803 | |
5804 | |
5805 | const __uc_type __urngrange = __g.max() - __g.min(); |
5806 | if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) |
5807 | |
5808 | |
5809 | { |
5810 | while (__n != 0 && __unsampled_sz >= 2) |
5811 | { |
5812 | const pair<_Size, _Size> __p = |
5813 | __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); |
5814 | |
5815 | --__unsampled_sz; |
5816 | if (__p.first < __n) |
5817 | { |
5818 | *__out++ = *__first; |
5819 | --__n; |
5820 | } |
5821 | |
5822 | ++__first; |
5823 | |
5824 | if (__n == 0) break; |
5825 | |
5826 | --__unsampled_sz; |
5827 | if (__p.second < __n) |
5828 | { |
5829 | *__out++ = *__first; |
5830 | --__n; |
5831 | } |
5832 | |
5833 | ++__first; |
5834 | } |
5835 | } |
5836 | |
5837 | |
5838 | |
5839 | for (; __n != 0; ++__first) |
5840 | if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) |
5841 | { |
5842 | *__out++ = *__first; |
5843 | --__n; |
5844 | } |
5845 | return __out; |
5846 | } |
5847 | |
5848 | #if __cplusplus > 201402L |
5849 | #define __cpp_lib_sample 201603 |
5850 | |
5851 | template<typename _PopulationIterator, typename _SampleIterator, |
5852 | typename _Distance, typename _UniformRandomBitGenerator> |
5853 | _SampleIterator |
5854 | sample(_PopulationIterator __first, _PopulationIterator __last, |
5855 | _SampleIterator __out, _Distance __n, |
5856 | _UniformRandomBitGenerator&& __g) |
5857 | { |
5858 | using __pop_cat = typename |
5859 | std::iterator_traits<_PopulationIterator>::iterator_category; |
5860 | using __samp_cat = typename |
5861 | std::iterator_traits<_SampleIterator>::iterator_category; |
5862 | |
5863 | static_assert( |
5864 | __or_<is_convertible<__pop_cat, forward_iterator_tag>, |
5865 | is_convertible<__samp_cat, random_access_iterator_tag>>::value, |
5866 | "output range must use a RandomAccessIterator when input range" |
5867 | " does not meet the ForwardIterator requirements"); |
5868 | |
5869 | static_assert(is_integral<_Distance>::value, |
5870 | "sample size must be an integer type"); |
5871 | |
5872 | typename iterator_traits<_PopulationIterator>::difference_type __d = __n; |
5873 | return _GLIBCXX_STD_A:: |
5874 | __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d, |
5875 | std::forward<_UniformRandomBitGenerator>(__g)); |
5876 | } |
5877 | #endif // C++17 |
5878 | #endif // C++14 |
5879 | |
5880 | _GLIBCXX_END_NAMESPACE_ALGO |
5881 | _GLIBCXX_END_NAMESPACE_VERSION |
5882 | } |
5883 | |
5884 | #endif /* _STL_ALGO_H */ |