source/numeric/funcobj.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  The Contents of this file are made available subject to
00004  *  the terms of GNU Lesser General Public License Version 2.1.
00005  *
00006  *
00007  *    GNU Lesser General Public License Version 2.1
00008  *    =============================================
00009  *    Copyright 2005-2008 by Kohei Yoshida.
00010  *    1039 Kingsway Dr., Apex, NC 27502, USA
00011  *
00012  *    This library is free software; you can redistribute it and/or
00013  *    modify it under the terms of the GNU Lesser General Public
00014  *    License version 2.1, as published by the Free Software Foundation.
00015  *
00016  *    This library is distributed in the hope that it will be useful,
00017  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *    Lesser General Public License for more details.
00020  *
00021  *    You should have received a copy of the GNU Lesser General Public
00022  *    License along with this library; if not, write to the Free Software
00023  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00024  *    MA  02111-1307  USA
00025  *
00026  ************************************************************************/
00027 
00028 #include "numeric/funcobj.hxx"
00029 #include "numeric/exception.hxx"
00030 #include <vector>
00031 #include <string>
00032 #include <sstream>
00033 
00034 using ::std::vector;
00035 using ::std::string;
00036 
00037 namespace scsolver { namespace numeric {
00038 
00039 const char* VarSizeException::what() const throw()
00040 {
00041     return "variable size exception";
00042 }
00043 
00048 class BaseFuncSingleObjImpl : public SingleVarFuncObj
00049 {
00050 public:
00051     BaseFuncSingleObjImpl(BaseFuncObj& rParent, size_t varIndex) :
00052         m_rParent(rParent),
00053         m_varIndex(varIndex)
00054     {
00055         if (varIndex >= m_rParent.getVarCount())
00056             throw VarSizeException();
00057     }
00058 
00059     virtual ~BaseFuncSingleObjImpl()
00060     {
00061     }
00062 
00063     virtual void setVar(double var)
00064     {
00065         m_rParent.setVar(m_varIndex, var);
00066     }
00067 
00068     virtual double getVar() const
00069     {
00070         return m_rParent.getVar(m_varIndex);
00071     }
00072 
00073     virtual double eval() const
00074     {
00075         return m_rParent.eval();
00076     }
00077 
00078     virtual const string getFuncString() const
00079     {
00080         return m_rParent.getFuncString();
00081     }
00082 
00083 private:
00084     BaseFuncObj& m_rParent;
00085     size_t m_varIndex;
00086 };
00087 
00088 //-----------------------------------------------------------------------------
00089 
00099 class BaseFuncRatioObjImpl : public SingleVarFuncObj
00100 {
00101 public:
00102     BaseFuncRatioObjImpl(BaseFuncObj& rParent, const vector<double>& ratios) :
00103         m_rParent(rParent),
00104         m_ratios(ratios),
00105         m_varIndex(0)
00106     {
00107         size_t varCount = m_rParent.getVarCount();
00108         if (ratios.size() != varCount || varCount == 0)
00109             throw VarSizeException();
00110 
00111         // By default, the 1st variable is used.  But if the ratio of the first
00112         // variable is zero, an alternative variable must be used.
00113         bool varIndexFound = false;
00114         for (size_t i = 0; i < varCount; ++i)
00115         {
00116             double absRatio = m_ratios[i] > 0 ? m_ratios[i] : -m_ratios[i];
00117             if (absRatio > 3.89e-15)
00118             {
00119                 m_varIndex = i;
00120                 varIndexFound = true;
00121                 break;
00122             }
00123         }
00124 
00125         if (!varIndexFound)
00126             throw Exception("BaseFuncRatioObjImpl::BaseFuncratioObjImpl: variable index not found");
00127 
00128         m_oldVar = rParent.getVar(m_varIndex);
00129     }
00130 
00131     virtual ~BaseFuncRatioObjImpl()
00132     {
00133     }
00134 
00135     virtual void setVar(double var)
00136     {
00137         m_rParent.setVar(m_varIndex, var);
00138         double delta = var - m_oldVar;
00139 
00140         size_t n = m_ratios.size();
00141         double baseRatio = m_ratios.at(m_varIndex);
00142         for (size_t i = 0; i < n; ++i)
00143         {
00144             if (i == m_varIndex)
00145                 continue;
00146 
00147             double ratio = m_ratios[i]/baseRatio;
00148             double origVal = m_rParent.getVar(i) + delta*ratio;
00149             m_rParent.setVar(i, origVal);
00150         }
00151 
00152         m_oldVar = var;
00153     }
00154 
00155     virtual double getVar() const
00156     {
00157         return m_rParent.getVar(0);
00158     }
00159 
00160     virtual double eval() const
00161     {
00162         return m_rParent.eval();
00163     }
00164 
00165     virtual const string getFuncString() const
00166     {
00167         string funcStr = m_rParent.getFuncString();
00168         if (m_ratios.empty())
00169             return funcStr;
00170 
00171         ::std::ostringstream os;
00172         os << funcStr << " : locked ratio (";
00173         size_t n = m_ratios.size();
00174         for (size_t i = 0; i < n; ++i)
00175         {
00176             if (i > 0)
00177                 os << ", ";
00178             os << m_ratios.at(i);
00179         }
00180         os << ")";
00181         return os.str();
00182     }
00183 
00184 private:
00185     BaseFuncObj&    m_rParent;
00186     vector<double>  m_ratios;
00187     size_t          m_varIndex;
00188     double          m_oldVar;
00189 };
00190 
00191 //-----------------------------------------------------------------------------
00192 // BaseFuncObj
00193 
00194 BaseFuncObj::BaseFuncObj() :
00195     m_pSVFuncObj(NULL)
00196 {
00197 }
00198 
00199 BaseFuncObj::BaseFuncObj(size_t varCount) :
00200     m_vars(varCount),
00201     m_pSVFuncObj(NULL)
00202 {
00203 }
00204 
00205 BaseFuncObj::BaseFuncObj(const BaseFuncObj& r) :
00206     m_vars(r.m_vars),
00207     m_pSVFuncObj(NULL) // this member does NOT need to be copied since its 
00208                        // instance is always created on the spot.
00209 {
00210 }
00211 
00212 BaseFuncObj::~BaseFuncObj()
00213 {
00214 }
00215 
00216 const vector<double>& BaseFuncObj::getVars() const
00217 {
00218     return m_vars;
00219 }
00220 
00221 double BaseFuncObj::getVar(size_t index) const
00222 {
00223     return m_vars.at(index);
00224 }
00225 
00226 SingleVarFuncObj& BaseFuncObj::getSingleVarFuncObj(size_t varIndex)
00227 {
00228     m_pSVFuncObj.reset(new BaseFuncSingleObjImpl(*this, varIndex));
00229     return *m_pSVFuncObj;
00230 }
00231 
00232 SingleVarFuncObj& BaseFuncObj::getSingleVarFuncObjByRatio(const vector<double>& ratios)
00233 {
00234     m_pSVFuncObj.reset(new BaseFuncRatioObjImpl(*this, ratios));
00235     return *m_pSVFuncObj;
00236 }
00237 
00238 void BaseFuncObj::setVar(size_t index, double var) const
00239 {
00240     if (index >= m_vars.size())
00241         return;
00242 
00243     m_vars[index] = var;
00244 }
00245 
00246 void BaseFuncObj::setVars(const vector<double> &vars) const
00247 {
00248     vector<double> tmp(vars);
00249     m_vars.swap(tmp);
00250 }
00251 
00252 size_t BaseFuncObj::getVarCount() const
00253 {
00254     return m_vars.size();
00255 }
00256 
00257 double BaseFuncObj::operator ()(const vector<double>& vars) const
00258 {
00259     setVars(vars);
00260     return eval();
00261 }
00262 
00263 // ----------------------------------------------------------------------------
00264 
00265 SingleVarFuncObj::SingleVarFuncObj()
00266 {
00267 }
00268 
00269 SingleVarFuncObj::~SingleVarFuncObj()
00270 {
00271 }
00272 
00273 double SingleVarFuncObj::operator()(double var)
00274 {
00275     setVar(var);
00276     return eval();
00277 }
00278 
00279 }}

Generated on Mon Jul 28 09:13:20 2008 for scsolver by  doxygen 1.5.3