00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CoinHelperFunctions.hpp"
00013
00014 #include "CouenneProblem.hpp"
00015 #include "CouenneFPpool.hpp"
00016 #include "CouenneFeasPump.hpp"
00017 #include "CouenneExprVar.hpp"
00018 #include "CouenneExprAux.hpp"
00019
00020 static const double COMP_TOLERANCE = COUENNE_EPS;
00021
00022 using namespace Couenne;
00023
00025 CouenneFPsolution::CouenneFPsolution (CouenneProblem *p, CouNumber *x, bool copied):
00026
00027 x_ (NULL),
00028 n_ (p -> nVars ()),
00029 nNLinf_ (0),
00030 nIinf_ (0),
00031 objVal_ (0.),
00032 maxNLinf_ (0.),
00033 maxIinf_ (0.),
00034 copied_ (copied),
00035 problem_ (p) {
00036
00040
00041 if (copied_) {
00042 x_ = x;
00043 return;
00044 }
00045
00046 x_ = CoinCopyOfArray (x, p -> nVars ());
00047
00048 for (std::vector <exprVar *>::iterator i = p -> Variables (). begin ();
00049 i != p -> Variables (). end ();
00050 ++i) {
00051
00052 if ((*i) -> Multiplicity () <= 0)
00053 continue;
00054
00055 CouNumber
00056 vval = (**i) ();
00057
00058 if ((*i) -> isInteger ()) {
00059
00060 double inf = CoinMax (vval - floor (vval + COUENNE_EPS),
00061 ceil (vval - COUENNE_EPS) - vval);
00062
00063 if (inf > COUENNE_EPS) {
00064
00065 ++nIinf_;
00066
00067 if (inf > maxIinf_)
00068 maxIinf_ = inf;
00069 }
00070 }
00071
00072 if (((*i) -> Type () == AUX) &&
00073 ((*i) -> Image () -> Linearity () > LINEAR)) {
00074
00075 double
00076 diff = 0.,
00077 fval = (*((*i) -> Image ())) ();
00078
00079 if ((*i) -> sign () != expression::AUX_GEQ) diff = CoinMax (diff, vval - fval);
00080 else if ((*i) -> sign () != expression::AUX_LEQ) diff = CoinMax (diff, fval - vval);
00081
00082 if (diff > COUENNE_EPS) {
00083
00084 ++nNLinf_;
00085
00086 if (diff > maxNLinf_)
00087 maxNLinf_ = diff;
00088 }
00089 }
00090 }
00091 }
00092
00093
00095 CouenneFPsolution::CouenneFPsolution (const CouenneFPsolution &src):
00096 x_ (src.x_ ? CoinCopyOfArray (src.x_, src.n_) : NULL),
00097 n_ (src.n_),
00098 nNLinf_ (src.nNLinf_),
00099 nIinf_ (src.nIinf_),
00100 objVal_ (src.objVal_),
00101 maxNLinf_ (src.maxNLinf_),
00102 maxIinf_ (src.maxIinf_),
00103 copied_ (false),
00104 problem_ (src.problem_) {}
00105
00106
00108 CouenneFPsolution &CouenneFPsolution::operator= (const CouenneFPsolution &src) {
00109
00110 x_ = src.x_ ? CoinCopyOfArray (src.x_, src.n_) : NULL;
00111 n_ = src.n_;
00112 nNLinf_ = src.nNLinf_;
00113 nIinf_ = src.nIinf_;
00114 objVal_ = src.objVal_;
00115 maxNLinf_ = src.maxNLinf_;
00116 maxIinf_ = src.maxIinf_;
00117 copied_ = false;
00118 problem_ = src.problem_;
00119
00120 return *this;
00121 }
00122
00124 CouenneFPsolution::~CouenneFPsolution () {
00125
00126 if (x_ && !copied_)
00127 delete [] x_;
00128 }
00129
00131 bool CouenneFPsolution::compare (const CouenneFPsolution &other, enum what_to_compare comparedTerm) const {
00132
00133 switch (comparedTerm) {
00134
00135 case SUM_INF: if (maxNLinf_ + maxIinf_ < other.maxNLinf_ + other.maxIinf_) return true;
00136 case OBJVAL: if (objVal_ < other.objVal_ - COUENNE_EPS * CoinMax (1., CoinMax (objVal_, other.objVal_))) return true;
00137 case SUM_NINF: if (nNLinf_ + nIinf_ < other.nNLinf_ + other.nIinf_) return true;
00138
00139
00140 case INTEGER_VARS: {
00141
00142
00143
00144
00145 for (std::vector <exprVar *>::iterator i = problem_ -> Variables (). begin ();
00146 i != problem_ -> Variables (). end ();
00147 ++i)
00148
00149 if (((*i) -> Multiplicity () > 0) &&
00150 (*i) -> isInteger ()) {
00151
00152 int indVar = (*i) -> Index ();
00153
00154
00155
00156
00157 #if 0
00158 if (0) {
00159 printf (" (%d,%g,%g,%g)", indVar, x_ [indVar], other.x_ [indVar], x_ [indVar] - other.x_ [indVar]);
00160
00161 if (x_ [indVar] < other.x_ [indVar] - COUENNE_EPS)
00162 printf ("\n-----\n");
00163 }
00164 #endif
00165 if (x_ [indVar] < other.x_ [indVar] - COUENNE_EPS)
00166 return true;
00167 }
00168
00169
00170 return false;
00171 }
00172
00173 case ALL_VARS: {
00174
00175
00176
00177 for (std::vector <exprVar *>::iterator i = problem_ -> Variables (). begin ();
00178 i != problem_ -> Variables (). end ();
00179 ++i)
00180
00181 if ((*i) -> Multiplicity () > 0) {
00182
00183 int indVar = (*i) -> Index ();
00184
00185 if (x_ [indVar] < other.x_ [indVar] + COUENNE_EPS)
00186 return true;
00187 }
00188
00189 return false;
00190 }
00191 }
00192
00193 printf ("CouenneFPsolution::compare: bad compared term\n");
00194 abort ();
00195 }
00196
00197
00199 CouenneFPpool::CouenneFPpool (const CouenneFPpool &src):
00200 set_ (src.set_),
00201 problem_ (src.problem_) {}
00202
00203
00205 CouenneFPpool &CouenneFPpool::operator= (const CouenneFPpool &src) {
00206
00207 set_ = src.set_;
00208 problem_ = src.problem_;
00209
00210 return *this;
00211 }
00212
00214 bool compareSol::operator() (const CouenneFPsolution &one,
00215 const CouenneFPsolution &two) const {
00216
00217 return one. compare (two, comparedTerm_);
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 }
00231
00234 void CouenneFPpool::findClosestAndReplace (double *&sol, const double *nSol, int nvars) {
00235
00236 double bestdist = COIN_DBL_MAX;
00237 std::set <CouenneFPsolution, compareSol>::iterator bestsol = set_. end ();
00238
00239 if( nSol )
00240 {
00241 for (std::set <CouenneFPsolution, compareSol>::iterator i = set_. begin ();
00242 i != set_. end (); ++i)
00243 {
00244
00245
00246 register double
00247 dist = 0.0,
00248 delta;
00249
00250 const register double
00251 *x = i -> x (),
00252 *s = nSol;
00253
00254 register bool move_on = false;
00255
00256 for (int j = nvars, k=0; j--; ++k) {
00257
00258 delta = *x++ - *s++;
00259
00262 if (problem_ -> Var (k) -> Multiplicity () <= 0)
00263 continue;
00264
00265 dist += delta * delta;
00266
00267 if (dist >= bestdist) {
00268
00269 move_on = true;
00270 break;
00271 }
00272 }
00273
00274 if (move_on)
00275 continue;
00276
00277
00278 if( dist < bestdist )
00279 {
00280 bestdist = dist;
00281 bestsol = i;
00282 }
00283 }
00284 }
00285 else
00286 bestsol = set_. begin ();
00287
00288 if( bestsol != set_. end () )
00289 {
00290 delete [] sol;
00291 sol = CoinCopyOfArray ((*bestsol).x(), nvars);
00292 set_. erase(bestsol);
00293 }
00294 }