/home/coin/SVN-release/CoinAll-1.1.0/Vol/src/VolVolume.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #ifndef __VOLUME_HPP__
00004 #define __VOLUME_HPP__
00005 
00006 #include <cfloat>
00007 #include <algorithm>
00008 #include <cstdio>
00009 #include <cmath>
00010 
00011 #ifndef VOL_DEBUG
00012 // When VOL_DEBUG is 1, we check vector indices
00013 #define VOL_DEBUG 0
00014 #endif
00015 
00016 template <class T> static inline T
00017 VolMax(register const T x, register const T y) {
00018    return ((x) > (y)) ? (x) : (y);
00019 }
00020 
00021 template <class T> static inline T
00022 VolAbs(register const T x) {
00023    return ((x) > 0) ? (x) : -(x);
00024 }
00025 
00026 //############################################################################
00027 
00028 #if defined(VOL_DEBUG) && (VOL_DEBUG != 0)
00029 #define VOL_TEST_INDEX(i, size)                 \
00030 {                                               \
00031    if ((i) < 0 || (i) >= (size)) {              \
00032       printf("bad VOL_?vector index\n");        \
00033       abort();                                  \
00034    }                                            \
00035 }
00036 #define VOL_TEST_SIZE(size)                     \
00037 {                                               \
00038    if (s <= 0) {                                \
00039       printf("bad VOL_?vector size\n");         \
00040       abort();                                  \
00041    }                                            \
00042 }
00043 #else
00044 #define VOL_TEST_INDEX(i, size)
00045 #define VOL_TEST_SIZE(size)
00046 #endif
00047       
00048 //############################################################################
00049 
00050 class VOL_dvector;
00051 class VOL_ivector;
00052 class VOL_primal;
00053 class VOL_dual;
00054 class VOL_swing;
00055 class VOL_alpha_factor;
00056 class VOL_vh;
00057 class VOL_indc;
00058 class VOL_user_hooks;
00059 class VOL_problem;
00060 
00061 //############################################################################
00062 
00066 struct VOL_parms {
00068    double lambdainit; 
00070    double alphainit; 
00072    double alphamin;
00074    double alphafactor;
00075 
00077    double ubinit;
00078 
00080    double primal_abs_precision;
00082    double gap_abs_precision; 
00084    double gap_rel_precision;  
00086    double granularity;
00087 
00090    double minimum_rel_ascent;
00092    int    ascent_first_check;
00095    int    ascent_check_invl;
00096    
00098    int    maxsgriters; 
00099 
00110    int    printflag; 
00112    int    printinvl; 
00114    int    heurinvl; 
00115 
00118    int greentestinvl; 
00121    int yellowtestinvl; 
00124    int redtestinvl;
00125 
00127    int    alphaint; 
00128 
00130    char* temp_dualfile;
00131 };
00132 
00133 //############################################################################
00134 
00143 class VOL_dvector {
00144 public:
00146    double* v;
00148    int sz;
00149 
00150 public:
00152    VOL_dvector(const int s) {
00153       VOL_TEST_SIZE(s);
00154       v = new double[sz = s];
00155    }
00157    VOL_dvector() : v(0), sz(0) {}
00159    VOL_dvector(const VOL_dvector& x) : v(0), sz(0) {
00160       sz = x.sz;
00161       if (sz > 0) {
00162          v = new double[sz];
00163          std::copy(x.v, x.v + sz, v);
00164       }
00165    }
00167    ~VOL_dvector() { delete[] v; }
00168 
00170    inline int size() const {return sz;}
00171 
00173    inline double& operator[](const int i) {
00174       VOL_TEST_INDEX(i, sz);
00175       return v[i];
00176    }
00177 
00179    inline double operator[](const int i) const {
00180       VOL_TEST_INDEX(i, sz);
00181       return v[i];
00182    }
00183 
00186    inline void clear() {
00187       delete[] v;
00188       v = 0;
00189       sz = 0;
00190    }
00193    inline void cc(const double gamma, const VOL_dvector& w) {
00194       if (sz != w.sz) {
00195          printf("bad VOL_dvector sizes\n");
00196          abort();
00197       }
00198       double * p_v = v - 1;
00199       const double * p_w = w.v - 1;
00200       const double * const p_e = v + sz;
00201       const double one_gamma = 1.0 - gamma;
00202       while ( ++p_v != p_e ){
00203          *p_v = one_gamma * (*p_v) + gamma * (*++p_w);
00204       }
00205    }
00206 
00209    inline void allocate(const int s) {
00210       VOL_TEST_SIZE(s);
00211       delete[] v;                 
00212       v = new double[sz = s];
00213    }
00214 
00216    inline void swap(VOL_dvector& w) {
00217       std::swap(v, w.v);
00218       std::swap(sz, w.sz);
00219    }
00220 
00222    VOL_dvector& operator=(const VOL_dvector& w);
00224    VOL_dvector& operator=(const double w);
00225 };
00226 
00227 //-----------------------------------------------------------------------------
00237 class VOL_ivector {
00238 public:
00240    int* v;
00242    int sz;
00243 public:
00245    VOL_ivector(const int s) {
00246       VOL_TEST_SIZE(s);
00247       v = new int[sz = s];
00248    }
00250    VOL_ivector() : v(0), sz(0) {}
00252    VOL_ivector(const VOL_ivector& x) {
00253       sz = x.sz;
00254       if (sz > 0) {
00255          v = new int[sz];
00256          std::copy(x.v, x.v + sz, v);
00257       }
00258    }
00260    ~VOL_ivector(){
00261       delete [] v;
00262    }
00263 
00265    inline int size() const { return sz; }
00267    inline int& operator[](const int i) {
00268       VOL_TEST_INDEX(i, sz);
00269       return v[i];
00270    }
00271 
00273    inline int operator[](const int i) const {
00274       VOL_TEST_INDEX(i, sz);
00275       return v[i];
00276    }
00277 
00280    inline void clear() {
00281       delete[] v;
00282       v = 0;
00283       sz = 0;
00284    }
00285 
00288    inline void allocate(const int s) {
00289       VOL_TEST_SIZE(s);
00290       delete[] v;
00291       v = new int[sz = s];
00292    }
00293 
00295    inline void swap(VOL_ivector& w) {
00296       std::swap(v, w.v);
00297       std::swap(sz, w.sz);
00298    }
00299 
00301    VOL_ivector& operator=(const VOL_ivector& v);      
00303    VOL_ivector& operator=(const int w);
00304 };
00305 
00306 //############################################################################
00307 // A class describing a primal solution. This class is used only internally 
00308 class VOL_primal {
00309 public: 
00310    // objective value of this primal solution 
00311    double value;
00312    // the largest of the v[i]'s
00313    double viol;  
00314    // primal solution  
00315    VOL_dvector x;
00316    // v=b-Ax, for the relaxed constraints
00317    VOL_dvector v; 
00318 
00319    VOL_primal(const int psize, const int dsize) : x(psize), v(dsize) {}
00320    VOL_primal(const VOL_primal& primal) :
00321       value(primal.value), viol(primal.viol), x(primal.x), v(primal.v) {}
00322    ~VOL_primal() {}
00323    inline VOL_primal& operator=(const VOL_primal& p) {
00324       if (this == &p) 
00325          return *this;
00326       value = p.value;
00327       viol = p.viol;
00328       x = p.x;
00329       v = p.v;
00330       return *this;
00331    }
00332 
00333    // convex combination. data members in this will be overwritten
00334    // convex combination between two primal solutions
00335    // x <-- alpha x + (1 - alpha) p.x
00336    // v <-- alpha v + (1 - alpha) p.v
00337    inline void cc(const double alpha, const VOL_primal& p) {
00338       value = alpha * p.value + (1.0 - alpha) * value;
00339       x.cc(alpha, p.x);
00340       v.cc(alpha, p.v);
00341    }
00342    // find maximum of v[i]
00343    void find_max_viol(const VOL_dvector& dual_lb, 
00344                       const VOL_dvector& dual_ub);
00345 };
00346 
00347 //-----------------------------------------------------------------------------
00348 // A class describing a dual solution. This class is used only internally 
00349 class VOL_dual {
00350 public:
00351    // lagrangian value
00352    double lcost; 
00353    // reduced costs * (pstar-primal)
00354    double xrc;
00355    // this information is only printed
00356    // dual vector
00357    VOL_dvector u; 
00358 
00359    VOL_dual(const int dsize) : u(dsize) { u = 0.0;}
00360    VOL_dual(const VOL_dual& dual) :
00361       lcost(dual.lcost), xrc(dual.xrc), u(dual.u) {}
00362    ~VOL_dual() {}
00363    inline VOL_dual& operator=(const VOL_dual& p) {
00364       if (this == &p) 
00365          return *this;
00366       lcost = p.lcost;
00367       xrc = p.xrc;
00368       u = p.u;
00369       return *this;
00370    }
00371    // dual step
00372    void   step(const double target, const double lambda,
00373                const VOL_dvector& dual_lb, const VOL_dvector& dual_ub,
00374                const VOL_dvector& v);
00375    double ascent(const VOL_dvector& v, const VOL_dvector& last_u) const;
00376    void   compute_xrc(const VOL_dvector& pstarx, const VOL_dvector& primalx,
00377                       const VOL_dvector& rc);
00378 
00379 };
00380 
00381 
00382 //############################################################################
00383 /* here we check whether an iteration is green, yellow or red. Also according
00384    to this information we decide whether lambda should be changed */
00385 class VOL_swing {
00386 private:
00387    VOL_swing(const VOL_swing&);
00388    VOL_swing& operator=(const VOL_swing&);
00389 public:
00390    enum condition {green, yellow, red} lastswing;
00391    int lastgreeniter, lastyellowiter, lastrediter;
00392    int ngs, nrs, nys;
00393    int rd;
00394    
00395    VOL_swing() {
00396       lastgreeniter = lastyellowiter = lastrediter = 0;
00397       ngs = nrs = nys = 0;
00398    }
00399    ~VOL_swing(){}
00400 
00401    inline void cond(const VOL_dual& dual, 
00402                     const double lcost, const double ascent, const int iter) {
00403       double eps = 1.e-3;
00404 
00405       if (ascent > 0.0  &&  lcost > dual.lcost + eps) {
00406          lastswing = green;
00407          lastgreeniter = iter;
00408          ++ngs;
00409          rd = 0;
00410       } else { 
00411          if (ascent <= 0  &&  lcost > dual.lcost) {
00412             lastswing = yellow;
00413             lastyellowiter = iter;
00414             ++nys;
00415             rd = 0;
00416          } else {
00417             lastswing = red;
00418             lastrediter = iter;
00419             ++nrs;
00420             rd = 1;
00421          }
00422       }
00423    }
00424 
00425    inline double
00426    lfactor(const VOL_parms& parm, const double lambda, const int iter) {
00427       double lambdafactor = 1.0;
00428       double eps = 5.e-4;
00429       int cons;
00430 
00431       switch (lastswing) {
00432        case green:
00433          cons = iter - VolMax(lastyellowiter, lastrediter);
00434          if (parm.printflag & 4)
00435             printf("      G: Consecutive Gs = %3d\n\n", cons);
00436          if (cons >= parm.greentestinvl && lambda < 2.0) {
00437             lastgreeniter = lastyellowiter = lastrediter = iter;
00438             lambdafactor = 2.0;
00439             if (parm.printflag & 2)
00440                printf("\n ---- increasing lamda to %g ----\n\n",
00441                       lambda * lambdafactor); 
00442          }
00443          break;
00444       
00445        case yellow:
00446          cons = iter - VolMax(lastgreeniter, lastrediter);
00447          if (parm.printflag & 4)
00448             printf("      Y: Consecutive Ys = %3d\n\n", cons);
00449          if (cons >= parm.yellowtestinvl) {
00450             lastgreeniter = lastyellowiter = lastrediter = iter;
00451             lambdafactor = 1.1;
00452             if (parm.printflag & 2)
00453                printf("\n **** increasing lamda to %g *****\n\n",
00454                       lambda * lambdafactor);
00455          }
00456          break;
00457       
00458        case red:
00459          cons = iter - VolMax(lastgreeniter, lastyellowiter);
00460          if (parm.printflag & 4)
00461             printf("      R: Consecutive Rs = %3d\n\n", cons);
00462          if (cons >= parm.redtestinvl && lambda > eps) {
00463             lastgreeniter = lastyellowiter = lastrediter = iter;
00464             lambdafactor = 0.67;
00465             if (parm.printflag & 2)
00466                printf("\n **** decreasing lamda to %g *****\n\n",
00467                       lambda * lambdafactor);
00468          } 
00469          break;
00470       }
00471       return lambdafactor;
00472    }
00473 
00474    inline void
00475    print() {
00476       printf("**** G= %i, Y= %i, R= %i ****\n", ngs, nys, nrs);
00477       ngs = nrs = nys = 0;  
00478    }
00479 };
00480 
00481 //############################################################################
00482 /* alpha should be decreased if after some number of iterations the objective
00483    has increased less that 1% */
00484 class VOL_alpha_factor {
00485 private:
00486    VOL_alpha_factor(const VOL_alpha_factor&);
00487    VOL_alpha_factor& operator=(const VOL_alpha_factor&);
00488 public:
00489    double lastvalue;
00490 
00491    VOL_alpha_factor() {lastvalue = -DBL_MAX;}
00492    ~VOL_alpha_factor() {}
00493 
00494    inline double factor(const VOL_parms& parm, const double lcost,
00495                         const double alpha) {
00496       if (alpha < parm.alphamin)
00497          return 1.0;
00498       register const double ll = VolAbs(lcost);
00499       const double x = ll > 10 ? (lcost-lastvalue)/ll : (lcost-lastvalue);
00500       lastvalue = lcost;
00501       return (x <= 0.01) ? parm.alphafactor : 1.0;
00502    }
00503 };
00504 
00505 //############################################################################
00506 /* here we compute the norm of the conjugate direction -hh-, the norm of the
00507    subgradient -norm-, the inner product between the subgradient and the 
00508    last conjugate direction -vh-, and the inner product between the new
00509    conjugate direction and the subgradient */
00510 class VOL_vh {
00511 private:
00512    VOL_vh(const VOL_vh&);
00513    VOL_vh& operator=(const VOL_vh&);
00514 public:
00515    double hh;
00516    double norm;
00517    double vh;
00518    double asc;
00519 
00520    VOL_vh(const double alpha,
00521           const VOL_dvector& dual_lb, const VOL_dvector& dual_ub,
00522           const VOL_dvector& v, const VOL_dvector& vstar,
00523           const VOL_dvector& u);
00524    ~VOL_vh(){}
00525 };
00526 
00527 //############################################################################
00528 /* here we compute different parameter to be printed. v2 is the square of 
00529    the norm of the subgradient. vu is the inner product between the dual
00530    variables and the subgradient. vabs is the maximum absolute value of
00531    the violations of pstar. asc is the inner product between the conjugate
00532    direction and the subgradient */
00533 class VOL_indc {
00534 private:
00535    VOL_indc(const VOL_indc&);
00536    VOL_indc& operator=(const VOL_indc&);
00537 public:
00538    double v2;
00539    double vu;
00540    double vabs;
00541    double asc;
00542 
00543 public:
00544    VOL_indc(const VOL_dvector& dual_lb, const VOL_dvector& dual_ub,
00545             const VOL_primal& primal, const VOL_primal& pstar,
00546             const VOL_dual& dual);
00547    ~VOL_indc() {}
00548 };
00549 
00550 //#############################################################################
00551 
00558 class VOL_user_hooks {
00559 public:
00560    virtual ~VOL_user_hooks() {}
00561 public:
00562    // for all hooks: return value of -1 means that volume should quit
00567    virtual int compute_rc(const VOL_dvector& u, VOL_dvector& rc) = 0;
00568 
00577    virtual int solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc,
00578                                 double& lcost, VOL_dvector& x, VOL_dvector& v,
00579                                 double& pcost) = 0;
00586    virtual int heuristics(const VOL_problem& p, 
00587                           const VOL_dvector& x, double& heur_val) = 0;
00588 };
00589 
00590 //#############################################################################
00591 
00600 class VOL_problem {
00601 private:
00602    VOL_problem(const VOL_problem&);
00603    VOL_problem& operator=(const VOL_problem&);
00604    void set_default_parm();
00605    // ############ INPUT fields ########################
00606 public: 
00610    VOL_problem();
00613    VOL_problem(const char *filename);
00615    ~VOL_problem();
00617 
00623    int solve(VOL_user_hooks& hooks, const bool use_preset_dual = false);
00625 
00626 private: 
00630    double alpha_; 
00632    double lambda_;
00633    // This union is here for padding (so that data members would be
00634    // double-aligned on x86 CPU
00635    union {
00637       int iter_;
00638       double __pad0;
00639    };
00641 
00642 public:
00643   
00647    double value;
00649    VOL_dvector dsol;
00651    VOL_dvector psol;
00653    VOL_dvector viol;
00655 
00659    VOL_parms parm;
00661    int psize;        
00663    int dsize;      
00666    VOL_dvector dual_lb;
00669    VOL_dvector dual_ub;
00671 
00672 public:
00676    int    iter() const { return iter_; }
00678    double alpha() const { return alpha_; }
00680    double lambda() const { return lambda_; }
00682 
00683 private:
00687    void read_params(const char* filename);
00688 
00690    int initialize(const bool use_preset_dual);
00691 
00693    void print_info(const int iter,
00694                    const VOL_primal& primal, const VOL_primal& pstar,
00695                    const VOL_dual& dual);
00696 
00699    double readjust_target(const double oldtarget, const double lcost) const;
00700 
00708    double power_heur(const VOL_primal& primal, const VOL_primal& pstar,
00709                      const VOL_dual& dual) const;
00711 };
00712 
00713 #endif

Generated on Sun Nov 14 14:06:42 2010 for Coin-All by  doxygen 1.4.7