TQpSolverBase.cxx

Go to the documentation of this file.
00001 // @(#)root/quadp:$Id: TQpSolverBase.cxx 35018 2010-08-25 16:40:46Z moneta $
00002 // Author: Eddy Offermann   May 2004
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 /*************************************************************************
00013  * Parts of this file are copied from the OOQP distribution and          *
00014  * are subject to the following license:                                 *
00015  *                                                                       *
00016  * COPYRIGHT 2001 UNIVERSITY OF CHICAGO                                  *
00017  *                                                                       *
00018  * The copyright holder hereby grants you royalty-free rights to use,    *
00019  * reproduce, prepare derivative works, and to redistribute this software*
00020  * to others, provided that any changes are clearly documented. This     *
00021  * software was authored by:                                             *
00022  *                                                                       *
00023  *   E. MICHAEL GERTZ      gertz@mcs.anl.gov                             *
00024  *   Mathematics and Computer Science Division                           *
00025  *   Argonne National Laboratory                                         *
00026  *   9700 S. Cass Avenue                                                 *
00027  *   Argonne, IL 60439-4844                                              *
00028  *                                                                       *
00029  *   STEPHEN J. WRIGHT     swright@cs.wisc.edu                           *
00030  *   Computer Sciences Department                                        *
00031  *   University of Wisconsin                                             *
00032  *   1210 West Dayton Street                                             *
00033  *   Madison, WI 53706   FAX: (608)262-9777                              *
00034  *                                                                       *
00035  * Any questions or comments may be directed to one of the authors.      *
00036  *                                                                       *
00037  * ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES OF   *
00038  * ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT, AND     *
00039  * OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A CONTRACT   *
00040  * WITH THE DEPARTMENT OF ENERGY.                                        *
00041  *************************************************************************/
00042 
00043 //////////////////////////////////////////////////////////////////////////
00044 //                                                                      //
00045 // TSolverBase                                                          //
00046 //                                                                      //
00047 // The Solver class contains methods for monitoring and checking the    //
00048 // convergence status of the algorithm, methods to determine the step   //
00049 // length along a given direction, methods to define the starting point,//
00050 // and the solve method that implements the interior-point algorithm    //
00051 //                                                                      //
00052 //////////////////////////////////////////////////////////////////////////
00053 
00054 #include "TMath.h"
00055 #include "TQpSolverBase.h"
00056 
00057 ClassImp(TQpSolverBase)
00058 
00059 //______________________________________________________________________________
00060 TQpSolverBase::TQpSolverBase()
00061 {
00062 // Default constructor
00063 
00064    fSys = 0;
00065 
00066    fDnorm = 0.;
00067 
00068    // define parameters associated with the step length heuristic
00069    fMutol   = 1.0e-8;
00070    fArtol   = 1.0e-8;
00071    fGamma_f = 0.99;
00072    fGamma_a = 1.0/(1.0-fGamma_f);
00073 
00074    fPhi   = 0.0;
00075 
00076    fMaxit = 100;
00077 
00078    // allocate space to track the sequence of complementarity gaps,
00079    // residual norms, and merit functions.
00080    fMu_history      = new Double_t[fMaxit];
00081    fRnorm_history   = new Double_t[fMaxit];
00082    fPhi_history     = new Double_t[fMaxit];
00083    fPhi_min_history = new Double_t[fMaxit];
00084 
00085    fIter = 0;
00086 }
00087 
00088 
00089 //______________________________________________________________________________
00090 TQpSolverBase::TQpSolverBase(const TQpSolverBase &another) : TObject(another)
00091 {
00092 // Copy constructor
00093 
00094    *this = another;
00095 }
00096 
00097 
00098 //______________________________________________________________________________
00099 TQpSolverBase::~TQpSolverBase()
00100 {
00101 // Deconstructor
00102 
00103    if (fSys) { delete fSys; fSys = 0; }
00104 
00105    if (fMu_history) { delete [] fMu_history;      fMu_history      = 0; }
00106    if (fMu_history) { delete [] fRnorm_history;   fRnorm_history   = 0; }
00107    if (fMu_history) { delete [] fPhi_history;     fPhi_history     = 0; }
00108    if (fMu_history) { delete [] fPhi_min_history; fPhi_min_history = 0; }
00109 }
00110 
00111 
00112 //______________________________________________________________________________
00113 void TQpSolverBase::Start(TQpProbBase *formulation,TQpVar *iterate,TQpDataBase *prob,
00114                           TQpResidual *resid,TQpVar *step)
00115 {
00116 // Implements a default starting-point heuristic. While interior-point theory
00117 //  places fairly loose restrictions on the choice of starting point, the choice 
00118 // of heuristic can significantly affect the robustness and efficiency of the
00119 //  algorithm.
00120 
00121    this->DefStart(formulation,iterate,prob,resid,step);
00122 }
00123 
00124 
00125 //______________________________________________________________________________
00126 void TQpSolverBase::DefStart(TQpProbBase * /* formulation */,TQpVar *iterate,
00127                              TQpDataBase *prob,TQpResidual *resid,TQpVar *step)
00128 {
00129 // Default starting point
00130 
00131    Double_t sdatanorm = TMath::Sqrt(fDnorm);
00132    Double_t a         = sdatanorm;
00133    Double_t b         = sdatanorm;
00134 
00135    iterate->InteriorPoint(a,b);
00136    resid->CalcResids(prob,iterate);
00137    resid->Set_r3_xz_alpha(iterate,0.0);
00138 
00139    fSys->Factor(prob,iterate);
00140    fSys->Solve(prob,iterate,resid,step);
00141    step->Negate();
00142 
00143    // Take the full affine scaling step
00144    iterate->Saxpy(step,1.0);
00145    // resid.CalcResids(prob,iterate); // Calc the resids if debugging.
00146    Double_t shift = 1.e3+2*iterate->Violation();
00147    iterate->ShiftBoundVariables(shift,shift);
00148 }
00149 
00150 
00151 //______________________________________________________________________________
00152 void TQpSolverBase::SteveStart(TQpProbBase * /* formulation */,
00153                                TQpVar *iterate,TQpDataBase *prob,
00154                                TQpResidual *resid,TQpVar *step)
00155 {
00156 // Starting point algoritm according to Stephen Wright
00157 
00158    Double_t sdatanorm = TMath::Sqrt(fDnorm);
00159    Double_t a = 0.0;
00160    Double_t b = 0.0;
00161 
00162    iterate->InteriorPoint(a,b);
00163 
00164    // set the r3 component of the rhs to -(norm of data), and calculate
00165    // the residuals that are obtained when all values are zero.
00166 
00167    resid->Set_r3_xz_alpha(iterate,-sdatanorm);
00168    resid->CalcResids(prob,iterate);
00169 
00170    // next, assign 1 to all the complementary variables, so that there
00171    // are identities in the coefficient matrix when we do the solve.
00172 
00173    a = 1.0; b = 1.0;
00174    iterate->InteriorPoint(a,b);
00175    fSys->Factor(prob,iterate);
00176    fSys->Solve (prob,iterate,resid,step);
00177    step->Negate();
00178 
00179    // copy the "step" into the current vector
00180 
00181    iterate = step;
00182 
00183    // calculate the maximum violation of the complementarity
00184    // conditions, and shift these variables to restore positivity.
00185    Double_t shift = 1.5*iterate->Violation();
00186    iterate->ShiftBoundVariables(shift,shift);
00187 
00188    // do Mehrotra-type adjustment
00189 
00190    const Double_t mutemp = iterate->GetMu();
00191    const Double_t xsnorm = iterate->Norm1();
00192    const Double_t delta = 0.5*iterate->fNComplementaryVariables*mutemp/xsnorm;
00193    iterate->ShiftBoundVariables(delta,delta);
00194 }
00195 
00196 
00197 //______________________________________________________________________________
00198 void TQpSolverBase::DumbStart(TQpProbBase * /* formulation */,
00199                               TQpVar *iterate,TQpDataBase * /* prob */,
00200                               TQpResidual * /* resid */,TQpVar * /* step */)
00201 {
00202 // Alternative starting point heuristic: sets the "complementary" variables to a large
00203 // positive value (based on the norm of the problem data) and the remaining variables
00204 // to zero .
00205 
00206    const Double_t sdatanorm = fDnorm;
00207    const Double_t a = 1.e3;
00208    const Double_t b = 1.e5;
00209    const Double_t bigstart = a*sdatanorm+b;
00210    iterate->InteriorPoint(bigstart,bigstart);
00211 }
00212 
00213 
00214 //______________________________________________________________________________
00215 Double_t TQpSolverBase::FinalStepLength(TQpVar *iterate,TQpVar *step)
00216 {
00217 // Implements a version of Mehrotra starting point heuristic,
00218 //  modified to ensure identical steps in the primal and dual variables.
00219 
00220    Int_t firstOrSecond;
00221    Double_t primalValue; Double_t primalStep; Double_t dualValue; Double_t dualStep;
00222    const Double_t maxAlpha = iterate->FindBlocking(step,primalValue,primalStep,
00223       dualValue,dualStep,firstOrSecond);
00224    Double_t mufull = iterate->MuStep(step,maxAlpha);
00225 
00226    mufull /= fGamma_a;
00227 
00228    Double_t alpha = 1.0;
00229    switch (firstOrSecond) {
00230       case 0:
00231          alpha = 1;              // No constraints were blocking
00232          break;
00233       case 1:
00234          alpha = (-primalValue+mufull/(dualValue+maxAlpha*dualStep))/primalStep;
00235          break;
00236       case 2:
00237          alpha = (-dualValue+mufull/(primalValue+maxAlpha*primalStep))/dualStep;
00238          break;
00239       default:
00240          R__ASSERT(0 && "Can't get here");
00241          break;
00242    }
00243    // make it at least fGamma_f * maxStep
00244    if (alpha < fGamma_f*maxAlpha) alpha = fGamma_f*maxAlpha;
00245    // back off just a touch
00246    alpha *= .99999999;
00247 
00248    return alpha;
00249 }
00250 
00251 
00252 //______________________________________________________________________________
00253 void TQpSolverBase::DoMonitor(TQpDataBase *data,TQpVar *vars,TQpResidual *resids,
00254                               Double_t alpha,Double_t sigma,Int_t i,Double_t mu,
00255                               Int_t stop_code,Int_t level)
00256 {
00257 // Monitor progress / convergence aat each interior-point iteration
00258 
00259    this->DefMonitor(data,vars,resids,alpha,sigma,i,mu,stop_code,level);
00260 }
00261 
00262 
00263 //______________________________________________________________________________
00264 Int_t TQpSolverBase::DoStatus(TQpDataBase *data,TQpVar *vars,TQpResidual *resids,
00265                               Int_t i,Double_t mu,Int_t level)
00266 {
00267 // Tests for termination. Unless the user supplies a specific termination 
00268 // routine, this method calls another method defaultStatus, which returns 
00269 // a code indicating the current convergence status.
00270 
00271    return this->DefStatus(data,vars,resids,i,mu,level);
00272 }
00273 
00274 
00275 //______________________________________________________________________________
00276 Int_t TQpSolverBase::DefStatus(TQpDataBase * /* data */,TQpVar * /* vars */,
00277                                TQpResidual *resids,Int_t iterate,Double_t mu,Int_t /* level */)
00278 {
00279 // Default status method
00280 
00281    Int_t stop_code = kNOT_FINISHED;
00282 
00283    const Double_t gap   = TMath::Abs(resids->GetDualityGap());
00284    const Double_t rnorm = resids->GetResidualNorm();
00285 
00286    Int_t idx = iterate-1;
00287    if (idx <  0     ) idx = 0;
00288    if (idx >= fMaxit) idx = fMaxit-1;
00289 
00290    // store the historical record
00291    fMu_history[idx] = mu;
00292    fRnorm_history[idx] = rnorm;
00293    fPhi = (rnorm+gap)/fDnorm;
00294    fPhi_history[idx] = fPhi;
00295 
00296    if (idx > 0) {
00297       fPhi_min_history[idx] = fPhi_min_history[idx-1];
00298       if (fPhi < fPhi_min_history[idx]) fPhi_min_history[idx] = fPhi;
00299    } else
00300    fPhi_min_history[idx] = fPhi;
00301 
00302    if (iterate >= fMaxit) {
00303       stop_code = kMAX_ITS_EXCEEDED;
00304    }
00305    else if (mu <= fMutol && rnorm <= fArtol*fDnorm) {
00306       stop_code = kSUCCESSFUL_TERMINATION;
00307    }
00308    if (stop_code != kNOT_FINISHED)  return stop_code;
00309 
00310    // check infeasibility condition
00311    if (idx >= 10 && fPhi >= 1.e-8 && fPhi >= 1.e4*fPhi_min_history[idx])
00312       stop_code = kINFEASIBLE;
00313    if (stop_code != kNOT_FINISHED)  return stop_code;
00314 
00315    // check for unknown status: slow convergence first
00316    if (idx >= 30 && fPhi_min_history[idx] >= .5*fPhi_min_history[idx-30])
00317       stop_code = kUNKNOWN;
00318 
00319    if (rnorm/fDnorm > fArtol &&
00320       (fRnorm_history[idx]/fMu_history[idx])/(fRnorm_history[0]/fMu_history[0]) >= 1.e8)
00321       stop_code = kUNKNOWN;
00322 
00323    return stop_code;
00324 }
00325 
00326 
00327 //______________________________________________________________________________
00328 TQpSolverBase &TQpSolverBase::operator=(const TQpSolverBase &source)
00329 {
00330 // Assignment operator
00331 
00332    if (this != &source) {
00333       TObject::operator=(source);
00334 
00335       fSys     = source.fSys;
00336       fDnorm   = source.fDnorm;
00337       fMutol   = source.fMutol;
00338       fArtol   = source.fArtol;
00339       fGamma_f = source.fGamma_f;
00340       fGamma_a = source.fGamma_a;
00341       fPhi     = source.fPhi;
00342       fIter    = source.fIter;
00343 
00344       if (fMaxit != source.fMaxit) {
00345          if (fMu_history) delete [] fMu_history;
00346          fMu_history = new Double_t[fMaxit];
00347          if (fRnorm_history) delete [] fRnorm_history;
00348          fRnorm_history = new Double_t[fMaxit];
00349          if (fPhi_history) delete [] fPhi_history;
00350          fPhi_history = new Double_t[fMaxit];
00351          if (fPhi_min_history) delete [] fPhi_min_history;
00352          fPhi_min_history = new Double_t[fMaxit];
00353       }
00354 
00355       fMaxit = source.fMaxit;
00356       memcpy(fMu_history,source.fMu_history,fMaxit*sizeof(Double_t));
00357       memcpy(fRnorm_history,source.fRnorm_history,fMaxit*sizeof(Double_t));
00358       memcpy(fPhi_history,source.fPhi_history,fMaxit*sizeof(Double_t));
00359       memcpy(fPhi_min_history,source.fPhi_min_history,fMaxit*sizeof(Double_t));
00360    }
00361    return *this;
00362 }

Generated on Tue Jul 5 14:37:59 2011 for ROOT_528-00b_version by  doxygen 1.5.1