|
bpp-core
2.1.0
|
00001 // 00002 // File: PowellMultiDimensions.cpp 00003 // Created by: Julien Dutheil 00004 // Created on: Mon Nov 17 15:16:45 2003 00005 // 00006 00007 /* 00008 Copyright or © or Copr. Bio++ Development Team, (November 17, 2004) 00009 00010 This software is a computer program whose purpose is to provide classes 00011 for numerical calculus. 00012 00013 This software is governed by the CeCILL license under French law and 00014 abiding by the rules of distribution of free software. You can use, 00015 modify and/ or redistribute the software under the terms of the CeCILL 00016 license as circulated by CEA, CNRS and INRIA at the following URL 00017 "http://www.cecill.info". 00018 00019 As a counterpart to the access to the source code and rights to copy, 00020 modify and redistribute granted by the license, users are provided only 00021 with a limited warranty and the software's author, the holder of the 00022 economic rights, and the successive licensors have only limited 00023 liability. 00024 00025 In this respect, the user's attention is drawn to the risks associated 00026 with loading, using, modifying and/or developing or reproducing the 00027 software by the user in light of its specific status of free software, 00028 that may mean that it is complicated to manipulate, and that also 00029 therefore means that it is reserved for developers and experienced 00030 professionals having in-depth computer knowledge. Users are therefore 00031 encouraged to load and test the software's suitability as regards their 00032 requirements in conditions enabling the security of their systems and/or 00033 data to be ensured and, more generally, to use and operate it in the 00034 same conditions as regards security. 00035 00036 The fact that you are presently reading this means that you have had 00037 knowledge of the CeCILL license and that you accept its terms. 00038 */ 00039 00040 #include "PowellMultiDimensions.h" 00041 #include "BrentOneDimension.h" 00042 #include "OneDimensionOptimizationTools.h" 00043 #include "../NumTools.h" 00044 00045 using namespace bpp; 00046 00047 /******************************************************************************/ 00048 00049 bool PowellMultiDimensions::PMDStopCondition::isToleranceReached() const { 00050 callCount_++; 00051 if (callCount_ <= burnin_) return false; 00052 return getCurrentTolerance() < tolerance_; 00053 } 00054 00055 double PowellMultiDimensions::PMDStopCondition::getCurrentTolerance() const 00056 { 00057 // NRC Test for done: 00058 const PowellMultiDimensions* pmd = dynamic_cast<const PowellMultiDimensions*>(optimizer_); 00059 double fp = pmd->fp_; 00060 double fret = pmd->fret_; 00061 return 2.0 * NumTools::abs(fp - fret) / (NumTools::abs(fp) + NumTools::abs(fret)); 00062 } 00063 00064 /******************************************************************************/ 00065 00066 PowellMultiDimensions::PowellMultiDimensions(Function* function) : 00067 AbstractOptimizer(function), fp_(0), fret_(0), pt_(), xi_(), ncom_(0), pcom_(), xicom_(), f1dim_(function) 00068 { 00069 setDefaultStopCondition_(new PMDStopCondition(this)); 00070 setStopCondition(*getDefaultStopCondition()); 00071 } 00072 00073 /******************************************************************************/ 00074 00075 void PowellMultiDimensions::doInit(const ParameterList& params) throw (Exception) 00076 { 00077 // Build the initial matrix: 00078 size_t n = params.size(); 00079 xi_.resize(n); 00080 for (size_t i = 0; i < n; i++) 00081 { 00082 // Copy the parameter list: 00083 xi_[i].resize(n); 00084 for(unsigned int j = 0; j < n; j++) 00085 { 00086 // Set the directions to unit vectors: 00087 xi_[i][j] = (j == i) ? 1 : 0; 00088 } 00089 } 00090 00091 // Starting point: 00092 fret_ = getFunction()->f(getParameters()); 00093 pt_ = getParameters(); 00094 } 00095 00096 /******************************************************************************/ 00097 00098 double PowellMultiDimensions::doStep() throw (Exception) 00099 { 00100 size_t n = getParameters().size(); 00101 fp_ = fret_; 00102 unsigned int ibig = 0; 00103 double del = 0.0; // Will be the biggest function decrease 00104 Vdouble xit(n); 00105 00106 // In each iteration, loop over all directions in the set. 00107 double fptt; 00108 for(unsigned int i = 0; i < n; i++) 00109 { 00110 // Copy the direction: 00111 for(unsigned int j = 0; j < n; j++) 00112 { 00113 xit[j] = xi_[j][i]; 00114 } 00115 fptt = fret_; 00116 nbEval_ += OneDimensionOptimizationTools::lineMinimization(f1dim_, 00117 getParameters_(), xit, getStopCondition()->getTolerance(), 00118 0, getMessageHandler(), getVerbose() > 0 ? getVerbose() - 1 : 0); 00119 fret_ = getFunction()->f(getParameters()); 00120 if (getVerbose() > 2) printPoint(getParameters(), fret_); 00121 if (fret_ > fp_) throw Exception("DEBUG: PowellMultiDimensions::doStep(). Line minimization failed!"); 00122 if (fptt - fret_ > del) 00123 { 00124 del = fptt - fret_; 00125 ibig = i; 00126 } 00127 } 00128 00129 ParameterList ptt = getParameters(); 00130 for (unsigned int j = 0; j < n; j++) 00131 { 00132 ptt[j].setValue(2.0 * getParameters()[j].getValue() - pt_[j].getValue()); 00133 xit[j] = getParameters()[j].getValue() - pt_[j].getValue(); 00134 pt_[j].setValue(getParameters()[j].getValue()); 00135 } 00136 fptt = getFunction()->f(ptt); 00137 if (fptt < fp_) 00138 { 00139 double t = 2.0 * (fp_ - 2.0 * fret_ + fptt) * NumTools::sqr(fp_ - fret_ - del) - del * NumTools::sqr(fp_ - fptt); 00140 if (t < 0.0) 00141 { 00142 //cout << endl << "New direction: drection " << ibig << " removed." << endl; 00143 nbEval_ += OneDimensionOptimizationTools::lineMinimization(f1dim_, 00144 getParameters_(), xit, getStopCondition()->getTolerance(), 00145 0, getMessageHandler(), getVerbose() > 0 ? getVerbose() - 1 : 0); 00146 fret_ = getFunction()->f(getParameters()); 00147 if (fret_ > fp_) throw Exception("DEBUG: PowellMultiDimensions::doStep(). Line minimization failed!"); 00148 for (unsigned int j = 0; j < n; j++) 00149 { 00150 xi_[j][ibig] = xi_[j][n - 1]; 00151 xi_[j][n - 1] = xit[j]; 00152 } 00153 } 00154 } 00155 else getFunction()->setParameters(getParameters()); 00156 00157 return fret_; 00158 } 00159 00160 /******************************************************************************/ 00161 00162 double PowellMultiDimensions::optimize() throw (Exception) 00163 { 00164 AbstractOptimizer::optimize(); 00165 // Apply best parameter: 00166 return getFunction()->f(getParameters()); 00167 } 00168 00169 /******************************************************************************/ 00170