source: stable/2.9/Cbc/src/CbcCutGenerator.cpp @ 2174

Last change on this file since 2174 was 2174, checked in by forrest, 3 years ago

add WEAKEN_CUTS to stable

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 53.8 KB
Line 
1/* $Id: CbcCutGenerator.cpp 2174 2015-03-24 09:57:18Z forrest $ */
2// Copyright (C) 2003, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#if defined(_MSC_VER)
7// Turn off compiler warning about long names
8#  pragma warning(disable:4786)
9#endif
10#include "CbcConfig.h"
11#include <cassert>
12#include <cstdlib>
13#include <cmath>
14#include <cfloat>
15
16#ifdef COIN_HAS_CLP
17#include "OsiClpSolverInterface.hpp"
18#else
19#include "OsiSolverInterface.hpp"
20#endif
21//#define CGL_DEBUG 1
22#ifdef CGL_DEBUG
23#include "OsiRowCutDebugger.hpp"
24#endif
25#include "CbcModel.hpp"
26#include "CbcMessage.hpp"
27#include "CbcCutGenerator.hpp"
28#include "CbcBranchDynamic.hpp"
29#include "CglProbing.hpp"
30#include "CoinTime.hpp"
31
32// Default Constructor
33CbcCutGenerator::CbcCutGenerator ()
34        : timeInCutGenerator_(0.0),
35        model_(NULL),
36        generator_(NULL),
37        generatorName_(NULL),
38        whenCutGenerator_(-1),
39        whenCutGeneratorInSub_(-100),
40        switchOffIfLessThan_(0),
41        depthCutGenerator_(-1),
42        depthCutGeneratorInSub_(-1),
43        inaccuracy_(0),
44        numberTimes_(0),
45        numberCuts_(0),
46        numberElements_(0),
47        numberColumnCuts_(0),
48        numberCutsActive_(0),
49        numberCutsAtRoot_(0),
50        numberActiveCutsAtRoot_(0),
51        numberShortCutsAtRoot_(0),
52        switches_(1),
53        maximumTries_(-1)
54{
55}
56// Normal constructor
57CbcCutGenerator::CbcCutGenerator(CbcModel * model, CglCutGenerator * generator,
58                                 int howOften, const char * name,
59                                 bool normal, bool atSolution,
60                                 bool infeasible, int howOftenInSub,
61                                 int whatDepth, int whatDepthInSub,
62                                 int switchOffIfLessThan)
63        :
64        timeInCutGenerator_(0.0),
65        depthCutGenerator_(whatDepth),
66        depthCutGeneratorInSub_(whatDepthInSub),
67        inaccuracy_(0),
68        numberTimes_(0),
69        numberCuts_(0),
70        numberElements_(0),
71        numberColumnCuts_(0),
72        numberCutsActive_(0),
73        numberCutsAtRoot_(0),
74        numberActiveCutsAtRoot_(0),
75        numberShortCutsAtRoot_(0),
76        switches_(1),
77        maximumTries_(-1)
78{
79    if (howOften < -1900) {
80        setGlobalCuts(true);
81        howOften += 2000;
82    } else if (howOften < -900) {
83        setGlobalCutsAtRoot(true);
84        howOften += 1000;
85    }
86    model_ = model;
87    generator_ = generator->clone();
88    generator_->refreshSolver(model_->solver());
89    setNeedsOptimalBasis(generator_->needsOptimalBasis());
90    whenCutGenerator_ = howOften;
91    whenCutGeneratorInSub_ = howOftenInSub;
92    switchOffIfLessThan_ = switchOffIfLessThan;
93    if (name)
94        generatorName_ = CoinStrdup(name);
95    else
96        generatorName_ = CoinStrdup("Unknown");
97    setNormal(normal);
98    setAtSolution(atSolution);
99    setWhenInfeasible(infeasible);
100}
101
102// Copy constructor
103CbcCutGenerator::CbcCutGenerator ( const CbcCutGenerator & rhs)
104{
105    model_ = rhs.model_;
106    generator_ = rhs.generator_->clone();
107    //generator_->refreshSolver(model_->solver());
108    whenCutGenerator_ = rhs.whenCutGenerator_;
109    whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_;
110    switchOffIfLessThan_ = rhs.switchOffIfLessThan_;
111    depthCutGenerator_ = rhs.depthCutGenerator_;
112    depthCutGeneratorInSub_ = rhs.depthCutGeneratorInSub_;
113    generatorName_ = CoinStrdup(rhs.generatorName_);
114    switches_ = rhs.switches_;
115    maximumTries_ = rhs.maximumTries_;
116    timeInCutGenerator_ = rhs.timeInCutGenerator_;
117    savedCuts_ = rhs.savedCuts_;
118    inaccuracy_ = rhs.inaccuracy_;
119    numberTimes_ = rhs.numberTimes_;
120    numberCuts_ = rhs.numberCuts_;
121    numberElements_ = rhs.numberElements_;
122    numberColumnCuts_ = rhs.numberColumnCuts_;
123    numberCutsActive_ = rhs.numberCutsActive_;
124    numberCutsAtRoot_  = rhs.numberCutsAtRoot_;
125    numberActiveCutsAtRoot_ = rhs.numberActiveCutsAtRoot_;
126    numberShortCutsAtRoot_ = rhs.numberShortCutsAtRoot_;
127}
128
129// Assignment operator
130CbcCutGenerator &
131CbcCutGenerator::operator=( const CbcCutGenerator & rhs)
132{
133    if (this != &rhs) {
134        delete generator_;
135        free(generatorName_);
136        model_ = rhs.model_;
137        generator_ = rhs.generator_->clone();
138        generator_->refreshSolver(model_->solver());
139        whenCutGenerator_ = rhs.whenCutGenerator_;
140        whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_;
141        switchOffIfLessThan_ = rhs.switchOffIfLessThan_;
142        depthCutGenerator_ = rhs.depthCutGenerator_;
143        depthCutGeneratorInSub_ = rhs.depthCutGeneratorInSub_;
144        generatorName_ = CoinStrdup(rhs.generatorName_);
145        switches_ = rhs.switches_;
146        maximumTries_ = rhs.maximumTries_;
147        timeInCutGenerator_ = rhs.timeInCutGenerator_;
148        savedCuts_ = rhs.savedCuts_;
149        inaccuracy_ = rhs.inaccuracy_;
150        numberTimes_ = rhs.numberTimes_;
151        numberCuts_ = rhs.numberCuts_;
152        numberElements_ = rhs.numberElements_;
153        numberColumnCuts_ = rhs.numberColumnCuts_;
154        numberCutsActive_ = rhs.numberCutsActive_;
155        numberCutsAtRoot_  = rhs.numberCutsAtRoot_;
156        numberActiveCutsAtRoot_ = rhs.numberActiveCutsAtRoot_;
157        numberShortCutsAtRoot_ = rhs.numberShortCutsAtRoot_;
158    }
159    return *this;
160}
161
162// Destructor
163CbcCutGenerator::~CbcCutGenerator ()
164{
165    free(generatorName_);
166    delete generator_;
167}
168
169/* This is used to refresh any inforamtion.
170   It also refreshes the solver in the cut generator
171   in case generator wants to do some work
172*/
173void
174CbcCutGenerator::refreshModel(CbcModel * model)
175{
176    model_ = model;
177    // added test - helps if generator not thread safe
178    if (whenCutGenerator_!=-100)
179      generator_->refreshSolver(model_->solver());
180}
181/* Generate cuts for the model data contained in si.
182   The generated cuts are inserted into and returned in the
183   collection of cuts cs.
184*/
185bool
186CbcCutGenerator::generateCuts( OsiCuts & cs , int fullScan, OsiSolverInterface * solver, CbcNode * node)
187{
188    /*
189          Make some decisions about whether we'll generate cuts. First convert
190          whenCutGenerator_ to a set of canonical values for comparison to the node
191          count.
192
193                 0 <    mod 1000000, with a result of 0 forced to 1
194           -99 <= <= 0  convert to 1
195          -100 =        Off, period
196        */
197        int depth;
198    if (node)
199        depth = node->depth();
200    else
201        depth = 0;
202    int howOften = whenCutGenerator_;
203    if (dynamic_cast<CglProbing*>(generator_)) {
204        if (howOften == -100 && model_->doCutsNow(3)) {
205            howOften = 1; // do anyway
206        }
207    }
208    if (howOften == -100)
209        return false;
210    int pass = model_->getCurrentPassNumber() - 1;
211    if (maximumTries_>0) {
212      // howOften means what it says
213      if ((pass%howOften)!=0||depth)
214        return false;
215      else
216        howOften=1;
217    }
218    if (howOften > 0)
219        howOften = howOften % 1000000;
220    else
221        howOften = 1;
222    if (!howOften)
223        howOften = 1;
224    bool returnCode = false;
225    //OsiSolverInterface * solver = model_->solver();
226    // Reset cuts on first pass
227    if (!pass)
228        savedCuts_ = OsiCuts();
229    /*
230          Determine if we should generate cuts based on node count.
231        */
232        bool doThis = (model_->getNodeCount() % howOften) == 0;
233    /*
234          If the user has provided a depth specification, it will override the node
235          count specification.
236        */
237        if (depthCutGenerator_ > 0) {
238        doThis = (depth % depthCutGenerator_) == 0;
239        if (depth < depthCutGenerator_)
240            doThis = true; // and also at top of tree
241    }
242        /*
243          A few magic numbers ...
244
245          The distinction between -100 and 100 for howOften is that we can override 100
246          with fullScan. -100 means no cuts, period. As does the magic number -200 for
247          whenCutGeneratorInSub_.
248        */
249
250    // But turn off if 100
251    if (howOften == 100)
252        doThis = false;
253    // Switch off if special setting
254    if (whenCutGeneratorInSub_ == -200 && model_->parentModel()) {
255        fullScan = 0;
256        doThis = false;
257    }
258    if (fullScan || doThis) {
259        CoinThreadRandom * randomNumberGenerator = NULL;
260#ifdef COIN_HAS_CLP
261        {
262            OsiClpSolverInterface * clpSolver
263            = dynamic_cast<OsiClpSolverInterface *> (solver);
264            if (clpSolver)
265                randomNumberGenerator =
266                    clpSolver->getModelPtr()->randomNumberGenerator();
267        }
268#endif
269        double time1 = 0.0;
270        if (timing())
271            time1 = CoinCpuTime();
272        //#define CBC_DEBUG
273        int numberRowCutsBefore = cs.sizeRowCuts() ;
274        int numberColumnCutsBefore = cs.sizeColCuts() ;
275#ifdef JJF_ZERO
276        int cutsBefore = cs.sizeCuts();
277#endif
278        CglTreeInfo info;
279        info.level = depth;
280        info.pass = pass;
281        info.formulation_rows = model_->numberRowsAtContinuous();
282        info.inTree = node != NULL;
283        info.randomNumberGenerator = randomNumberGenerator;
284        info.options = (globalCutsAtRoot()) ? 8 : 0;
285        if (ineffectualCuts())
286            info.options |= 32;
287        if (globalCuts())
288            info.options |= 16;
289        if (fullScan < 0)
290            info.options |= 128;
291        if (whetherInMustCallAgainMode())
292          info.options |= 1024;
293        // See if we want alternate set of cuts
294        if ((model_->moreSpecialOptions()&16384) != 0)
295            info.options |= 256;
296        if (model_->parentModel())
297            info.options |= 512;
298        // above had &&!model_->parentModel()&&depth<2)
299        incrementNumberTimesEntered();
300        CglProbing* generator =
301            dynamic_cast<CglProbing*>(generator_);
302        //if (!depth&&!pass)
303        //printf("Cut generator %s when %d\n",generatorName_,whenCutGenerator_);
304        if (!generator) {
305            // Pass across model information in case it could be useful
306            //void * saveData = solver->getApplicationData();
307            //solver->setApplicationData(model_);
308            generator_->generateCuts(*solver, cs, info);
309            //solver->setApplicationData(saveData);
310        } else {
311            // Probing - return tight column bounds
312            CglTreeProbingInfo * info2 = model_->probingInfo();
313            bool doCuts = false;
314            if (info2 && !depth) {
315                info2->options = (globalCutsAtRoot()) ? 8 : 0;
316                info2->level = depth;
317                info2->pass = pass;
318                info2->formulation_rows = model_->numberRowsAtContinuous();
319                info2->inTree = node != NULL;
320                info2->randomNumberGenerator = randomNumberGenerator;
321                generator->generateCutsAndModify(*solver, cs, info2);
322                doCuts = true;
323            } else if (depth) {
324                /* The idea behind this is that probing may work in a different
325                   way deep in tree.  So every now and then try various
326                   combinations to see what works.
327                */
328#define TRY_NOW_AND_THEN
329#ifdef TRY_NOW_AND_THEN
330                if ((numberTimes_ == 200 || (numberTimes_ > 200 && (numberTimes_ % 2000) == 0))
331                        && !model_->parentModel() && info.formulation_rows > 200) {
332                    /* In tree, every now and then try various combinations
333                       maxStack, maxProbe (last 5 digits)
334                       123 is special and means CglProbing will try and
335                       be intelligent.
336                    */
337                    int test[] = {
338                        100123,
339                        199999,
340                        200123,
341                        299999,
342                        500123,
343                        599999,
344                        1000123,
345                        1099999,
346                        2000123,
347                        2099999
348                    };
349                    int n = static_cast<int> (sizeof(test) / sizeof(int));
350                    int saveStack = generator->getMaxLook();
351                    int saveNumber = generator->getMaxProbe();
352                    int kr1 = 0;
353                    int kc1 = 0;
354                    int bestStackTree = -1;
355                    int bestNumberTree = -1;
356                    for (int i = 0; i < n; i++) {
357                        //OsiCuts cs2 = cs;
358                        int stack = test[i] / 100000;
359                        int number = test[i] - 100000 * stack;
360                        generator->setMaxLook(stack);
361                        generator->setMaxProbe(number);
362                        int numberRowCutsBefore = cs.sizeRowCuts() ;
363                        int numberColumnCutsBefore = cs.sizeColCuts() ;
364                        generator_->generateCuts(*solver, cs, info);
365                        int numberRowCuts = cs.sizeRowCuts() - numberRowCutsBefore ;
366                        int numberColumnCuts = cs.sizeColCuts() - numberColumnCutsBefore ;
367#ifdef CLP_INVESTIGATE
368                        if (numberRowCuts < kr1 || numberColumnCuts < kc1)
369                            printf("Odd ");
370#endif
371                        if (numberRowCuts > kr1 || numberColumnCuts > kc1) {
372#ifdef CLP_INVESTIGATE
373                            printf("*** ");
374#endif
375                            kr1 = numberRowCuts;
376                            kc1 = numberColumnCuts;
377                            bestStackTree = stack;
378                            bestNumberTree = number;
379                            doCuts = true;
380                        }
381#ifdef CLP_INVESTIGATE
382                        printf("maxStack %d number %d gives %d row cuts and %d column cuts\n",
383                               stack, number, numberRowCuts, numberColumnCuts);
384#endif
385                    }
386                    generator->setMaxLook(saveStack);
387                    generator->setMaxProbe(saveNumber);
388                    if (bestStackTree > 0) {
389                        generator->setMaxLook(bestStackTree);
390                        generator->setMaxProbe(bestNumberTree);
391#ifdef CLP_INVESTIGATE
392                        printf("RRNumber %d -> %d, stack %d -> %d\n",
393                               saveNumber, bestNumberTree, saveStack, bestStackTree);
394#endif
395                    } else {
396                        // no good
397                        generator->setMaxLook(0);
398#ifdef CLP_INVESTIGATE
399                        printf("RRSwitching off number %d -> %d, stack %d -> %d\n",
400                               saveNumber, saveNumber, saveStack, 1);
401#endif
402                    }
403                }
404#endif
405                if (generator->getMaxLook() > 0 && !doCuts) {
406                    generator->generateCutsAndModify(*solver, cs, &info);
407                    doCuts = true;
408                }
409            } else {
410                // at root - don't always do
411                if (pass < 15 || (pass&1) == 0) {
412                    generator->generateCutsAndModify(*solver, cs, &info);
413                    doCuts = true;
414                }
415            }
416            if (doCuts && generator->tightLower()) {
417                // probing may have tightened bounds - check
418                const double * tightLower = generator->tightLower();
419                const double * lower = solver->getColLower();
420                const double * tightUpper = generator->tightUpper();
421                const double * upper = solver->getColUpper();
422                const double * solution = solver->getColSolution();
423                int j;
424                int numberColumns = solver->getNumCols();
425                double primalTolerance = 1.0e-8;
426                const char * tightenBounds = generator->tightenBounds();
427#ifdef CGL_DEBUG
428                const OsiRowCutDebugger * debugger = solver->getRowCutDebugger();
429                if (debugger && debugger->onOptimalPath(*solver)) {
430                    printf("On optimal path CbcCut\n");
431                    int nCols = solver->getNumCols();
432                    const double * optimal = debugger->optimalSolution();
433                    const double * objective = solver->getObjCoefficients();
434                    double objval1 = 0.0, objval2 = 0.0;
435                    for (int i = 0; i < nCols; i++) {
436                        if (!solver->isInteger(i))
437                          continue;
438#if CGL_DEBUG>1
439                        printf("%d %g %g %g %g\n", i, lower[i], solution[i], upper[i], optimal[i]);
440#endif
441                        objval1 += solution[i] * objective[i];
442                        objval2 += optimal[i] * objective[i];
443                        assert(optimal[i] >= lower[i] - 1.0e-5 && optimal[i] <= upper[i] + 1.0e-5);
444                        assert(optimal[i] >= tightLower[i] - 1.0e-5 && optimal[i] <= tightUpper[i] + 1.0e-5);
445                    }
446                    printf("current obj %g, integer %g\n", objval1, objval2);
447                }
448#endif
449                bool feasible = true;
450                if ((model_->getThreadMode()&2) == 0) {
451                    for (j = 0; j < numberColumns; j++) {
452                        if (solver->isInteger(j)) {
453                            if (tightUpper[j] < upper[j]) {
454                                double nearest = floor(tightUpper[j] + 0.5);
455                                //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible
456                                solver->setColUpper(j, nearest);
457                                if (nearest < solution[j] - primalTolerance)
458                                    returnCode = true;
459                            }
460                            if (tightLower[j] > lower[j]) {
461                                double nearest = floor(tightLower[j] + 0.5);
462                                //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible
463                                solver->setColLower(j, nearest);
464                                if (nearest > solution[j] + primalTolerance)
465                                    returnCode = true;
466                            }
467                        } else {
468                            if (upper[j] > lower[j]) {
469                                if (tightUpper[j] == tightLower[j]) {
470                                    // fix
471                                    //if (tightLower[j]!=lower[j])
472                                    solver->setColLower(j, tightLower[j]);
473                                    //if (tightUpper[j]!=upper[j])
474                                    solver->setColUpper(j, tightUpper[j]);
475                                    if (tightLower[j] > solution[j] + primalTolerance ||
476                                            tightUpper[j] < solution[j] - primalTolerance)
477                                        returnCode = true;
478                                } else if (tightenBounds && tightenBounds[j]) {
479                                    solver->setColLower(j, CoinMax(tightLower[j], lower[j]));
480                                    solver->setColUpper(j, CoinMin(tightUpper[j], upper[j]));
481                                    if (tightLower[j] > solution[j] + primalTolerance ||
482                                            tightUpper[j] < solution[j] - primalTolerance)
483                                        returnCode = true;
484                                }
485                            }
486                        }
487                        if (upper[j] < lower[j] - 1.0e-3) {
488                            feasible = false;
489                            break;
490                        }
491                    }
492                } else {
493                    CoinPackedVector lbs;
494                    CoinPackedVector ubs;
495                    int numberChanged = 0;
496                    bool ifCut = false;
497                    for (j = 0; j < numberColumns; j++) {
498                        if (solver->isInteger(j)) {
499                            if (tightUpper[j] < upper[j]) {
500                                double nearest = floor(tightUpper[j] + 0.5);
501                                //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible
502                                ubs.insert(j, nearest);
503                                numberChanged++;
504                                if (nearest < solution[j] - primalTolerance)
505                                    ifCut = true;
506                            }
507                            if (tightLower[j] > lower[j]) {
508                                double nearest = floor(tightLower[j] + 0.5);
509                                //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible
510                                lbs.insert(j, nearest);
511                                numberChanged++;
512                                if (nearest > solution[j] + primalTolerance)
513                                    ifCut = true;
514                            }
515                        } else {
516                            if (upper[j] > lower[j]) {
517                                if (tightUpper[j] == tightLower[j]) {
518                                    // fix
519                                    lbs.insert(j, tightLower[j]);
520                                    ubs.insert(j, tightUpper[j]);
521                                    if (tightLower[j] > solution[j] + primalTolerance ||
522                                            tightUpper[j] < solution[j] - primalTolerance)
523                                        ifCut = true;
524                                } else if (tightenBounds && tightenBounds[j]) {
525                                    lbs.insert(j, CoinMax(tightLower[j], lower[j]));
526                                    ubs.insert(j, CoinMin(tightUpper[j], upper[j]));
527                                    if (tightLower[j] > solution[j] + primalTolerance ||
528                                            tightUpper[j] < solution[j] - primalTolerance)
529                                        ifCut = true;
530                                }
531                            }
532                        }
533                        if (upper[j] < lower[j] - 1.0e-3) {
534                            feasible = false;
535                            break;
536                        }
537                    }
538                    if (numberChanged) {
539                        OsiColCut cc;
540                        cc.setUbs(ubs);
541                        cc.setLbs(lbs);
542                        if (ifCut) {
543                            cc.setEffectiveness(100.0);
544                        } else {
545                            cc.setEffectiveness(1.0e-5);
546                        }
547                        cs.insert(cc);
548                    }
549                }
550                if (!feasible) {
551                    // not feasible -add infeasible cut
552                    OsiRowCut rc;
553                    rc.setLb(COIN_DBL_MAX);
554                    rc.setUb(0.0);
555                    cs.insert(rc);
556                }
557            }
558            //if (!solver->basisIsAvailable())
559            //returnCode=true;
560            if (!returnCode) {
561              // bounds changed but still optimal
562#ifdef COIN_HAS_CLP
563              OsiClpSolverInterface * clpSolver
564                = dynamic_cast<OsiClpSolverInterface *> (solver);
565              if (clpSolver) {
566                clpSolver->setLastAlgorithm(2);
567              }
568#endif
569            }
570#ifdef JJF_ZERO
571            // Pass across info to pseudocosts
572            char * mark = new char[numberColumns];
573            memset(mark, 0, numberColumns);
574            int nLook = generator->numberThisTime();
575            const int * lookedAt = generator->lookedAt();
576            const int * fixedDown = generator->fixedDown();
577            const int * fixedUp = generator->fixedUp();
578            for (j = 0; j < nLook; j++)
579                mark[lookedAt[j]] = 1;
580            int numberObjects = model_->numberObjects();
581            for (int i = 0; i < numberObjects; i++) {
582                CbcSimpleIntegerDynamicPseudoCost * obj1 =
583                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(model_->modifiableObject(i)) ;
584                if (obj1) {
585                    int iColumn = obj1->columnNumber();
586                    if (mark[iColumn])
587                        obj1->setProbingInformation(fixedDown[iColumn], fixedUp[iColumn]);
588                }
589            }
590            delete [] mark;
591#endif
592        }
593        CbcCutModifier * modifier = model_->cutModifier();
594        if (modifier) {
595            int numberRowCutsAfter = cs.sizeRowCuts() ;
596            int k ;
597            int nOdd = 0;
598            //const OsiSolverInterface * solver = model_->solver();
599            for (k = numberRowCutsAfter - 1; k >= numberRowCutsBefore; k--) {
600                OsiRowCut & thisCut = cs.rowCut(k) ;
601                int returnCode = modifier->modify(solver, thisCut);
602                if (returnCode) {
603                    nOdd++;
604                    if (returnCode == 3)
605                        cs.eraseRowCut(k);
606                }
607            }
608            if (nOdd)
609                COIN_DETAIL_PRINT(printf("Cut generator %s produced %d cuts of which %d were modified\n",
610                                         generatorName_, numberRowCutsAfter - numberRowCutsBefore, nOdd));
611        }
612        {
613            // make all row cuts without test for duplicate
614            int numberRowCutsAfter = cs.sizeRowCuts() ;
615            int k ;
616#ifdef CGL_DEBUG
617            const OsiRowCutDebugger * debugger = solver->getRowCutDebugger();
618#endif
619            //#define WEAKEN_CUTS 1
620#ifdef WEAKEN_CUTS
621            const double * lower = solver->getColLower();
622            const double * upper = solver->getColUpper();
623            const double * solution = solver->getColSolution();
624#endif
625            for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
626                OsiRowCut * thisCut = cs.rowCutPtr(k) ;
627#ifdef WEAKEN_CUTS
628                // weaken cut if coefficients not integer
629                double lb=thisCut->lb();
630                double ub=thisCut->ub();
631                if (lb<-1.0e100||ub>1.0e100) {
632                  // normal cut
633                  CoinPackedVector rpv = thisCut->row();
634                  const int n = rpv.getNumElements();
635                  const int * indices = rpv.getIndices();
636                  const double * elements = rpv.getElements();
637                  double bound=0.0;
638                  double sum=0.0;
639                  bool integral=true;
640                  int nInteger=0;
641                  for (int k=0; k<n; k++) {
642                    double value = fabs(elements[k]);
643                    int column=indices[k];
644                    sum += value;
645                    if (value!=floor(value+0.5))
646                      integral=false;
647                    if (solver->isInteger(column)) {
648                      nInteger++;
649                      double largerBound = CoinMax(fabs(lower[column]),
650                                                   fabs(upper[column]));
651                      double solutionBound=fabs(solution[column])+10.0;
652                      bound += CoinMin(largerBound,solutionBound);
653                    }
654                  }
655#if WEAKEN_CUTS ==1
656                  // leave if all 0-1
657                  if (nInteger==bound)
658                    integral=true;
659#elif WEAKEN_CUTS==4||WEAKEN_CUTS==5
660                  // leave if all 0-1
661                  if (nInteger==bound && n < 40)
662                    integral=true;
663#endif
664                  if (!integral) {
665                    double weakenBy=1.0e-7*(bound+sum);
666#if WEAKEN_CUTS==3||WEAKEN_CUTS==5
667                    weakenBy *= 10.0;
668#endif             
669                    if (lb<-1.0e100)
670                      thisCut->setUb(ub+weakenBy);
671                    else
672                      thisCut->setLb(lb-weakenBy);
673                  }
674                }
675#endif
676#ifdef CGL_DEBUG
677                if (debugger && debugger->onOptimalPath(*solver)) {
678                  if(debugger->invalidCut(*thisCut)) {
679                      abort();
680                  }
681                }
682#endif
683                thisCut->mutableRow().setTestForDuplicateIndex(false);
684            }
685        }
686        // Add in saved cuts if violated
687        if (false && !depth) {
688            const double * solution = solver->getColSolution();
689            double primalTolerance = 1.0e-7;
690            int numberCuts = savedCuts_.sizeRowCuts() ;
691            for (int k = numberCuts - 1; k >= 0; k--) {
692                const OsiRowCut * thisCut = savedCuts_.rowCutPtr(k) ;
693                double sum = 0.0;
694                int n = thisCut->row().getNumElements();
695                const int * column = thisCut->row().getIndices();
696                const double * element = thisCut->row().getElements();
697                assert (n);
698                for (int i = 0; i < n; i++) {
699                    double value = element[i];
700                    sum += value * solution[column[i]];
701                }
702                if (sum > thisCut->ub() + primalTolerance) {
703                    sum = sum - thisCut->ub();
704                } else if (sum < thisCut->lb() - primalTolerance) {
705                    sum = thisCut->lb() - sum;
706                } else {
707                    sum = 0.0;
708                }
709                if (sum) {
710                    // add to candidates and take out here
711                    cs.insert(*thisCut);
712                    savedCuts_.eraseRowCut(k);
713                }
714            }
715        }
716        if (!atSolution()) {
717            int numberRowCutsAfter = cs.sizeRowCuts() ;
718            int k ;
719            int nEls = 0;
720            int nCuts = numberRowCutsAfter - numberRowCutsBefore;
721            // Remove NULL cuts!
722            int nNull = 0;
723            const double * solution = solver->getColSolution();
724            bool feasible = true;
725            double primalTolerance = 1.0e-7;
726            int shortCut = (depth) ? -1 : generator_->maximumLengthOfCutInTree();
727            for (k = numberRowCutsAfter - 1; k >= numberRowCutsBefore; k--) {
728                const OsiRowCut * thisCut = cs.rowCutPtr(k) ;
729                double sum = 0.0;
730                if (thisCut->lb() <= thisCut->ub()) {
731                    int n = thisCut->row().getNumElements();
732                    if (n <= shortCut)
733                        numberShortCutsAtRoot_++;
734                    const int * column = thisCut->row().getIndices();
735                    const double * element = thisCut->row().getElements();
736                    if (n <= 0) {
737                        // infeasible cut - give up
738                        feasible = false;
739                        break;
740                    }
741                    nEls += n;
742                    for (int i = 0; i < n; i++) {
743                        double value = element[i];
744                        sum += value * solution[column[i]];
745                    }
746                    if (sum > thisCut->ub() + primalTolerance) {
747                        sum = sum - thisCut->ub();
748                    } else if (sum < thisCut->lb() - primalTolerance) {
749                        sum = thisCut->lb() - sum;
750                    } else {
751                        sum = 0.0;
752                        cs.eraseRowCut(k);
753                        nNull++;
754                    }
755                }
756            }
757            //if (nNull)
758            //printf("%s has %d cuts and %d elements - %d null!\n",generatorName_,
759            //       nCuts,nEls,nNull);
760            numberRowCutsAfter = cs.sizeRowCuts() ;
761            nCuts = numberRowCutsAfter - numberRowCutsBefore;
762            nEls = 0;
763            for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
764                const OsiRowCut * thisCut = cs.rowCutPtr(k) ;
765                int n = thisCut->row().getNumElements();
766                nEls += n;
767            }
768            //printf("%s has %d cuts and %d elements\n",generatorName_,
769            //     nCuts,nEls);
770            int nElsNow = solver->getMatrixByCol()->getNumElements();
771            int numberColumns = solver->getNumCols();
772            int numberRows = solver->getNumRows();
773            //double averagePerRow = static_cast<double>(nElsNow)/
774            //static_cast<double>(numberRows);
775            int nAdd;
776            int nAdd2;
777            int nReasonable;
778            if (!model_->parentModel() && depth < 2) {
779                if (inaccuracy_ < 3) {
780                    nAdd = 10000;
781                    if (pass > 0 && numberColumns > -500)
782                        nAdd = CoinMin(nAdd, nElsNow + 2 * numberRows);
783                } else {
784                    nAdd = 10000;
785                    if (pass > 0)
786                        nAdd = CoinMin(nAdd, nElsNow + 2 * numberRows);
787                }
788                nAdd2 = 5 * numberColumns;
789                nReasonable = CoinMax(nAdd2, nElsNow / 8 + nAdd);
790                if (!depth && !pass) {
791                    // allow more
792                    nAdd += nElsNow / 2;
793                    nAdd2 += nElsNow / 2;
794                    nReasonable += nElsNow / 2;
795                }
796                //if (!depth&&ineffectualCuts())
797                //nReasonable *= 2;
798            } else {
799                nAdd = 200;
800                nAdd2 = 2 * numberColumns;
801                nReasonable = CoinMax(nAdd2, nElsNow / 8 + nAdd);
802            }
803            //#define UNS_WEIGHT 0.1
804#ifdef UNS_WEIGHT
805            const double * colLower = solver->getColLower();
806            const double * colUpper = solver->getColUpper();
807#endif
808            if (/*nEls>CoinMax(nAdd2,nElsNow/8+nAdd)*/nCuts && feasible) {
809                //printf("need to remove cuts\n");
810                // just add most effective
811#ifndef JJF_ONE
812                int nDelete = nEls - nReasonable;
813
814                nElsNow = nEls;
815                double * sort = new double [nCuts];
816                int * which = new int [nCuts];
817                // For parallel cuts
818                double * element2 = new double [numberColumns];
819                //#define USE_OBJECTIVE 2
820#ifdef USE_OBJECTIVE
821                const double *objective = solver->getObjCoefficients() ;
822#if USE_OBJECTIVE>1
823                double objNorm = 0.0;
824                for (int i = 0; i < numberColumns; i++)
825                    objNorm += objective[i] * objective[i];
826                if (objNorm)
827                    objNorm = 1.0 / sqrt(objNorm);
828                else
829                    objNorm = 1.0;
830                objNorm *= 0.01; // downgrade
831#endif
832#endif
833                CoinZeroN(element2, numberColumns);
834                for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
835                    const OsiRowCut * thisCut = cs.rowCutPtr(k) ;
836                    double sum = 0.0;
837                    if (thisCut->lb() <= thisCut->ub()) {
838                        int n = thisCut->row().getNumElements();
839                        const int * column = thisCut->row().getIndices();
840                        const double * element = thisCut->row().getElements();
841                        assert (n);
842#ifdef UNS_WEIGHT
843                        double normU = 0.0;
844                        double norm = 1.0e-3;
845                        int nU = 0;
846                        for (int i = 0; i < n; i++) {
847                            double value = element[i];
848                            int iColumn = column[i];
849                            double solValue = solution[iColumn];
850                            sum += value * solValue;
851                            value *= value;
852                            norm += value;
853                            if (solValue > colLower[iColumn] + 1.0e-6 &&
854                                    solValue < colUpper[iColumn] - 1.0e-6) {
855                                normU += value;
856                                nU++;
857                            }
858                        }
859#ifdef JJF_ZERO
860                        int nS = n - nU;
861                        if (numberColumns > 20000) {
862                            if (nS > 50) {
863                                double ratio = 50.0 / nS;
864                                normU /= ratio;
865                            }
866                        }
867#endif
868                        norm += UNS_WEIGHT * (normU - norm);
869#else
870                        double norm = 1.0e-3;
871#ifdef USE_OBJECTIVE
872                        double obj = 0.0;
873#endif
874                        for (int i = 0; i < n; i++) {
875                            int iColumn = column[i];
876                            double value = element[i];
877                            sum += value * solution[iColumn];
878                            norm += value * value;
879#ifdef USE_OBJECTIVE
880                            obj += value * objective[iColumn];
881#endif
882                        }
883#endif
884                        if (sum > thisCut->ub()) {
885                            sum = sum - thisCut->ub();
886                        } else if (sum < thisCut->lb()) {
887                            sum = thisCut->lb() - sum;
888                        } else {
889                            sum = 0.0;
890                        }
891#ifdef USE_OBJECTIVE
892                        if (sum) {
893#if USE_OBJECTIVE==1
894                            obj = CoinMax(1.0e-6, fabs(obj));
895                            norm = sqrt(obj * norm);
896                            //sum += fabs(obj)*invObjNorm;
897                            //printf("sum %g norm %g normobj %g invNorm %g mod %g\n",
898                            //     sum,norm,obj,invObjNorm,obj*invObjNorm);
899                            // normalize
900                            sum /= sqrt(norm);
901#else
902                            // normalize
903                            norm = 1.0 / sqrt(norm);
904                            sum = (sum + objNorm * obj) * norm;
905#endif
906                        }
907#else
908                        // normalize
909                        sum /= sqrt(norm);
910#endif
911                        //sum /= pow(norm,0.3);
912                        // adjust for length
913                        //sum /= pow(reinterpret_cast<double>(n),0.2);
914                        //sum /= sqrt((double) n);
915                        // randomize
916                        //double randomNumber =
917                        //model_->randomNumberGenerator()->randomDouble();
918                        //sum *= (0.5+randomNumber);
919                    } else {
920                        // keep
921                        sum = COIN_DBL_MAX;
922                    }
923                    sort[k-numberRowCutsBefore] = sum;
924                    which[k-numberRowCutsBefore] = k;
925                }
926                CoinSort_2(sort, sort + nCuts, which);
927                // Now see which ones are too similar
928                int nParallel = 0;
929                double testValue = (depth > 1) ? 0.99 : 0.999999;
930                for (k = 0; k < nCuts; k++) {
931                    int j = which[k];
932                    const OsiRowCut * thisCut = cs.rowCutPtr(j) ;
933                    if (thisCut->lb() > thisCut->ub())
934                        break; // cut is infeasible
935                    int n = thisCut->row().getNumElements();
936                    const int * column = thisCut->row().getIndices();
937                    const double * element = thisCut->row().getElements();
938                    assert (n);
939                    double norm = 0.0;
940                    double lb = thisCut->lb();
941                    double ub = thisCut->ub();
942                    for (int i = 0; i < n; i++) {
943                        double value = element[i];
944                        element2[column[i]] = value;
945                        norm += value * value;
946                    }
947                    int kkk = CoinMin(nCuts, k + 5);
948                    for (int kk = k + 1; kk < kkk; kk++) {
949                        int jj = which[kk];
950                        const OsiRowCut * thisCut2 = cs.rowCutPtr(jj) ;
951                        if (thisCut2->lb() > thisCut2->ub())
952                            break; // cut is infeasible
953                        int nB = thisCut2->row().getNumElements();
954                        const int * columnB = thisCut2->row().getIndices();
955                        const double * elementB = thisCut2->row().getElements();
956                        assert (nB);
957                        double normB = 0.0;
958                        double product = 0.0;
959                        for (int i = 0; i < nB; i++) {
960                            double value = elementB[i];
961                            normB += value * value;
962                            product += value * element2[columnB[i]];
963                        }
964                        if (product > 0.0 && product*product > testValue*norm*normB) {
965                            bool parallel = true;
966                            double lbB = thisCut2->lb();
967                            double ubB = thisCut2->ub();
968                            if ((lb < -1.0e20 && lbB > -1.0e20) ||
969                                    (lbB < -1.0e20 && lb > -1.0e20))
970                                parallel = false;
971                            double tolerance;
972                            tolerance = CoinMax(fabs(lb), fabs(lbB)) + 1.0e-6;
973                            if (fabs(lb - lbB) > tolerance)
974                                parallel = false;
975                            if ((ub > 1.0e20 && ubB < 1.0e20) ||
976                                    (ubB > 1.0e20 && ub < 1.0e20))
977                                parallel = false;
978                            tolerance = CoinMax(fabs(ub), fabs(ubB)) + 1.0e-6;
979                            if (fabs(ub - ubB) > tolerance)
980                                parallel = false;
981                            if (parallel) {
982                                nParallel++;
983                                sort[k] = 0.0;
984                                break;
985                            }
986                        }
987                    }
988                    for (int i = 0; i < n; i++) {
989                        element2[column[i]] = 0.0;
990                    }
991                }
992                delete [] element2;
993                CoinSort_2(sort, sort + nCuts, which);
994                k = 0;
995                while (nDelete > 0 || !sort[k]) {
996                    int iCut = which[k];
997                    const OsiRowCut * thisCut = cs.rowCutPtr(iCut) ;
998                    int n = thisCut->row().getNumElements();
999                    // may be best, just to save if short
1000                    if (false && n && sort[k]) {
1001                        // add to saved cuts
1002                        savedCuts_.insert(*thisCut);
1003                    }
1004                    nDelete -= n;
1005                    k++;
1006                    if (k >= nCuts)
1007                        break;
1008                }
1009                std::sort(which, which + k);
1010                k--;
1011                for (; k >= 0; k--) {
1012                    cs.eraseRowCut(which[k]);
1013                }
1014                delete [] sort;
1015                delete [] which;
1016                numberRowCutsAfter = cs.sizeRowCuts() ;
1017#else
1018                double * norm = new double [nCuts];
1019                int * which = new int [2*nCuts];
1020                double * score = new double [nCuts];
1021                double * ortho = new double [nCuts];
1022                int nIn = 0;
1023                int nOut = nCuts;
1024                // For parallel cuts
1025                double * element2 = new double [numberColumns];
1026                const double *objective = solver->getObjCoefficients() ;
1027                double objNorm = 0.0;
1028                for (int i = 0; i < numberColumns; i++)
1029                    objNorm += objective[i] * objective[i];
1030                if (objNorm)
1031                    objNorm = 1.0 / sqrt(objNorm);
1032                else
1033                    objNorm = 1.0;
1034                objNorm *= 0.1; // weight of 0.1
1035                CoinZeroN(element2, numberColumns);
1036                int numberRowCuts = numberRowCutsAfter - numberRowCutsBefore;
1037                int iBest = -1;
1038                double best = 0.0;
1039                int nPossible = 0;
1040                double testValue = (depth > 1) ? 0.7 : 0.5;
1041                for (k = 0; k < numberRowCuts; k++) {
1042                    const OsiRowCut * thisCut = cs.rowCutPtr(k + numberRowCutsBefore) ;
1043                    double sum = 0.0;
1044                    if (thisCut->lb() <= thisCut->ub()) {
1045                        int n = thisCut->row().getNumElements();
1046                        const int * column = thisCut->row().getIndices();
1047                        const double * element = thisCut->row().getElements();
1048                        assert (n);
1049                        double normThis = 1.0e-6;
1050                        double obj = 0.0;
1051                        for (int i = 0; i < n; i++) {
1052                            int iColumn = column[i];
1053                            double value = element[i];
1054                            sum += value * solution[iColumn];
1055                            normThis += value * value;
1056                            obj += value * objective[iColumn];
1057                        }
1058                        if (sum > thisCut->ub()) {
1059                            sum = sum - thisCut->ub();
1060                        } else if (sum < thisCut->lb()) {
1061                            sum = thisCut->lb() - sum;
1062                        } else {
1063                            sum = 0.0;
1064                        }
1065                        if (sum) {
1066                            normThis = 1.0 / sqrt(normThis);
1067                            norm[k] = normThis;
1068                            sum *= normThis;
1069                            obj *= normThis;
1070                            score[k] = sum + obj * objNorm;
1071                            ortho[k] = 1.0;
1072                        }
1073                    } else {
1074                        // keep and discard others
1075                        nIn = 1;
1076                        which[0] = k;
1077                        for (int j = 0; j < numberRowCuts; j++) {
1078                            if (j != k)
1079                                which[nOut++] = j;
1080                        }
1081                        iBest = -1;
1082                        break;
1083                    }
1084                    if (sum) {
1085                        if (score[k] > best) {
1086                            best = score[k];
1087                            iBest = nPossible;
1088                        }
1089                        which[nPossible++] = k;
1090                    } else {
1091                        which[nOut++] = k;
1092                    }
1093                }
1094                while (iBest >= 0) {
1095                    int kBest = which[iBest];
1096                    int j = which[nIn];
1097                    which[iBest] = j;
1098                    which[nIn++] = kBest;
1099                    const OsiRowCut * thisCut = cs.rowCutPtr(kBest + numberRowCutsBefore) ;
1100                    int n = thisCut->row().getNumElements();
1101                    nReasonable -= n;
1102                    if (nReasonable <= 0) {
1103                        for (k = nIn; k < nPossible; k++)
1104                            which[nOut++] = which[k];
1105                        break;
1106                    }
1107                    // Now see which ones are too similar and choose next
1108                    iBest = -1;
1109                    best = 0.0;
1110                    int nOld = nPossible;
1111                    nPossible = nIn;
1112                    const int * column = thisCut->row().getIndices();
1113                    const double * element = thisCut->row().getElements();
1114                    assert (n);
1115                    double normNew = norm[kBest];
1116                    for (int i = 0; i < n; i++) {
1117                        double value = element[i];
1118                        element2[column[i]] = value;
1119                    }
1120                    for (int j = nIn; j < nOld; j++) {
1121                        k = which[j];
1122                        const OsiRowCut * thisCut2 = cs.rowCutPtr(k + numberRowCutsBefore) ;
1123                        int nB = thisCut2->row().getNumElements();
1124                        const int * columnB = thisCut2->row().getIndices();
1125                        const double * elementB = thisCut2->row().getElements();
1126                        assert (nB);
1127                        double normB = norm[k];
1128                        double product = 0.0;
1129                        for (int i = 0; i < nB; i++) {
1130                            double value = elementB[i];
1131                            product += value * element2[columnB[i]];
1132                        }
1133                        double orthoScore = 1.0 - product * normNew * normB;
1134                        if (orthoScore >= testValue) {
1135                            ortho[k] = CoinMin(orthoScore, ortho[k]);
1136                            double test = score[k] + ortho[k];
1137                            if (test > best) {
1138                                best = score[k];
1139                                iBest = nPossible;
1140                            }
1141                            which[nPossible++] = k;
1142                        } else {
1143                            which[nOut++] = k;
1144                        }
1145                    }
1146                    for (int i = 0; i < n; i++) {
1147                        element2[column[i]] = 0.0;
1148                    }
1149                }
1150                delete [] score;
1151                delete [] ortho;
1152                std::sort(which + nCuts, which + nOut);
1153                k = nOut - 1;
1154                for (; k >= nCuts; k--) {
1155                    cs.eraseRowCut(which[k] + numberRowCutsBefore);
1156                }
1157                delete [] norm;
1158                delete [] which;
1159                numberRowCutsAfter = cs.sizeRowCuts() ;
1160#endif
1161            }
1162        }
1163#ifdef CBC_DEBUG
1164        {
1165            int numberRowCutsAfter = cs.sizeRowCuts() ;
1166            int k ;
1167            int nBad = 0;
1168            for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
1169                OsiRowCut thisCut = cs.rowCut(k) ;
1170                if (thisCut.lb() > thisCut.ub() ||
1171                        thisCut.lb() > 1.0e8 ||
1172                        thisCut.ub() < -1.0e8)
1173                    printf("cut from %s has bounds %g and %g!\n",
1174                           generatorName_, thisCut.lb(), thisCut.ub());
1175                if (thisCut.lb() <= thisCut.ub()) {
1176                    /* check size of elements.
1177                       We can allow smaller but this helps debug generators as it
1178                       is unsafe to have small elements */
1179                    int n = thisCut.row().getNumElements();
1180                    const int * column = thisCut.row().getIndices();
1181                    const double * element = thisCut.row().getElements();
1182                    assert (n);
1183                    for (int i = 0; i < n; i++) {
1184                        double value = element[i];
1185                        if (fabs(value) <= 1.0e-12 || fabs(value) >= 1.0e20)
1186                            nBad++;
1187                    }
1188                }
1189                if (nBad)
1190                    printf("Cut generator %s produced %d cuts of which %d had tiny or large elements\n",
1191                           generatorName_, numberRowCutsAfter - numberRowCutsBefore, nBad);
1192            }
1193        }
1194#endif
1195        int numberRowCutsAfter = cs.sizeRowCuts() ;
1196        int numberColumnCutsAfter = cs.sizeColCuts() ;
1197        if (numberRowCutsBefore < numberRowCutsAfter) {
1198            for (int k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
1199                OsiRowCut thisCut = cs.rowCut(k) ;
1200                int n = thisCut.row().getNumElements();
1201                numberElements_ += n;
1202            }
1203#ifdef JJF_ZERO
1204            printf("generator %s generated %d row cuts\n",
1205                   generatorName_, numberRowCutsAfter - numberRowCutsBefore);
1206#endif
1207            numberCuts_ += numberRowCutsAfter - numberRowCutsBefore;
1208        }
1209        if (numberColumnCutsBefore < numberColumnCutsAfter) {
1210#ifdef JJF_ZERO
1211            printf("generator %s generated %d column cuts\n",
1212                   generatorName_, numberColumnCutsAfter - numberColumnCutsBefore);
1213#endif
1214            numberColumnCuts_ += numberColumnCutsAfter - numberColumnCutsBefore;
1215        }
1216        if (timing())
1217            timeInCutGenerator_ += CoinCpuTime() - time1;
1218        // switch off if first time and no good
1219        if (node == NULL && !pass ) {
1220            if (numberRowCutsAfter - numberRowCutsBefore
1221                < switchOffIfLessThan_ /*&& numberCuts_ < switchOffIfLessThan_*/) {
1222              // switch off
1223              maximumTries_ = 0;
1224              whenCutGenerator_=-100;
1225              //whenCutGenerator_ = -100;
1226              //whenCutGeneratorInSub_ = -200;
1227            }
1228        }
1229        if (maximumTries_>0) {
1230          maximumTries_--;
1231          if (!maximumTries_) 
1232            whenCutGenerator_=-100;
1233        }
1234    }
1235    return returnCode;
1236}
1237void
1238CbcCutGenerator::setHowOften(int howOften)
1239{
1240
1241    if (howOften >= 1000000) {
1242        // leave Probing every SCANCUTS_PROBING
1243        howOften = howOften % 1000000;
1244        CglProbing* generator =
1245            dynamic_cast<CglProbing*>(generator_);
1246
1247        if (generator && howOften > SCANCUTS_PROBING)
1248            howOften = SCANCUTS_PROBING + 1000000;
1249        else
1250            howOften += 1000000;
1251    }
1252    whenCutGenerator_ = howOften;
1253}
1254void
1255CbcCutGenerator::setWhatDepth(int value)
1256{
1257    depthCutGenerator_ = value;
1258}
1259void
1260CbcCutGenerator::setWhatDepthInSub(int value)
1261{
1262    depthCutGeneratorInSub_ = value;
1263}
1264// Add in statistics from other
1265void 
1266CbcCutGenerator::addStatistics(const CbcCutGenerator * other)
1267{
1268  // Time in cut generator
1269  timeInCutGenerator_ += other->timeInCutGenerator_;
1270  // Number times cut generator entered
1271  numberTimes_ += other->numberTimes_;
1272  // Total number of cuts added
1273  numberCuts_ += other->numberCuts_;
1274  // Total number of elements added
1275  numberElements_ += other->numberElements_;
1276  // Total number of column cuts added
1277  numberColumnCuts_ += other->numberColumnCuts_;
1278  // Total number of cuts active after (at end of n cut passes at each node)
1279  numberCutsActive_ += other->numberCutsActive_;
1280  // Number of cuts generated at root
1281  numberCutsAtRoot_ += other->numberCutsAtRoot_;
1282  // Number of cuts active at root
1283  numberActiveCutsAtRoot_ += other->numberActiveCutsAtRoot_;
1284  // Number of short cuts at root
1285  numberShortCutsAtRoot_ += other->numberShortCutsAtRoot_;
1286}
1287// Scale back statistics by factor
1288void 
1289CbcCutGenerator::scaleBackStatistics(int factor)
1290{
1291  // leave time
1292  // Number times cut generator entered
1293  numberTimes_ = (numberTimes_+factor-1)/factor;
1294  // Total number of cuts added
1295  numberCuts_ = (numberCuts_+factor-1)/factor;
1296  // Total number of elements added
1297  numberElements_ = (numberElements_+factor-1)/factor;
1298  // Total number of column cuts added
1299  numberColumnCuts_ = (numberColumnCuts_+factor-1)/factor;
1300  // Total number of cuts active after (at end of n cut passes at each node)
1301  numberCutsActive_ = (numberCutsActive_+factor-1)/factor;
1302  // Number of cuts generated at root
1303  numberCutsAtRoot_ = (numberCutsAtRoot_+factor-1)/factor;
1304  // Number of cuts active at root
1305  numberActiveCutsAtRoot_ = (numberActiveCutsAtRoot_+factor-1)/factor;
1306  // Number of short cuts at root
1307  numberShortCutsAtRoot_ = (numberShortCutsAtRoot_+factor-1)/factor;
1308}
1309// Create C++ lines to get to current state
1310void
1311CbcCutGenerator::generateTuning( FILE * fp)
1312{
1313    fprintf(fp, "// Cbc tuning for generator %s\n", generatorName_);
1314    fprintf(fp, "   generator->setHowOften(%d);\n", whenCutGenerator_);
1315    fprintf(fp, "   generator->setSwitchOffIfLessThan(%d);\n", switchOffIfLessThan_);
1316    fprintf(fp, "   generator->setWhatDepth(%d);\n", depthCutGenerator_);
1317    fprintf(fp, "   generator->setInaccuracy(%d);\n", inaccuracy_);
1318    if (timing())
1319        fprintf(fp, "   generator->setTiming(true);\n");
1320    if (normal())
1321        fprintf(fp, "   generator->setNormal(true);\n");
1322    if (atSolution())
1323        fprintf(fp, "   generator->setAtSolution(true);\n");
1324    if (whenInfeasible())
1325        fprintf(fp, "   generator->setWhenInfeasible(true);\n");
1326    if (needsOptimalBasis())
1327        fprintf(fp, "   generator->setNeedsOptimalBasis(true);\n");
1328    if (mustCallAgain())
1329        fprintf(fp, "   generator->setMustCallAgain(true);\n");
1330    if (whetherToUse())
1331        fprintf(fp, "   generator->setWhetherToUse(true);\n");
1332}
1333
1334
1335
Note: See TracBrowser for help on using the repository browser.