source: branches/sandbox/Cbc/src/CbcSimpleInteger.cpp @ 1293

Last change on this file since 1293 was 1293, checked in by EdwinStraver, 10 years ago
File size: 7.7 KB
Line 
1// Edwin 11/9/2009-- carved out of CbcBranchActual
2#if defined(_MSC_VER)
3// Turn off compiler warning about long names
4#  pragma warning(disable:4786)
5#endif
6#include <cassert>
7#include <cstdlib>
8#include <cmath>
9#include <cfloat>
10//#define CBC_DEBUG
11
12#include "CoinTypes.hpp"
13#include "OsiSolverInterface.hpp"
14#include "OsiSolverBranch.hpp"
15#include "CbcModel.hpp"
16#include "CbcMessage.hpp"
17#include "CbcSimpleInteger.hpp"
18#include "CbcBranchActual.hpp"
19#include "CoinSort.hpp"
20#include "CoinError.hpp"
21
22
23//##############################################################################
24
25/** Default Constructor
26
27  Equivalent to an unspecified binary variable.
28*/
29CbcSimpleInteger::CbcSimpleInteger ()
30        : CbcObject(),
31        originalLower_(0.0),
32        originalUpper_(1.0),
33        breakEven_(0.5),
34        columnNumber_(-1),
35        preferredWay_(0)
36{
37}
38
39/** Useful constructor
40
41  Loads actual upper & lower bounds for the specified variable.
42*/
43CbcSimpleInteger::CbcSimpleInteger ( CbcModel * model, int iColumn, double breakEven)
44        : CbcObject(model)
45{
46    columnNumber_ = iColumn ;
47    originalLower_ = model->solver()->getColLower()[columnNumber_] ;
48    originalUpper_ = model->solver()->getColUpper()[columnNumber_] ;
49    breakEven_ = breakEven;
50    assert (breakEven_ > 0.0 && breakEven_ < 1.0);
51    preferredWay_ = 0;
52}
53
54
55// Copy constructor
56CbcSimpleInteger::CbcSimpleInteger ( const CbcSimpleInteger & rhs)
57        : CbcObject(rhs)
58
59{
60    columnNumber_ = rhs.columnNumber_;
61    originalLower_ = rhs.originalLower_;
62    originalUpper_ = rhs.originalUpper_;
63    breakEven_ = rhs.breakEven_;
64    preferredWay_ = rhs.preferredWay_;
65}
66
67// Clone
68CbcObject *
69CbcSimpleInteger::clone() const
70{
71    return new CbcSimpleInteger(*this);
72}
73
74// Assignment operator
75CbcSimpleInteger &
76CbcSimpleInteger::operator=( const CbcSimpleInteger & rhs)
77{
78    if (this != &rhs) {
79        CbcObject::operator=(rhs);
80        columnNumber_ = rhs.columnNumber_;
81        originalLower_ = rhs.originalLower_;
82        originalUpper_ = rhs.originalUpper_;
83        breakEven_ = rhs.breakEven_;
84        preferredWay_ = rhs.preferredWay_;
85    }
86    return *this;
87}
88
89// Destructor
90CbcSimpleInteger::~CbcSimpleInteger ()
91{
92}
93// Construct an OsiSimpleInteger object
94OsiSimpleInteger *
95CbcSimpleInteger::osiObject() const
96{
97    OsiSimpleInteger * obj = new OsiSimpleInteger(columnNumber_,
98            originalLower_, originalUpper_);
99    obj->setPriority(priority());
100    return obj;
101}
102double
103CbcSimpleInteger::infeasibility(const OsiBranchingInformation * info,
104                                int &preferredWay) const
105{
106    double value = info->solution_[columnNumber_];
107    value = CoinMax(value, info->lower_[columnNumber_]);
108    value = CoinMin(value, info->upper_[columnNumber_]);
109    double nearest = floor(value + (1.0 - breakEven_));
110    assert (breakEven_ > 0.0 && breakEven_ < 1.0);
111    if (nearest > value)
112        preferredWay = 1;
113    else
114        preferredWay = -1;
115    if (preferredWay_)
116        preferredWay = preferredWay_;
117    double weight = fabs(value - nearest);
118    // normalize so weight is 0.5 at break even
119    if (nearest < value)
120        weight = (0.5 / breakEven_) * weight;
121    else
122        weight = (0.5 / (1.0 - breakEven_)) * weight;
123    if (fabs(value - nearest) <= info->integerTolerance_)
124        return 0.0;
125    else
126        return weight;
127}
128double
129CbcSimpleInteger::feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const
130{
131    double value = info->solution_[columnNumber_];
132#ifdef COIN_DEVELOP
133    if (fabs(value - floor(value + 0.5)) > 1.0e-5)
134        printf("value for %d away from integer %g\n", columnNumber_, value);
135#endif
136    double newValue = CoinMax(value, info->lower_[columnNumber_]);
137    newValue = CoinMin(newValue, info->upper_[columnNumber_]);
138    newValue = floor(newValue + 0.5);
139    solver->setColLower(columnNumber_, newValue);
140    solver->setColUpper(columnNumber_, newValue);
141    return fabs(value - newValue);
142}
143
144/* Create an OsiSolverBranch object
145
146This returns NULL if branch not represented by bound changes
147*/
148OsiSolverBranch *
149CbcSimpleInteger::solverBranch(OsiSolverInterface * /*solver*/,
150                               const OsiBranchingInformation * info) const
151{
152    double value = info->solution_[columnNumber_];
153    value = CoinMax(value, info->lower_[columnNumber_]);
154    value = CoinMin(value, info->upper_[columnNumber_]);
155    assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]);
156#ifndef NDEBUG
157    double nearest = floor(value + 0.5);
158    assert (fabs(value - nearest) > info->integerTolerance_);
159#endif
160    OsiSolverBranch * branch = new OsiSolverBranch();
161    branch->addBranch(columnNumber_, value);
162    return branch;
163}
164// Creates a branching object
165CbcBranchingObject *
166CbcSimpleInteger::createCbcBranch(OsiSolverInterface * /*solver*/,
167                                  const OsiBranchingInformation * info, int way)
168{
169    CbcIntegerBranchingObject * branch = new CbcIntegerBranchingObject(model_, 0, -1, 0.5);
170    fillCreateBranch(branch, info, way);
171    return branch;
172}
173// Fills in a created branching object
174void
175CbcSimpleInteger::fillCreateBranch(CbcIntegerBranchingObject * branch, const OsiBranchingInformation * info, int way)
176{
177    branch->setOriginalObject(this);
178    double value = info->solution_[columnNumber_];
179    value = CoinMax(value, info->lower_[columnNumber_]);
180    value = CoinMin(value, info->upper_[columnNumber_]);
181    assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]);
182    if (!info->hotstartSolution_ && priority_ != -999) {
183#ifndef NDEBUG
184        double nearest = floor(value + 0.5);
185        assert (fabs(value - nearest) > info->integerTolerance_);
186#endif
187    } else if (info->hotstartSolution_) {
188        double targetValue = info->hotstartSolution_[columnNumber_];
189        if (way > 0)
190            value = targetValue - 0.1;
191        else
192            value = targetValue + 0.1;
193    } else {
194        if (value <= info->lower_[columnNumber_])
195            value += 0.1;
196        else if (value >= info->upper_[columnNumber_])
197            value -= 0.1;
198    }
199    assert (value >= info->lower_[columnNumber_] &&
200            value <= info->upper_[columnNumber_]);
201    branch->fillPart(columnNumber_, way, value);
202}
203/* Column number if single column object -1 otherwise,
204   so returns >= 0
205   Used by heuristics
206*/
207int
208CbcSimpleInteger::columnNumber() const
209{
210    return columnNumber_;
211}
212/* Reset variable bounds to their original values.
213
214    Bounds may be tightened, so it may be good to be able to set this info in object.
215*/
216void
217CbcSimpleInteger::resetBounds(const OsiSolverInterface * solver)
218{
219    originalLower_ = solver->getColLower()[columnNumber_] ;
220    originalUpper_ = solver->getColUpper()[columnNumber_] ;
221}
222
223/*  Change column numbers after preprocessing
224 */
225void
226CbcSimpleInteger::resetSequenceEtc(int /*numberColumns*/,
227                                   const int * originalColumns)
228{
229    //assert (numberColumns>0);
230    int iColumn;
231#if 0
232    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
233        if (columnNumber_ == originalColumns[iColumn])
234            break;
235    }
236    assert (iColumn < numberColumns);
237#else
238    iColumn = originalColumns[columnNumber_];
239    assert (iColumn >= 0);
240#endif
241    columnNumber_ = iColumn;
242}
243// This looks at solution and sets bounds to contain solution
244/** More precisely: it first forces the variable within the existing
245    bounds, and then tightens the bounds to fix the variable at the
246    nearest integer value.
247*/
248void
249CbcSimpleInteger::feasibleRegion()
250{
251    abort();
252}
Note: See TracBrowser for help on using the repository browser.