source: stable/2.7/Cbc/src/CbcHeuristicLocal.cpp @ 1675

Last change on this file since 1675 was 1675, checked in by stefan, 8 years ago

sync with trunk rev1674

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.6 KB
Line 
1/* $Id: CbcHeuristicLocal.cpp 1675 2011-06-19 17:23:14Z stefan $ */
2// Copyright (C) 2002, 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 <cassert>
11#include <cstdlib>
12#include <cmath>
13#include <cfloat>
14
15#include "OsiSolverInterface.hpp"
16#include "CbcModel.hpp"
17#include "CbcMessage.hpp"
18#include "CbcHeuristicLocal.hpp"
19#include "CbcBranchActual.hpp"
20#include "CbcStrategy.hpp"
21#include "CglPreProcess.hpp"
22
23// Default Constructor
24CbcHeuristicLocal::CbcHeuristicLocal()
25        : CbcHeuristic()
26{
27    numberSolutions_ = 0;
28    swap_ = 0;
29    used_ = NULL;
30    lastRunDeep_ = -1000000;
31}
32
33// Constructor with model - assumed before cuts
34
35CbcHeuristicLocal::CbcHeuristicLocal(CbcModel & model)
36        : CbcHeuristic(model)
37{
38    numberSolutions_ = 0;
39    swap_ = 0;
40    lastRunDeep_ = -1000000;
41    // Get a copy of original matrix
42    assert(model.solver());
43    if (model.solver()->getNumRows()) {
44        matrix_ = *model.solver()->getMatrixByCol();
45    }
46    int numberColumns = model.solver()->getNumCols();
47    used_ = new int[numberColumns];
48    memset(used_, 0, numberColumns*sizeof(int));
49}
50
51// Destructor
52CbcHeuristicLocal::~CbcHeuristicLocal ()
53{
54    delete [] used_;
55}
56
57// Clone
58CbcHeuristic *
59CbcHeuristicLocal::clone() const
60{
61    return new CbcHeuristicLocal(*this);
62}
63// Create C++ lines to get to current state
64void
65CbcHeuristicLocal::generateCpp( FILE * fp)
66{
67    CbcHeuristicLocal other;
68    fprintf(fp, "0#include \"CbcHeuristicLocal.hpp\"\n");
69    fprintf(fp, "3  CbcHeuristicLocal heuristicLocal(*cbcModel);\n");
70    CbcHeuristic::generateCpp(fp, "heuristicLocal");
71    if (swap_ != other.swap_)
72        fprintf(fp, "3  heuristicLocal.setSearchType(%d);\n", swap_);
73    else
74        fprintf(fp, "4  heuristicLocal.setSearchType(%d);\n", swap_);
75    fprintf(fp, "3  cbcModel->addHeuristic(&heuristicLocal);\n");
76}
77
78// Copy constructor
79CbcHeuristicLocal::CbcHeuristicLocal(const CbcHeuristicLocal & rhs)
80        :
81        CbcHeuristic(rhs),
82        matrix_(rhs.matrix_),
83        numberSolutions_(rhs.numberSolutions_),
84        swap_(rhs.swap_)
85{
86    if (model_ && rhs.used_) {
87        int numberColumns = model_->solver()->getNumCols();
88        used_ = CoinCopyOfArray(rhs.used_, numberColumns);
89    } else {
90        used_ = NULL;
91    }
92}
93
94// Assignment operator
95CbcHeuristicLocal &
96CbcHeuristicLocal::operator=( const CbcHeuristicLocal & rhs)
97{
98    if (this != &rhs) {
99        CbcHeuristic::operator=(rhs);
100        matrix_ = rhs.matrix_;
101        numberSolutions_ = rhs.numberSolutions_;
102        swap_ = rhs.swap_;
103        delete [] used_;
104        if (model_ && rhs.used_) {
105            int numberColumns = model_->solver()->getNumCols();
106            used_ = CoinCopyOfArray(rhs.used_, numberColumns);
107        } else {
108            used_ = NULL;
109        }
110    }
111    return *this;
112}
113
114// Resets stuff if model changes
115void
116CbcHeuristicLocal::resetModel(CbcModel * /*model*/)
117{
118    //CbcHeuristic::resetModel(model);
119    delete [] used_;
120    if (model_ && used_) {
121        int numberColumns = model_->solver()->getNumCols();
122        used_ = new int[numberColumns];
123        memset(used_, 0, numberColumns*sizeof(int));
124    } else {
125        used_ = NULL;
126    }
127}
128/*
129  Run a mini-BaB search after fixing all variables not marked as used by
130  solution(). (See comments there for semantics.)
131
132  Return values are:
133    1: smallBranchAndBound found a solution
134    0: everything else
135
136  The degree of overload as return codes from smallBranchAndBound are folded
137  into 0 is such that it's impossible to distinguish return codes that really
138  require attention from a simple `nothing of interest'.
139*/
140// This version fixes stuff and does IP
141int
142CbcHeuristicLocal::solutionFix(double & objectiveValue,
143                               double * newSolution,
144                               const int * /*keep*/)
145{
146/*
147  If when is set to off (0), or set to root (1) and we're not at the root,
148  return. If this heuristic discovered the current solution, don't continue.
149*/
150
151    numCouldRun_++;
152    // See if to do
153    if (!when() || (when() == 1 && model_->phase() != 1))
154        return 0; // switched off
155    // Don't do if it was this heuristic which found solution!
156    if (this == model_->lastHeuristic())
157        return 0;
158/*
159  Load up a new solver with the solution.
160
161  Why continuousSolver(), as opposed to solver()?
162*/
163    OsiSolverInterface * newSolver = model_->continuousSolver()->clone();
164    const double * colLower = newSolver->getColLower();
165    //const double * colUpper = newSolver->getColUpper();
166
167    int numberIntegers = model_->numberIntegers();
168    const int * integerVariable = model_->integerVariable();
169/*
170  The net effect here is that anything that hasn't moved from its lower bound
171  will be fixed at lower bound.
172
173  See comments in solution() w.r.t. asymmetric treatment of upper and lower
174  bounds.
175*/
176
177    int i;
178    int nFix = 0;
179    for (i = 0; i < numberIntegers; i++) {
180        int iColumn = integerVariable[i];
181        const OsiObject * object = model_->object(i);
182        // get original bounds
183        double originalLower;
184        double originalUpper;
185        getIntegerInformation( object, originalLower, originalUpper);
186        newSolver->setColLower(iColumn, CoinMax(colLower[iColumn], originalLower));
187        if (!used_[iColumn]) {
188            newSolver->setColUpper(iColumn, colLower[iColumn]);
189            nFix++;
190        }
191    }
192/*
193  Try a `small' branch-and-bound search. The notion here is that we've fixed a
194  lot of variables and reduced the amount of `free' problem to a point where a
195  small BaB search will suffice to fully explore the remaining problem. This
196  routine will execute integer presolve, then call branchAndBound to do the
197  actual search.
198*/
199    int returnCode = 0;
200#ifdef CLP_INVESTIGATE2
201    printf("Fixing %d out of %d (%d continuous)\n",
202           nFix, numberIntegers, newSolver->getNumCols() - numberIntegers);
203#endif
204    if (nFix*10 <= numberIntegers) {
205        // see if we can fix more
206        int * which = new int [2*(numberIntegers-nFix)];
207        int * sort = which + (numberIntegers - nFix);
208        int n = 0;
209        for (i = 0; i < numberIntegers; i++) {
210            int iColumn = integerVariable[i];
211            if (used_[iColumn]) {
212                which[n] = iColumn;
213                sort[n++] = used_[iColumn];
214            }
215        }
216        CoinSort_2(sort, sort + n, which);
217        // only half fixed in total
218        n = CoinMin(n, numberIntegers / 2 - nFix);
219        int allow = CoinMax(numberSolutions_ - 2, sort[0]);
220        int nFix2 = 0;
221        for (i = 0; i < n; i++) {
222            int iColumn = integerVariable[i];
223            if (used_[iColumn] <= allow) {
224                newSolver->setColUpper(iColumn, colLower[iColumn]);
225                nFix2++;
226            } else {
227                break;
228            }
229        }
230        delete [] which;
231        nFix += nFix2;
232#ifdef CLP_INVESTIGATE2
233        printf("Number fixed increased from %d to %d\n",
234               nFix - nFix2, nFix);
235#endif
236    }
237    if (nFix*10 > numberIntegers) {
238        returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, objectiveValue,
239                                         objectiveValue, "CbcHeuristicLocal");
240 /*
241  -2 is return due to user event, and -1 is overloaded with what look to be
242  two contradictory meanings.
243*/
244       if (returnCode < 0) {
245            returnCode = 0; // returned on size
246            int numberColumns = newSolver->getNumCols();
247            int numberContinuous = numberColumns - numberIntegers;
248            if (numberContinuous > 2*numberIntegers &&
249                    nFix*10 < numberColumns) {
250#define LOCAL_FIX_CONTINUOUS
251#ifdef LOCAL_FIX_CONTINUOUS
252                //const double * colUpper = newSolver->getColUpper();
253                const double * colLower = newSolver->getColLower();
254                int nAtLb = 0;
255                //double sumDj=0.0;
256                const double * dj = newSolver->getReducedCost();
257                double direction = newSolver->getObjSense();
258                for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
259                    if (!newSolver->isInteger(iColumn)) {
260                        if (!used_[iColumn]) {
261                            //double djValue = dj[iColumn]*direction;
262                            nAtLb++;
263                            //sumDj += djValue;
264                        }
265                    }
266                }
267                if (nAtLb) {
268                    // fix some continuous
269                    double * sort = new double[nAtLb];
270                    int * which = new int [nAtLb];
271                    //double threshold = CoinMax((0.01*sumDj)/static_cast<double>(nAtLb),1.0e-6);
272                    int nFix2 = 0;
273                    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
274                        if (!newSolver->isInteger(iColumn)) {
275                            if (!used_[iColumn]) {
276                                double djValue = dj[iColumn] * direction;
277                                if (djValue > 1.0e-6) {
278                                    sort[nFix2] = -djValue;
279                                    which[nFix2++] = iColumn;
280                                }
281                            }
282                        }
283                    }
284                    CoinSort_2(sort, sort + nFix2, which);
285                    int divisor = 2;
286                    nFix2 = CoinMin(nFix2, (numberColumns - nFix) / divisor);
287                    for (int i = 0; i < nFix2; i++) {
288                        int iColumn = which[i];
289                        newSolver->setColUpper(iColumn, colLower[iColumn]);
290                    }
291                    delete [] sort;
292                    delete [] which;
293#ifdef CLP_INVESTIGATE2
294                    printf("%d integers have zero value, and %d continuous fixed at lb\n",
295                           nFix, nFix2);
296#endif
297                    returnCode = smallBranchAndBound(newSolver,
298                                                     numberNodes_, newSolution,
299                                                     objectiveValue,
300                                                     objectiveValue, "CbcHeuristicLocal");
301                    if (returnCode < 0)
302                        returnCode = 0; // returned on size
303                }
304#endif
305            }
306        }
307    }
308/*
309  If the result is complete exploration with a solution (3) or proven
310  infeasibility (2), we could generate a cut (the AI folks would call it a
311  nogood) to prevent us from going down this route in the future.
312*/
313    if ((returnCode&2) != 0) {
314        // could add cut
315        returnCode &= ~2;
316    }
317
318    delete newSolver;
319    return returnCode;
320}
321/*
322  First tries setting a variable to better value.  If feasible then
323  tries setting others.  If not feasible then tries swaps
324  Returns 1 if solution, 0 if not
325  The main body of this routine implements an O((q^2)/2) brute force search
326  around the current solution, for q = number of integer variables. Call this
327  the inc/dec heuristic.  For each integer variable x<i>, first decrement the
328  value. Then, for integer variables x<i+1>, ..., x<q-1>, try increment and
329  decrement. If one of these permutations produces a better solution,
330  remember it.  Then repeat, with x<i> incremented. If we find a better
331  solution, update our notion of current solution and continue.
332
333  The net effect is a greedy walk: As each improving pair is found, the
334  current solution is updated and the search continues from this updated
335  solution.
336
337  Way down at the end, we call solutionFix, which will create a drastically
338  restricted problem based on variables marked as used, then do mini-BaC on
339  the restricted problem. This can occur even if we don't try the inc/dec
340  heuristic. This would be more obvious if the inc/dec heuristic were broken
341  out as a separate routine and solutionFix had a name that reflected where
342  it was headed.
343
344  The return code of 0 is grossly overloaded, because it maps to a return
345  code of 0 from solutionFix, which is itself grossly overloaded. See
346  comments in solutionFix and in CbcHeuristic::smallBranchAndBound.
347  */
348int
349CbcHeuristicLocal::solution(double & solutionValue,
350                            double * betterSolution)
351{
352/*
353  Execute only if a new solution has been discovered since the last time we
354  were called.
355*/
356
357    numCouldRun_++;
358    // See if frequency kills off idea
359    int swap = swap_%100;
360    int skip = swap_/100;
361    int nodeCount = model_->getNodeCount();
362    if (nodeCount<lastRunDeep_+skip && nodeCount != lastRunDeep_+1) 
363      return 0;
364    if (numberSolutions_ == model_->getSolutionCount() &&
365        (numberSolutions_ == howOftenShallow_ ||
366         nodeCount < lastRunDeep_+2*skip))
367        return 0;
368    howOftenShallow_ = numberSolutions_;
369    numberSolutions_ = model_->getSolutionCount();
370    if (nodeCount<lastRunDeep_+skip ) 
371      return 0;
372    lastRunDeep_ = nodeCount;
373    howOftenShallow_ = numberSolutions_;
374
375    if ((swap%10) == 2) {
376        // try merge
377        return solutionFix( solutionValue, betterSolution, NULL);
378    }
379/*
380  Exclude long (column), thin (row) systems.
381
382  Given the n^2 nature of the search, more than 100,000 columns could get
383  expensive. But I don't yet see the rationale for the second part of the
384  condition (cols > 10*rows). And cost is proportional to number of integer
385  variables --- shouldn't we use that?
386
387  Why wait until we have more than one solution?
388*/
389    if ((model_->getNumCols() > 100000 && model_->getNumCols() >
390            10*model_->getNumRows()) || numberSolutions_ <= 1)
391        return 0; // probably not worth it
392    // worth trying
393
394    OsiSolverInterface * solver = model_->solver();
395    const double * rowLower = solver->getRowLower();
396    const double * rowUpper = solver->getRowUpper();
397    const double * solution = model_->bestSolution();
398/*
399  Shouldn't this test be redundant if we've already checked that
400  numberSolutions_ > 1? Stronger: shouldn't this be an assertion?
401*/
402    if (!solution)
403        return 0; // No solution found yet
404    const double * objective = solver->getObjCoefficients();
405    double primalTolerance;
406    solver->getDblParam(OsiPrimalTolerance, primalTolerance);
407
408    int numberRows = matrix_.getNumRows();
409
410    int numberIntegers = model_->numberIntegers();
411    const int * integerVariable = model_->integerVariable();
412
413    int i;
414    double direction = solver->getObjSense();
415    double newSolutionValue = model_->getObjValue() * direction;
416    int returnCode = 0;
417    numRuns_++;
418    // Column copy
419    const double * element = matrix_.getElements();
420    const int * row = matrix_.getIndices();
421    const CoinBigIndex * columnStart = matrix_.getVectorStarts();
422    const int * columnLength = matrix_.getVectorLengths();
423
424    // Get solution array for heuristic solution
425    int numberColumns = solver->getNumCols();
426    double * newSolution = new double [numberColumns];
427    memcpy(newSolution, solution, numberColumns*sizeof(double));
428#ifdef LOCAL_FIX_CONTINUOUS
429    // mark continuous used
430    const double * columnLower = solver->getColLower();
431    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
432        if (!solver->isInteger(iColumn)) {
433            if (solution[iColumn] > columnLower[iColumn] + 1.0e-8)
434                used_[iColumn] = numberSolutions_;
435        }
436    }
437#endif
438
439    // way is 1 if down possible, 2 if up possible, 3 if both possible
440    char * way = new char[numberIntegers];
441    // corrected costs
442    double * cost = new double[numberIntegers];
443    // for array to mark infeasible rows after iColumn branch
444    char * mark = new char[numberRows];
445    memset(mark, 0, numberRows);
446    // space to save values so we don't introduce rounding errors
447    double * save = new double[numberRows];
448/*
449  Force variables within their original bounds, then to the nearest integer.
450  Overall, we seem to be prepared to cope with noninteger bounds. Is this
451  necessary? Seems like we'd be better off to force the bounds to integrality
452  as part of preprocessing.  More generally, why do we need to do this? This
453  solution should have been cleaned and checked when it was accepted as a
454  solution!
455
456  Once the value is set, decide whether we can move up or down.
457
458  The only place that used_ is used is in solutionFix; if a variable is not
459  flagged as used, it will be fixed (at lower bound). Why the asymmetric
460  treatment? This makes some sense for binary variables (for which there are
461  only two options). But for general integer variables, why not make a similar
462  test against the original upper bound?
463*/
464
465    // clean solution
466    for (i = 0; i < numberIntegers; i++) {
467        int iColumn = integerVariable[i];
468        const OsiObject * object = model_->object(i);
469        // get original bounds
470        double originalLower;
471        double originalUpper;
472        getIntegerInformation( object, originalLower, originalUpper);
473        double value = newSolution[iColumn];
474        if (value < originalLower) {
475            value = originalLower;
476            newSolution[iColumn] = value;
477        } else if (value > originalUpper) {
478            value = originalUpper;
479            newSolution[iColumn] = value;
480        }
481        double nearest = floor(value + 0.5);
482        //assert(fabs(value-nearest)<10.0*primalTolerance);
483        value = nearest;
484        newSolution[iColumn] = nearest;
485        // if away from lower bound mark that fact
486        if (nearest > originalLower) {
487            used_[iColumn] = numberSolutions_;
488        }
489        cost[i] = direction * objective[iColumn];
490/*
491  Given previous computation we're checking that value is at least 1 away
492  from the original bounds.
493*/
494        int iway = 0;
495
496        if (value > originalLower + 0.5)
497            iway = 1;
498        if (value < originalUpper - 0.5)
499            iway |= 2;
500        way[i] = static_cast<char>(iway);
501    }
502/*
503  Calculate lhs of each constraint for groomed solution.
504*/
505    // get row activities
506    double * rowActivity = new double[numberRows];
507    memset(rowActivity, 0, numberRows*sizeof(double));
508
509    for (i = 0; i < numberColumns; i++) {
510        int j;
511        double value = newSolution[i];
512        if (value) {
513            for (j = columnStart[i];
514                    j < columnStart[i] + columnLength[i]; j++) {
515                int iRow = row[j];
516                rowActivity[iRow] += value * element[j];
517            }
518        }
519    }
520/*
521  Check that constraints are satisfied. For small infeasibility, force the
522  activity within bound. Again, why is this necessary if the current solution
523  was accepted as a valid solution?
524
525  Why are we scanning past the first unacceptable constraint?
526*/
527    // check was feasible - if not adjust (cleaning may move)
528    // if very infeasible then give up
529    bool tryHeuristic = true;
530    for (i = 0; i < numberRows; i++) {
531        if (rowActivity[i] < rowLower[i]) {
532            if (rowActivity[i] < rowLower[i] - 10.0*primalTolerance)
533                tryHeuristic = false;
534            rowActivity[i] = rowLower[i];
535        } else if (rowActivity[i] > rowUpper[i]) {
536            if (rowActivity[i] < rowUpper[i] + 10.0*primalTolerance)
537                tryHeuristic = false;
538            rowActivity[i] = rowUpper[i];
539        }
540    }
541/*
542  This bit of code is not quite totally redundant: it'll bail at 10,000
543  instead of 100,000. Potentially we can do a lot of work to get here, only
544  to abandon it.
545*/
546    // Switch off if may take too long
547    if (model_->getNumCols() > 10000 && model_->getNumCols() >
548            10*model_->getNumRows())
549        tryHeuristic = false;
550/*
551  Try the inc/dec heuristic?
552*/
553    if (tryHeuristic) {
554
555        // total change in objective
556        double totalChange = 0.0;
557        // local best change in objective
558        double bestChange = 0.0;
559        // maybe just do 1000
560        int maxIntegers = numberIntegers;
561        if (((swap/10) &1) != 0) {
562          maxIntegers = CoinMin(1000,numberIntegers);
563        }
564/*
565  Outer loop to walk integer variables. Call the current variable x<i>. At the
566  end of this loop, bestChange will contain the best (negative) change in the
567  objective for any single pair.
568
569  The trouble is, we're limited to monotonically increasing improvement.
570  Suppose we discover an improvement of 10 for some pair. If, later in the
571  search, we discover an improvement of 9 for some other pair, we will not use
572  it. That seems wasteful.
573*/
574
575        for (i = 0; i < numberIntegers; i++) {
576            int iColumn = integerVariable[i];
577            bestChange = 0.0;
578            int endInner = CoinMin(numberIntegers,i+maxIntegers);
579
580            double objectiveCoefficient = cost[i];
581            int k;
582            int j;
583            int goodK = -1;
584            int wayK = -1, wayI = -1;
585/*
586  Try decrementing x<i>.
587*/
588            if ((way[i]&1) != 0) {
589                int numberInfeasible = 0;
590/*
591  Adjust row activities where x<i> has a nonzero coefficient. Save the old
592  values for restoration. Mark any rows that become infeasible as a result
593  of the decrement.
594*/
595                // save row activities and adjust
596                for (j = columnStart[iColumn];
597                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
598                    int iRow = row[j];
599                    save[iRow] = rowActivity[iRow];
600                    rowActivity[iRow] -= element[j];
601                    if (rowActivity[iRow] < rowLower[iRow] - primalTolerance ||
602                            rowActivity[iRow] > rowUpper[iRow] + primalTolerance) {
603                        // mark row
604                        mark[iRow] = 1;
605                        numberInfeasible++;
606                    }
607                }
608  /*
609  Run through the remaining integer variables. Try increment and decrement on
610  each one. If the potential objective change is better than anything we've
611  seen so far, do a full evaluation of x<k> in that direction.  If we can
612  repair all infeasibilities introduced by pushing x<i> down, we have a
613  winner. Remember the best variable, and the direction for x<i> and x<k>.
614*/
615              // try down
616                for (k = i + 1; k < endInner; k++) {
617                    if ((way[k]&1) != 0) {
618                        // try down
619                        if (-objectiveCoefficient - cost[k] < bestChange) {
620                            // see if feasible down
621                            bool good = true;
622                            int numberMarked = 0;
623                            int kColumn = integerVariable[k];
624                            for (j = columnStart[kColumn];
625                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
626                                int iRow = row[j];
627                                double newValue = rowActivity[iRow] - element[j];
628                                if (newValue < rowLower[iRow] - primalTolerance ||
629                                        newValue > rowUpper[iRow] + primalTolerance) {
630                                    good = false;
631                                    break;
632                                } else if (mark[iRow]) {
633                                    // made feasible
634                                    numberMarked++;
635                                }
636                            }
637                            if (good && numberMarked == numberInfeasible) {
638                                // better solution
639                                goodK = k;
640                                wayK = -1;
641                                wayI = -1;
642                                bestChange = -objectiveCoefficient - cost[k];
643                            }
644                        }
645                    }
646                    if ((way[k]&2) != 0) {
647                        // try up
648                        if (-objectiveCoefficient + cost[k] < bestChange) {
649                            // see if feasible up
650                            bool good = true;
651                            int numberMarked = 0;
652                            int kColumn = integerVariable[k];
653                            for (j = columnStart[kColumn];
654                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
655                                int iRow = row[j];
656                                double newValue = rowActivity[iRow] + element[j];
657                                if (newValue < rowLower[iRow] - primalTolerance ||
658                                        newValue > rowUpper[iRow] + primalTolerance) {
659                                    good = false;
660                                    break;
661                                } else if (mark[iRow]) {
662                                    // made feasible
663                                    numberMarked++;
664                                }
665                            }
666                            if (good && numberMarked == numberInfeasible) {
667                                // better solution
668                                goodK = k;
669                                wayK = 1;
670                                wayI = -1;
671                                bestChange = -objectiveCoefficient + cost[k];
672                            }
673                        }
674                    }
675                }
676/*
677  Remove effect of decrementing x<i> by restoring original lhs values.
678*/
679                // restore row activities
680                for (j = columnStart[iColumn];
681                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
682                    int iRow = row[j];
683                    rowActivity[iRow] = save[iRow];
684                    mark[iRow] = 0;
685                }
686            }
687/*
688  Try to increment x<i>. Actions as for decrement.
689*/
690            if ((way[i]&2) != 0) {
691                int numberInfeasible = 0;
692                // save row activities and adjust
693                for (j = columnStart[iColumn];
694                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
695                    int iRow = row[j];
696                    save[iRow] = rowActivity[iRow];
697                    rowActivity[iRow] += element[j];
698                    if (rowActivity[iRow] < rowLower[iRow] - primalTolerance ||
699                            rowActivity[iRow] > rowUpper[iRow] + primalTolerance) {
700                        // mark row
701                        mark[iRow] = 1;
702                        numberInfeasible++;
703                    }
704                }
705                // try up
706                for (k = i + 1; k < endInner; k++) {
707                    if ((way[k]&1) != 0) {
708                        // try down
709                        if (objectiveCoefficient - cost[k] < bestChange) {
710                            // see if feasible down
711                            bool good = true;
712                            int numberMarked = 0;
713                            int kColumn = integerVariable[k];
714                            for (j = columnStart[kColumn];
715                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
716                                int iRow = row[j];
717                                double newValue = rowActivity[iRow] - element[j];
718                                if (newValue < rowLower[iRow] - primalTolerance ||
719                                        newValue > rowUpper[iRow] + primalTolerance) {
720                                    good = false;
721                                    break;
722                                } else if (mark[iRow]) {
723                                    // made feasible
724                                    numberMarked++;
725                                }
726                            }
727                            if (good && numberMarked == numberInfeasible) {
728                                // better solution
729                                goodK = k;
730                                wayK = -1;
731                                wayI = 1;
732                                bestChange = objectiveCoefficient - cost[k];
733                            }
734                        }
735                    }
736                    if ((way[k]&2) != 0) {
737                        // try up
738                        if (objectiveCoefficient + cost[k] < bestChange) {
739                            // see if feasible up
740                            bool good = true;
741                            int numberMarked = 0;
742                            int kColumn = integerVariable[k];
743                            for (j = columnStart[kColumn];
744                                    j < columnStart[kColumn] + columnLength[kColumn]; j++) {
745                                int iRow = row[j];
746                                double newValue = rowActivity[iRow] + element[j];
747                                if (newValue < rowLower[iRow] - primalTolerance ||
748                                        newValue > rowUpper[iRow] + primalTolerance) {
749                                    good = false;
750                                    break;
751                                } else if (mark[iRow]) {
752                                    // made feasible
753                                    numberMarked++;
754                                }
755                            }
756                            if (good && numberMarked == numberInfeasible) {
757                                // better solution
758                                goodK = k;
759                                wayK = 1;
760                                wayI = 1;
761                                bestChange = objectiveCoefficient + cost[k];
762                            }
763                        }
764                    }
765                }
766                // restore row activities
767                for (j = columnStart[iColumn];
768                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
769                    int iRow = row[j];
770                    rowActivity[iRow] = save[iRow];
771                    mark[iRow] = 0;
772                }
773            }
774/*
775  We've found a pair x<i> and x<k> which produce a better solution. Update our
776  notion of current solution to match.
777
778  Why does this not update newSolutionValue?
779*/
780            if (goodK >= 0) {
781                // we found something - update solution
782                for (j = columnStart[iColumn];
783                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
784                    int iRow = row[j];
785                    rowActivity[iRow]  += wayI * element[j];
786                }
787                newSolution[iColumn] += wayI;
788                int kColumn = integerVariable[goodK];
789                for (j = columnStart[kColumn];
790                        j < columnStart[kColumn] + columnLength[kColumn]; j++) {
791                    int iRow = row[j];
792                    rowActivity[iRow]  += wayK * element[j];
793                }
794                newSolution[kColumn] += wayK;
795/*
796  Adjust motion range for x<k>. We may have banged up against a bound with that
797  last move.
798*/
799               // See if k can go further ?
800                const OsiObject * object = model_->object(goodK);
801                // get original bounds
802                double originalLower;
803                double originalUpper;
804                getIntegerInformation( object, originalLower, originalUpper);
805
806                double value = newSolution[kColumn];
807                int iway = 0;
808
809                if (value > originalLower + 0.5)
810                    iway = 1;
811                if (value < originalUpper - 0.5)
812                    iway |= 2;
813                way[goodK] = static_cast<char>(iway);
814                totalChange += bestChange;
815            }
816        }
817/*
818  End of loop to try increment/decrement of integer variables.
819
820  newSolutionValue does not necessarily match the current newSolution, and
821  bestChange simply reflects the best single change. Still, that's sufficient
822  to indicate that there's been at least one change. Check that we really do
823  have a valid solution.
824*/
825        if (totalChange + newSolutionValue < solutionValue) {
826            // paranoid check
827            memset(rowActivity, 0, numberRows*sizeof(double));
828
829            for (i = 0; i < numberColumns; i++) {
830                int j;
831                double value = newSolution[i];
832                if (value) {
833                    for (j = columnStart[i];
834                            j < columnStart[i] + columnLength[i]; j++) {
835                        int iRow = row[j];
836                        rowActivity[iRow] += value * element[j];
837                    }
838                }
839            }
840            int numberBad = 0;
841            double sumBad = 0.0;
842            // check was approximately feasible
843            for (i = 0; i < numberRows; i++) {
844                if (rowActivity[i] < rowLower[i]) {
845                    sumBad += rowLower[i] - rowActivity[i];
846                    if (rowActivity[i] < rowLower[i] - 10.0*primalTolerance)
847                        numberBad++;
848                } else if (rowActivity[i] > rowUpper[i]) {
849                    sumBad += rowUpper[i] - rowActivity[i];
850                    if (rowActivity[i] > rowUpper[i] + 10.0*primalTolerance)
851                        numberBad++;
852                }
853            }
854            if (!numberBad) {
855                for (i = 0; i < numberIntegers; i++) {
856                    int iColumn = integerVariable[i];
857                    const OsiObject * object = model_->object(i);
858                    // get original bounds
859                    double originalLower;
860                    double originalUpper;
861                    getIntegerInformation( object, originalLower, originalUpper);
862
863                    double value = newSolution[iColumn];
864                    // if away from lower bound mark that fact
865                    if (value > originalLower) {
866                        used_[iColumn] = numberSolutions_;
867                    }
868                }
869/*
870  Copy the solution to the array returned to the client. Grab a basis from
871  the solver (which, if it exists, is almost certainly infeasible, but it
872  should be ok for a dual start). The value returned as solutionValue is
873  conservative because of handling of newSolutionValue and bestChange, as
874  described above.
875*/
876                // new solution
877                memcpy(betterSolution, newSolution, numberColumns*sizeof(double));
878                CoinWarmStartBasis * basis =
879                    dynamic_cast<CoinWarmStartBasis *>(solver->getWarmStart()) ;
880                if (basis) {
881                    model_->setBestSolutionBasis(* basis);
882                    delete basis;
883                }
884                returnCode = 1;
885                solutionValue = newSolutionValue + bestChange;
886            } else {
887                // bad solution - should not happen so debug if see message
888                COIN_DETAIL_PRINT(printf("Local search got bad solution with %d infeasibilities summing to %g\n",
889                                         numberBad, sumBad));
890            }
891        }
892    }
893/*
894  We're done. Clean up.
895*/
896    delete [] newSolution;
897    delete [] rowActivity;
898    delete [] way;
899    delete [] cost;
900    delete [] save;
901    delete [] mark;
902/*
903  Do we want to try swapping values between solutions?
904  swap_ is set elsewhere; it's not adjusted during heuristic execution.
905
906  Again, redundant test. We shouldn't be here if numberSolutions_ = 1.
907*/
908    if (numberSolutions_ > 1 && (swap%10) == 1) {
909        // try merge
910        int returnCode2 = solutionFix( solutionValue, betterSolution, NULL);
911        if (returnCode2)
912            returnCode = 1;
913    }
914    return returnCode;
915}
916// update model
917void CbcHeuristicLocal::setModel(CbcModel * model)
918{
919    model_ = model;
920    // Get a copy of original matrix
921    assert(model_->solver());
922    if (model_->solver()->getNumRows()) {
923        matrix_ = *model_->solver()->getMatrixByCol();
924    }
925    delete [] used_;
926    int numberColumns = model->solver()->getNumCols();
927    used_ = new int[numberColumns];
928    memset(used_, 0, numberColumns*sizeof(int));
929}
930// Default Constructor
931CbcHeuristicNaive::CbcHeuristicNaive()
932        : CbcHeuristic()
933{
934    large_ = 1.0e6;
935}
936
937// Constructor with model - assumed before cuts
938
939CbcHeuristicNaive::CbcHeuristicNaive(CbcModel & model)
940        : CbcHeuristic(model)
941{
942    large_ = 1.0e6;
943}
944
945// Destructor
946CbcHeuristicNaive::~CbcHeuristicNaive ()
947{
948}
949
950// Clone
951CbcHeuristic *
952CbcHeuristicNaive::clone() const
953{
954    return new CbcHeuristicNaive(*this);
955}
956// Create C++ lines to get to current state
957void
958CbcHeuristicNaive::generateCpp( FILE * fp)
959{
960    CbcHeuristicNaive other;
961    fprintf(fp, "0#include \"CbcHeuristicLocal.hpp\"\n");
962    fprintf(fp, "3  CbcHeuristicNaive naive(*cbcModel);\n");
963    CbcHeuristic::generateCpp(fp, "naive");
964    if (large_ != other.large_)
965        fprintf(fp, "3  naive.setLarge(%g);\n", large_);
966    else
967        fprintf(fp, "4  naive.setLarge(%g);\n", large_);
968    fprintf(fp, "3  cbcModel->addHeuristic(&naive);\n");
969}
970
971// Copy constructor
972CbcHeuristicNaive::CbcHeuristicNaive(const CbcHeuristicNaive & rhs)
973        :
974        CbcHeuristic(rhs),
975        large_(rhs.large_)
976{
977}
978
979// Assignment operator
980CbcHeuristicNaive &
981CbcHeuristicNaive::operator=( const CbcHeuristicNaive & rhs)
982{
983    if (this != &rhs) {
984        CbcHeuristic::operator=(rhs);
985        large_ = rhs.large_;
986    }
987    return *this;
988}
989
990// Resets stuff if model changes
991void
992CbcHeuristicNaive::resetModel(CbcModel * model)
993{
994    CbcHeuristic::resetModel(model);
995}
996int
997CbcHeuristicNaive::solution(double & solutionValue,
998                            double * betterSolution)
999{
1000    numCouldRun_++;
1001    // See if to do
1002    bool atRoot = model_->getNodeCount() == 0;
1003    int passNumber = model_->getCurrentPassNumber();
1004    if (!when() || (when() == 1 && model_->phase() != 1) || !atRoot || passNumber != 1)
1005        return 0; // switched off
1006    // Don't do if it was this heuristic which found solution!
1007    if (this == model_->lastHeuristic())
1008        return 0;
1009    numRuns_++;
1010    double cutoff;
1011    model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff);
1012    double direction = model_->solver()->getObjSense();
1013    cutoff *= direction;
1014    cutoff = CoinMin(cutoff, solutionValue);
1015    OsiSolverInterface * solver = model_->continuousSolver();
1016    if (!solver)
1017        solver = model_->solver();
1018    const double * colLower = solver->getColLower();
1019    const double * colUpper = solver->getColUpper();
1020    const double * objective = solver->getObjCoefficients();
1021
1022    int numberColumns = model_->getNumCols();
1023    int numberIntegers = model_->numberIntegers();
1024    const int * integerVariable = model_->integerVariable();
1025
1026    int i;
1027    bool solutionFound = false;
1028    CoinWarmStartBasis saveBasis;
1029    CoinWarmStartBasis * basis =
1030        dynamic_cast<CoinWarmStartBasis *>(solver->getWarmStart()) ;
1031    if (basis) {
1032        saveBasis = * basis;
1033        delete basis;
1034    }
1035    // First just fix all integers as close to zero as possible
1036    OsiSolverInterface * newSolver = cloneBut(7); // wassolver->clone();
1037    for (i = 0; i < numberIntegers; i++) {
1038        int iColumn = integerVariable[i];
1039        double lower = colLower[iColumn];
1040        double upper = colUpper[iColumn];
1041        double value;
1042        if (lower > 0.0)
1043            value = lower;
1044        else if (upper < 0.0)
1045            value = upper;
1046        else
1047            value = 0.0;
1048        newSolver->setColLower(iColumn, value);
1049        newSolver->setColUpper(iColumn, value);
1050    }
1051    newSolver->initialSolve();
1052    if (newSolver->isProvenOptimal()) {
1053        double solValue = newSolver->getObjValue() * direction ;
1054        if (solValue < cutoff) {
1055            // we have a solution
1056            solutionFound = true;
1057            solutionValue = solValue;
1058            memcpy(betterSolution, newSolver->getColSolution(),
1059                   numberColumns*sizeof(double));
1060            COIN_DETAIL_PRINT(printf("Naive fixing close to zero gave solution of %g\n", solutionValue));
1061            cutoff = solValue - model_->getCutoffIncrement();
1062        }
1063    }
1064    // Now fix all integers as close to zero if zero or large cost
1065    int nFix = 0;
1066    for (i = 0; i < numberIntegers; i++) {
1067        int iColumn = integerVariable[i];
1068        double lower = colLower[iColumn];
1069        double upper = colUpper[iColumn];
1070        double value;
1071        if (fabs(objective[i]) > 0.0 && fabs(objective[i]) < large_) {
1072            nFix++;
1073            if (lower > 0.0)
1074                value = lower;
1075            else if (upper < 0.0)
1076                value = upper;
1077            else
1078                value = 0.0;
1079            newSolver->setColLower(iColumn, value);
1080            newSolver->setColUpper(iColumn, value);
1081        } else {
1082            // set back to original
1083            newSolver->setColLower(iColumn, lower);
1084            newSolver->setColUpper(iColumn, upper);
1085        }
1086    }
1087    const double * solution = solver->getColSolution();
1088    if (nFix) {
1089        newSolver->setWarmStart(&saveBasis);
1090        newSolver->setColSolution(solution);
1091        newSolver->initialSolve();
1092        if (newSolver->isProvenOptimal()) {
1093            double solValue = newSolver->getObjValue() * direction ;
1094            if (solValue < cutoff) {
1095                // try branch and bound
1096                double * newSolution = new double [numberColumns];
1097                COIN_DETAIL_PRINT(printf("%d fixed after fixing costs\n", nFix));
1098                int returnCode = smallBranchAndBound(newSolver,
1099                                                     numberNodes_, newSolution,
1100                                                     solutionValue,
1101                                                     solutionValue, "CbcHeuristicNaive1");
1102                if (returnCode < 0)
1103                    returnCode = 0; // returned on size
1104                if ((returnCode&2) != 0) {
1105                    // could add cut
1106                    returnCode &= ~2;
1107                }
1108                if (returnCode == 1) {
1109                    // solution
1110                    solutionFound = true;
1111                    memcpy(betterSolution, newSolution,
1112                           numberColumns*sizeof(double));
1113                    COIN_DETAIL_PRINT(printf("Naive fixing zeros gave solution of %g\n", solutionValue));
1114                    cutoff = solutionValue - model_->getCutoffIncrement();
1115                }
1116                delete [] newSolution;
1117            }
1118        }
1119    }
1120#if 1
1121    newSolver->setObjSense(-direction); // maximize
1122    newSolver->setWarmStart(&saveBasis);
1123    newSolver->setColSolution(solution);
1124    for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
1125        double value = solution[iColumn];
1126        double lower = colLower[iColumn];
1127        double upper = colUpper[iColumn];
1128        double newLower;
1129        double newUpper;
1130        if (newSolver->isInteger(iColumn)) {
1131            newLower = CoinMax(lower, floor(value) - 2.0);
1132            newUpper = CoinMin(upper, ceil(value) + 2.0);
1133        } else {
1134            newLower = CoinMax(lower, value - 1.0e5);
1135            newUpper = CoinMin(upper, value + 1.0e-5);
1136        }
1137        newSolver->setColLower(iColumn, newLower);
1138        newSolver->setColUpper(iColumn, newUpper);
1139    }
1140    newSolver->initialSolve();
1141    if (newSolver->isProvenOptimal()) {
1142        double solValue = newSolver->getObjValue() * direction ;
1143        if (solValue < cutoff) {
1144            nFix = 0;
1145            newSolver->setObjSense(direction); // correct direction
1146            //const double * thisSolution = newSolver->getColSolution();
1147            for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
1148                double value = solution[iColumn];
1149                double lower = colLower[iColumn];
1150                double upper = colUpper[iColumn];
1151                double newLower = lower;
1152                double newUpper = upper;
1153                if (newSolver->isInteger(iColumn)) {
1154                    if (value < lower + 1.0e-6) {
1155                        nFix++;
1156                        newUpper = lower;
1157                    } else if (value > upper - 1.0e-6) {
1158                        nFix++;
1159                        newLower = upper;
1160                    } else {
1161                        newLower = CoinMax(lower, floor(value) - 2.0);
1162                        newUpper = CoinMin(upper, ceil(value) + 2.0);
1163                    }
1164                }
1165                newSolver->setColLower(iColumn, newLower);
1166                newSolver->setColUpper(iColumn, newUpper);
1167            }
1168            // try branch and bound
1169            double * newSolution = new double [numberColumns];
1170            COIN_DETAIL_PRINT(printf("%d fixed after maximizing\n", nFix));
1171            int returnCode = smallBranchAndBound(newSolver,
1172                                                 numberNodes_, newSolution,
1173                                                 solutionValue,
1174                                                 solutionValue, "CbcHeuristicNaive1");
1175            if (returnCode < 0)
1176                returnCode = 0; // returned on size
1177            if ((returnCode&2) != 0) {
1178                // could add cut
1179                returnCode &= ~2;
1180            }
1181            if (returnCode == 1) {
1182                // solution
1183                solutionFound = true;
1184                memcpy(betterSolution, newSolution,
1185                       numberColumns*sizeof(double));
1186                COIN_DETAIL_PRINT(printf("Naive maximizing gave solution of %g\n", solutionValue));
1187                cutoff = solutionValue - model_->getCutoffIncrement();
1188            }
1189            delete [] newSolution;
1190        }
1191    }
1192#endif
1193    delete newSolver;
1194    return solutionFound ? 1 : 0;
1195}
1196// update model
1197void CbcHeuristicNaive::setModel(CbcModel * model)
1198{
1199    model_ = model;
1200}
1201// Default Constructor
1202CbcHeuristicCrossover::CbcHeuristicCrossover()
1203        : CbcHeuristic(),
1204        numberSolutions_(0),
1205        useNumber_(3)
1206{
1207    setWhen(1);
1208}
1209
1210// Constructor with model - assumed before cuts
1211
1212CbcHeuristicCrossover::CbcHeuristicCrossover(CbcModel & model)
1213        : CbcHeuristic(model),
1214        numberSolutions_(0),
1215        useNumber_(3)
1216{
1217    setWhen(1);
1218    for (int i = 0; i < 10; i++)
1219        random_[i] = model.randomNumberGenerator()->randomDouble();
1220}
1221
1222// Destructor
1223CbcHeuristicCrossover::~CbcHeuristicCrossover ()
1224{
1225}
1226
1227// Clone
1228CbcHeuristic *
1229CbcHeuristicCrossover::clone() const
1230{
1231    return new CbcHeuristicCrossover(*this);
1232}
1233// Create C++ lines to get to current state
1234void
1235CbcHeuristicCrossover::generateCpp( FILE * fp)
1236{
1237    CbcHeuristicCrossover other;
1238    fprintf(fp, "0#include \"CbcHeuristicLocal.hpp\"\n");
1239    fprintf(fp, "3  CbcHeuristicCrossover crossover(*cbcModel);\n");
1240    CbcHeuristic::generateCpp(fp, "crossover");
1241    if (useNumber_ != other.useNumber_)
1242        fprintf(fp, "3  crossover.setNumberSolutions(%d);\n", useNumber_);
1243    else
1244        fprintf(fp, "4  crossover.setNumberSolutions(%d);\n", useNumber_);
1245    fprintf(fp, "3  cbcModel->addHeuristic(&crossover);\n");
1246}
1247
1248// Copy constructor
1249CbcHeuristicCrossover::CbcHeuristicCrossover(const CbcHeuristicCrossover & rhs)
1250        :
1251        CbcHeuristic(rhs),
1252        attempts_(rhs.attempts_),
1253        numberSolutions_(rhs.numberSolutions_),
1254        useNumber_(rhs.useNumber_)
1255{
1256    memcpy(random_, rhs.random_, 10*sizeof(double));
1257}
1258
1259// Assignment operator
1260CbcHeuristicCrossover &
1261CbcHeuristicCrossover::operator=( const CbcHeuristicCrossover & rhs)
1262{
1263    if (this != &rhs) {
1264        CbcHeuristic::operator=(rhs);
1265        useNumber_ = rhs.useNumber_;
1266        attempts_ = rhs.attempts_;
1267        numberSolutions_ = rhs.numberSolutions_;
1268        memcpy(random_, rhs.random_, 10*sizeof(double));
1269    }
1270    return *this;
1271}
1272
1273// Resets stuff if model changes
1274void
1275CbcHeuristicCrossover::resetModel(CbcModel * model)
1276{
1277    CbcHeuristic::resetModel(model);
1278}
1279int
1280CbcHeuristicCrossover::solution(double & solutionValue,
1281                                double * betterSolution)
1282{
1283    if (when_ == 0)
1284        return 0;
1285    numCouldRun_++;
1286    bool useBest = (numberSolutions_ != model_->getSolutionCount());
1287    if (!useBest && (when_ % 10) == 1)
1288        return 0;
1289    numberSolutions_ = model_->getSolutionCount();
1290    OsiSolverInterface * continuousSolver = model_->continuousSolver();
1291    int useNumber = CoinMin(model_->numberSavedSolutions(), useNumber_);
1292    if (useNumber < 2 || !continuousSolver)
1293        return 0;
1294    // Fix later
1295    if (!useBest)
1296        abort();
1297    numRuns_++;
1298    double cutoff;
1299    model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff);
1300    double direction = model_->solver()->getObjSense();
1301    cutoff *= direction;
1302    cutoff = CoinMin(cutoff, solutionValue);
1303    OsiSolverInterface * solver = cloneBut(2);
1304    // But reset bounds
1305    solver->setColLower(continuousSolver->getColLower());
1306    solver->setColUpper(continuousSolver->getColUpper());
1307    int numberColumns = solver->getNumCols();
1308    // Fixed
1309    double * fixed = new double [numberColumns];
1310    for (int i = 0; i < numberColumns; i++)
1311        fixed[i] = -COIN_DBL_MAX;
1312    int whichSolution[10];
1313    for (int i = 0; i < useNumber; i++)
1314        whichSolution[i] = i;
1315    for (int i = 0; i < useNumber; i++) {
1316        int k = whichSolution[i];
1317        const double * solution = model_->savedSolution(k);
1318        for (int j = 0; j < numberColumns; j++) {
1319            if (solver->isInteger(j)) {
1320                if (fixed[j] == -COIN_DBL_MAX)
1321                    fixed[j] = floor(solution[j] + 0.5);
1322                else if (fabs(fixed[j] - solution[j]) > 1.0e-7)
1323                    fixed[j] = COIN_DBL_MAX;
1324            }
1325        }
1326    }
1327    const double * colLower = solver->getColLower();
1328    for (int i = 0; i < numberColumns; i++) {
1329        if (solver->isInteger(i)) {
1330            double value = fixed[i];
1331            if (value != COIN_DBL_MAX) {
1332                if (when_ < 10) {
1333                    solver->setColLower(i, value);
1334                    solver->setColUpper(i, value);
1335                } else if (value == colLower[i]) {
1336                    solver->setColUpper(i, value);
1337                }
1338            }
1339        }
1340    }
1341    int returnCode = smallBranchAndBound(solver, numberNodes_, betterSolution,
1342                                         solutionValue,
1343                                         solutionValue, "CbcHeuristicCrossover");
1344    if (returnCode < 0)
1345        returnCode = 0; // returned on size
1346    if ((returnCode&2) != 0) {
1347        // could add cut
1348        returnCode &= ~2;
1349    }
1350
1351    delete solver;
1352    return returnCode;
1353}
1354// update model
1355void CbcHeuristicCrossover::setModel(CbcModel * model)
1356{
1357    model_ = model;
1358    if (model) {
1359        for (int i = 0; i < 10; i++)
1360            random_[i] = model->randomNumberGenerator()->randomDouble();
1361    }
1362}
1363
1364
Note: See TracBrowser for help on using the repository browser.