/home/coin/SVN-release/Alps-1.2.1/Osi/test/OsiTestSolver.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 // this is a copy of VolVolume (stable/1.1 rev. 233)
00005 
00006 #ifndef __OSITESTSOLVER_HPP__
00007 #define __OSITESTSOLVER_HPP__
00008 
00009 #include <cfloat>
00010 #include <algorithm>
00011 #include <cstdio>
00012 #include <cmath>
00013 
00014 #ifndef VOL_DEBUG
00015 // When VOL_DEBUG is 1, we check vector indices
00016 #define VOL_DEBUG 0
00017 #endif
00018 
00019 template <class T> static inline T
00020 VolMax(register const T x, register const T y) {
00021    return ((x) > (y)) ? (x) : (y);
00022 }
00023 
00024 template <class T> static inline T
00025 VolAbs(register const T x) {
00026    return ((x) > 0) ? (x) : -(x);
00027 }
00028 
00029 //############################################################################
00030 
00031 #if defined(VOL_DEBUG) && (VOL_DEBUG != 0)
00032 #define VOL_TEST_INDEX(i, size)                 \
00033 {                                               \
00034    if ((i) < 0 || (i) >= (size)) {              \
00035       printf("bad VOL_?vector index\n");        \
00036       abort();                                  \
00037    }                                            \
00038 }
00039 #define VOL_TEST_SIZE(size)                     \
00040 {                                               \
00041    if (s <= 0) {                                \
00042       printf("bad VOL_?vector size\n");         \
00043       abort();                                  \
00044    }                                            \
00045 }
00046 #else
00047 #define VOL_TEST_INDEX(i, size)
00048 #define VOL_TEST_SIZE(size)
00049 #endif
00050       
00051 //############################################################################
00052 
00053 class VOL_dvector;
00054 class VOL_ivector;
00055 class VOL_primal;
00056 class VOL_dual;
00057 class VOL_swing;
00058 class VOL_alpha_factor;
00059 class VOL_vh;
00060 class VOL_indc;
00061 class VOL_user_hooks;
00062 class VOL_problem;
00063 
00064 //############################################################################
00065 
00069 struct VOL_parms {
00071    double lambdainit; 
00073    double alphainit; 
00075    double alphamin;
00077    double alphafactor;
00078 
00080    double ubinit;
00081 
00083    double primal_abs_precision;
00085    double gap_abs_precision; 
00087    double gap_rel_precision;  
00089    double granularity;
00090 
00093    double minimum_rel_ascent;
00095    int    ascent_first_check;
00098    int    ascent_check_invl;
00099    
00101    int    maxsgriters; 
00102 
00113    int    printflag; 
00115    int    printinvl; 
00117    int    heurinvl; 
00118 
00121    int greentestinvl; 
00124    int yellowtestinvl; 
00127    int redtestinvl;
00128 
00130    int    alphaint; 
00131 
00133    char* temp_dualfile;
00134 };
00135 
00136 //############################################################################
00137 
00146 class VOL_dvector {
00147 public:
00149    double* v;
00151    int sz;
00152 
00153 public:
00155    VOL_dvector(const int s) {
00156       VOL_TEST_SIZE(s);
00157       v = new double[sz = s];
00158    }
00160    VOL_dvector() : v(0), sz(0) {}
00162    VOL_dvector(const VOL_dvector& x) : v(0), sz(0) {
00163       sz = x.sz;
00164       if (sz > 0) {
00165          v = new double[sz];
00166          std::copy(x.v, x.v + sz, v);
00167       }
00168    }
00170    ~VOL_dvector() { delete[] v; }
00171 
00173    inline int size() const {return sz;}
00174 
00176    inline double& operator[](const int i) {
00177       VOL_TEST_INDEX(i, sz);
00178       return v[i];
00179    }
00180 
00182    inline double operator[](const int i) const {
00183       VOL_TEST_INDEX(i, sz);
00184       return v[i];
00185    }
00186 
00189    inline void clear() {
00190       delete[] v;
00191       v = 0;
00192       sz = 0;
00193    }
00196    inline void cc(const double gamma, const VOL_dvector& w) {
00197       if (sz != w.sz) {
00198          printf("bad VOL_dvector sizes\n");
00199          abort();
00200       }
00201       double * p_v = v - 1;
00202       const double * p_w = w.v - 1;
00203       const double * const p_e = v + sz;
00204       const double one_gamma = 1.0 - gamma;
00205       while ( ++p_v != p_e ){
00206          *p_v = one_gamma * (*p_v) + gamma * (*++p_w);
00207       }
00208    }
00209 
00212    inline void allocate(const int s) {
00213       VOL_TEST_SIZE(s);
00214       delete[] v;                 
00215       v = new double[sz = s];
00216    }
00217 
00219    inline void swap(VOL_dvector& w) {
00220       std::swap(v, w.v);
00221       std::swap(sz, w.sz);
00222    }
00223 
00225    VOL_dvector& operator=(const VOL_dvector& w);
00227    VOL_dvector& operator=(const double w);
00228 };
00229 
00230 //-----------------------------------------------------------------------------
00240 class VOL_ivector {
00241 public:
00243    int* v;
00245    int sz;
00246 public:
00248    VOL_ivector(const int s) {
00249       VOL_TEST_SIZE(s);
00250       v = new int[sz = s];
00251    }
00253    VOL_ivector() : v(0), sz(0) {}
00255    VOL_ivector(const VOL_ivector& x) {
00256       sz = x.sz;
00257       if (sz > 0) {
00258          v = new int[sz];
00259          std::copy(x.v, x.v + sz, v);
00260       }
00261    }
00263    ~VOL_ivector(){
00264       delete [] v;
00265    }
00266 
00268    inline int size() const { return sz; }
00270    inline int& operator[](const int i) {
00271       VOL_TEST_INDEX(i, sz);
00272       return v[i];
00273    }
00274 
00276    inline int operator[](const int i) const {
00277       VOL_TEST_INDEX(i, sz);
00278       return v[i];
00279    }
00280 
00283    inline void clear() {
00284       delete[] v;
00285       v = 0;
00286       sz = 0;
00287    }
00288 
00291    inline void allocate(const int s) {
00292       VOL_TEST_SIZE(s);
00293       delete[] v;
00294       v = new int[sz = s];
00295    }
00296 
00298    inline void swap(VOL_ivector& w) {
00299       std::swap(v, w.v);
00300       std::swap(sz, w.sz);
00301    }
00302 
00304    VOL_ivector& operator=(const VOL_ivector& v);      
00306    VOL_ivector& operator=(const int w);
00307 };
00308 
00309 //############################################################################
00310 // A class describing a primal solution. This class is used only internally 
00311 class VOL_primal {
00312 public: 
00313    // objective value of this primal solution 
00314    double value;
00315    // the largest of the v[i]'s
00316    double viol;  
00317    // primal solution  
00318    VOL_dvector x;
00319    // v=b-Ax, for the relaxed constraints
00320    VOL_dvector v; 
00321 
00322    VOL_primal(const int psize, const int dsize) : x(psize), v(dsize) {}
00323    VOL_primal(const VOL_primal& primal) :
00324       value(primal.value), viol(primal.viol), x(primal.x), v(primal.v) {}
00325    ~VOL_primal() {}
00326    inline VOL_primal& operator=(const VOL_primal& p) {
00327       if (this == &p) 
00328          return *this;
00329       value = p.value;
00330       viol = p.viol;
00331       x = p.x;
00332       v = p.v;
00333       return *this;
00334    }
00335 
00336    // convex combination. data members in this will be overwritten
00337    // convex combination between two primal solutions
00338    // x <-- alpha x + (1 - alpha) p.x
00339    // v <-- alpha v + (1 - alpha) p.v
00340    inline void cc(const double alpha, const VOL_primal& p) {
00341       value = alpha * p.value + (1.0 - alpha) * value;
00342       x.cc(alpha, p.x);
00343       v.cc(alpha, p.v);
00344    }
00345    // find maximum of v[i]
00346    void find_max_viol(const VOL_dvector& dual_lb, 
00347                       const VOL_dvector& dual_ub);
00348 };
00349 
00350 //-----------------------------------------------------------------------------
00351 // A class describing a dual solution. This class is used only internally 
00352 class VOL_dual {
00353 public:
00354    // lagrangian value
00355    double lcost; 
00356    // reduced costs * (pstar-primal)
00357    double xrc;
00358    // this information is only printed
00359    // dual vector
00360    VOL_dvector u; 
00361 
00362    VOL_dual(const int dsize) : u(dsize) { u = 0.0;}
00363    VOL_dual(const VOL_dual& dual) :
00364       lcost(dual.lcost), xrc(dual.xrc), u(dual.u) {}
00365    ~VOL_dual() {}
00366    inline VOL_dual& operator=(const VOL_dual& p) {
00367       if (this == &p) 
00368          return *this;
00369       lcost = p.lcost;
00370       xrc = p.xrc;
00371       u = p.u;
00372       return *this;
00373    }
00374    // dual step
00375    void   step(const double target, const double lambda,
00376                const VOL_dvector& dual_lb, const VOL_dvector& dual_ub,
00377                const VOL_dvector& v);
00378    double ascent(const VOL_dvector& v, const VOL_dvector& last_u) const;
00379    void   compute_xrc(const VOL_dvector& pstarx, const VOL_dvector& primalx,
00380                       const VOL_dvector& rc);
00381 
00382 };
00383 
00384 
00385 //############################################################################
00386 /* here we check whether an iteration is green, yellow or red. Also according
00387    to this information we decide whether lambda should be changed */
00388 class VOL_swing {
00389 private:
00390    VOL_swing(const VOL_swing&);
00391    VOL_swing& operator=(const VOL_swing&);
00392 public:
00393    enum condition {green, yellow, red} lastswing;
00394    int lastgreeniter, lastyellowiter, lastrediter;
00395    int ngs, nrs, nys;
00396    int rd;
00397    
00398    VOL_swing() {
00399       lastgreeniter = lastyellowiter = lastrediter = 0;
00400       ngs = nrs = nys = 0;
00401    }
00402    ~VOL_swing(){}
00403 
00404    inline void cond(const VOL_dual& dual, 
00405                     const double lcost, const double ascent, const int iter) {
00406       double eps = 1.e-3;
00407 
00408       if (ascent > 0.0  &&  lcost > dual.lcost + eps) {
00409          lastswing = green;
00410          lastgreeniter = iter;
00411          ++ngs;
00412          rd = 0;
00413       } else { 
00414          if (ascent <= 0  &&  lcost > dual.lcost) {
00415             lastswing = yellow;
00416             lastyellowiter = iter;
00417             ++nys;
00418             rd = 0;
00419          } else {
00420             lastswing = red;
00421             lastrediter = iter;
00422             ++nrs;
00423             rd = 1;
00424          }
00425       }
00426    }
00427 
00428    inline double
00429    lfactor(const VOL_parms& parm, const double lambda, const int iter) {
00430       double lambdafactor = 1.0;
00431       double eps = 5.e-4;
00432       int cons;
00433 
00434       switch (lastswing) {
00435        case green:
00436          cons = iter - VolMax(lastyellowiter, lastrediter);
00437          if (parm.printflag & 4)
00438             printf("      G: Consecutive Gs = %3d\n\n", cons);
00439          if (cons >= parm.greentestinvl && lambda < 2.0) {
00440             lastgreeniter = lastyellowiter = lastrediter = iter;
00441             lambdafactor = 2.0;
00442             if (parm.printflag & 2)
00443                printf("\n ---- increasing lamda to %g ----\n\n",
00444                       lambda * lambdafactor); 
00445          }
00446          break;
00447       
00448        case yellow:
00449          cons = iter - VolMax(lastgreeniter, lastrediter);
00450          if (parm.printflag & 4)
00451             printf("      Y: Consecutive Ys = %3d\n\n", cons);
00452          if (cons >= parm.yellowtestinvl) {
00453             lastgreeniter = lastyellowiter = lastrediter = iter;
00454             lambdafactor = 1.1;
00455             if (parm.printflag & 2)
00456                printf("\n **** increasing lamda to %g *****\n\n",
00457                       lambda * lambdafactor);
00458          }
00459          break;
00460       
00461        case red:
00462          cons = iter - VolMax(lastgreeniter, lastyellowiter);
00463          if (parm.printflag & 4)
00464             printf("      R: Consecutive Rs = %3d\n\n", cons);
00465          if (cons >= parm.redtestinvl && lambda > eps) {
00466             lastgreeniter = lastyellowiter = lastrediter = iter;
00467             lambdafactor = 0.67;
00468             if (parm.printflag & 2)
00469                printf("\n **** decreasing lamda to %g *****\n\n",
00470                       lambda * lambdafactor);
00471          } 
00472          break;
00473       }
00474       return lambdafactor;
00475    }
00476 
00477    inline void
00478    print() {
00479       printf("**** G= %i, Y= %i, R= %i ****\n", ngs, nys, nrs);
00480       ngs = nrs = nys = 0;  
00481    }
00482 };
00483 
00484 //############################################################################
00485 /* alpha should be decreased if after some number of iterations the objective
00486    has increased less that 1% */
00487 class VOL_alpha_factor {
00488 private:
00489    VOL_alpha_factor(const VOL_alpha_factor&);
00490    VOL_alpha_factor& operator=(const VOL_alpha_factor&);
00491 public:
00492    double lastvalue;
00493 
00494    VOL_alpha_factor() {lastvalue = -DBL_MAX;}
00495    ~VOL_alpha_factor() {}
00496 
00497    inline double factor(const VOL_parms& parm, const double lcost,
00498                         const double alpha) {
00499       if (alpha < parm.alphamin)
00500          return 1.0;
00501       register const double ll = VolAbs(lcost);
00502       const double x = ll > 10 ? (lcost-lastvalue)/ll : (lcost-lastvalue);
00503       lastvalue = lcost;
00504       return (x <= 0.01) ? parm.alphafactor : 1.0;
00505    }
00506 };
00507 
00508 //############################################################################
00509 /* here we compute the norm of the conjugate direction -hh-, the norm of the
00510    subgradient -norm-, the inner product between the subgradient and the 
00511    last conjugate direction -vh-, and the inner product between the new
00512    conjugate direction and the subgradient */
00513 class VOL_vh {
00514 private:
00515    VOL_vh(const VOL_vh&);
00516    VOL_vh& operator=(const VOL_vh&);
00517 public:
00518    double hh;
00519    double norm;
00520    double vh;
00521    double asc;
00522 
00523    VOL_vh(const double alpha,
00524           const VOL_dvector& dual_lb, const VOL_dvector& dual_ub,
00525           const VOL_dvector& v, const VOL_dvector& vstar,
00526           const VOL_dvector& u);
00527    ~VOL_vh(){}
00528 };
00529 
00530 //############################################################################
00531 /* here we compute different parameter to be printed. v2 is the square of 
00532    the norm of the subgradient. vu is the inner product between the dual
00533    variables and the subgradient. vabs is the maximum absolute value of
00534    the violations of pstar. asc is the inner product between the conjugate
00535    direction and the subgradient */
00536 class VOL_indc {
00537 private:
00538    VOL_indc(const VOL_indc&);
00539    VOL_indc& operator=(const VOL_indc&);
00540 public:
00541    double v2;
00542    double vu;
00543    double vabs;
00544    double asc;
00545 
00546 public:
00547    VOL_indc(const VOL_dvector& dual_lb, const VOL_dvector& dual_ub,
00548             const VOL_primal& primal, const VOL_primal& pstar,
00549             const VOL_dual& dual);
00550    ~VOL_indc() {}
00551 };
00552 
00553 //#############################################################################
00554 
00561 class VOL_user_hooks {
00562 public:
00563    virtual ~VOL_user_hooks() {}
00564 public:
00565    // for all hooks: return value of -1 means that volume should quit
00570    virtual int compute_rc(const VOL_dvector& u, VOL_dvector& rc) = 0;
00571 
00580    virtual int solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc,
00581                                 double& lcost, VOL_dvector& x, VOL_dvector& v,
00582                                 double& pcost) = 0;
00589    virtual int heuristics(const VOL_problem& p, 
00590                           const VOL_dvector& x, double& heur_val) = 0;
00591 };
00592 
00593 //#############################################################################
00594 
00603 class VOL_problem {
00604 private:
00605    VOL_problem(const VOL_problem&);
00606    VOL_problem& operator=(const VOL_problem&);
00607    void set_default_parm();
00608    // ############ INPUT fields ########################
00609 public: 
00613    VOL_problem();
00616    VOL_problem(const char *filename);
00618    ~VOL_problem();
00620 
00626    int solve(VOL_user_hooks& hooks, const bool use_preset_dual = false);
00628 
00629 private: 
00633    double alpha_; 
00635    double lambda_;
00636    // This union is here for padding (so that data members would be
00637    // double-aligned on x86 CPU
00638    union {
00640       int iter_;
00641       double __pad0;
00642    };
00644 
00645 public:
00646   
00650    double value;
00652    VOL_dvector dsol;
00654    VOL_dvector psol;
00656    VOL_dvector viol;
00658 
00662    VOL_parms parm;
00664    int psize;        
00666    int dsize;      
00669    VOL_dvector dual_lb;
00672    VOL_dvector dual_ub;
00674 
00675 public:
00679    int    iter() const { return iter_; }
00681    double alpha() const { return alpha_; }
00683    double lambda() const { return lambda_; }
00685 
00686 private:
00690    void read_params(const char* filename);
00691 
00693    int initialize(const bool use_preset_dual);
00694 
00696    void print_info(const int iter,
00697                    const VOL_primal& primal, const VOL_primal& pstar,
00698                    const VOL_dual& dual);
00699 
00702    double readjust_target(const double oldtarget, const double lcost) const;
00703 
00711    double power_heur(const VOL_primal& primal, const VOL_primal& pstar,
00712                      const VOL_dual& dual) const;
00714 };
00715 
00716 #endif

Generated on Fri Dec 31 03:01:56 2010 by  doxygen 1.4.7