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 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
00039
00040 if (copied_) {
00041 x_ = x;
00042 return;
00043 }
00044
00045 x_ = CoinCopyOfArray (x, p -> nVars ());
00046
00047 for (std::vector <exprVar *>::iterator i = p -> Variables (). begin ();
00048 i != p -> Variables (). end ();
00049 ++i) {
00050
00051 CouNumber
00052 vval = (**i) ();
00053
00054 if ((*i) -> Multiplicity () <= 0)
00055 continue;
00056
00057 if ((*i) -> isInteger ()) {
00058
00059 double inf = CoinMax (vval - floor (vval + COUENNE_EPS),
00060 ceil (vval - COUENNE_EPS) - vval);
00061
00062 if (inf > COUENNE_EPS) {
00063
00064 ++nIinf_;
00065
00066 if (inf > maxIinf_)
00067 maxIinf_ = inf;
00068 }
00069 }
00070
00071 if (((*i) -> Type () == AUX) &&
00072 ((*i) -> Image () -> Linearity () > LINEAR)) {
00073
00074 double
00075 diff = 0.,
00076 fval = (*((*i) -> Image ())) ();
00077
00078 if ((*i) -> sign () != expression::AUX_GEQ) diff = CoinMax (diff, vval - fval);
00079 else if ((*i) -> sign () != expression::AUX_LEQ) diff = CoinMax (diff, fval - vval);
00080
00081 if (diff > COUENNE_EPS) {
00082
00083 ++nNLinf_;
00084
00085 if (diff > maxNLinf_)
00086 maxNLinf_ = diff;
00087 }
00088 }
00089 }
00090 }
00091
00092
00095 CouenneFPsolution::CouenneFPsolution (CouNumber *x,
00096 int n,
00097 int nNLinf,
00098 int nIinf,
00099 CouNumber objVal,
00100 CouNumber maxNLinf,
00101 CouNumber maxIinf):
00102
00103 x_ (CoinCopyOfArray (x, n)),
00104 n_ (n),
00105 nNLinf_ (nNLinf),
00106 nIinf_ (nIinf),
00107 objVal_ (objVal),
00108 maxNLinf_ (maxNLinf),
00109 maxIinf_ (maxIinf),
00110 copied_ (false) {}
00111
00113 CouenneFPsolution::CouenneFPsolution (const CouenneFPsolution &src):
00114 x_ (src.x_ ? CoinCopyOfArray (src.x_, src.n_) : NULL),
00115 n_ (src.n_),
00116 nNLinf_ (src.nNLinf_),
00117 nIinf_ (src.nIinf_),
00118 objVal_ (src.objVal_),
00119 maxNLinf_ (src.maxNLinf_),
00120 maxIinf_ (src.maxIinf_),
00121 copied_ (false) {}
00122
00123
00125 CouenneFPsolution &CouenneFPsolution::operator= (const CouenneFPsolution &src) {
00126
00127 x_ = src.x_ ? CoinCopyOfArray (src.x_, src.n_) : NULL;
00128 n_ = src.n_;
00129 nNLinf_ = src.nNLinf_;
00130 nIinf_ = src.nIinf_;
00131 objVal_ = src.objVal_;
00132 maxNLinf_ = src.maxNLinf_;
00133 maxIinf_ = src.maxIinf_;
00134 copied_ = false;
00135
00136 return *this;
00137 }
00138
00140 CouenneFPsolution::~CouenneFPsolution () {
00141
00142 if (x_ && !copied_)
00143 delete [] x_;
00144 }
00145
00147 bool CouenneFPsolution::compare (const CouenneFPsolution &other, enum what_to_compare comparedTerm) const {
00148
00149 switch (comparedTerm) {
00150
00151 case SUM_NINF: return (nNLinf_ + nIinf_ < other.nNLinf_ + other.nIinf_);
00152 case SUM_INF: return (maxNLinf_ + maxIinf_ < other.maxNLinf_ + other.maxIinf_);
00153 case OBJVAL: return (objVal_ < other.objVal_);
00154 }
00155
00156 printf ("CouenneFPsolution::compare: bad compared term\n");
00157 abort ();
00158 }
00159
00160
00162 CouenneFPpool::CouenneFPpool (const CouenneFPpool &src):
00163 set_ (src.set_) {}
00164
00165
00167 CouenneFPpool &CouenneFPpool::operator= (const CouenneFPpool &src) {
00168
00169 set_ = src.set_;
00170
00171 return *this;
00172 }
00173
00175 bool compareSol::operator() (const CouenneFPsolution &one,
00176 const CouenneFPsolution &two) const {
00177
00178 register const double
00179 *x1 = one.x (),
00180 *x2 = two.x ();
00181
00182 register int n = one.n ();
00183
00184 while (n--)
00185 if ((*x1++ - *x2++) <= COMP_TOLERANCE)
00186 return true;
00187
00188 return false;
00189 }
00190
00193 void CouenneFPpool::findClosestAndReplace (double *sol, double *nSol, int nvars) {
00194
00195 double bestdist = COIN_DBL_MAX;
00196 std::set <CouenneFPsolution>::iterator bestsol = set_. end ();
00197
00198 if( nSol )
00199 {
00200 for (std::set <CouenneFPsolution>::iterator i = set_. begin ();
00201 i != set_. end (); ++i)
00202 {
00203
00204
00205 register double
00206 dist = 0.0,
00207 delta;
00208
00209 const register double
00210 *x = i -> x (),
00211 *s = nSol;
00212
00213 register bool move_on = false;
00214
00215 for (int j = nvars; j--;) {
00216
00217 delta = *x++ - *s++;
00218
00219 dist += delta * delta;
00220
00221 if (dist >= bestdist) {
00222
00223 move_on = true;
00224 break;
00225 }
00226 }
00227
00228 if (move_on)
00229 continue;
00230
00231
00232 if( dist < bestdist )
00233 {
00234 bestdist = dist;
00235 bestsol = i;
00236 }
00237 }
00238 }
00239 else
00240 bestsol = set_. begin ();
00241
00242 if( bestsol != set_. end () )
00243 {
00244 sol = CoinCopyOfArray ((*bestsol).x(), nvars);
00245 set_. erase(bestsol);
00246 }
00247 }