00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "numeric/bisectionsearch.hxx"
00029 #include "numeric/exception.hxx"
00030 #include "numeric/funcobj.hxx"
00031 #include "numeric/diff.hxx"
00032
00033 namespace scsolver { namespace numeric {
00034
00035 BisectionSearch::BisectionSearch(double lower, double upper) :
00036 BaseLineSearch(),
00037 m_lowerBound(lower),
00038 m_upperBound(upper),
00039 m_maxIteration(100)
00040 {
00041 }
00042
00043 BisectionSearch::~BisectionSearch()
00044 {
00045 }
00046
00047 double BisectionSearch::solve()
00048 {
00049 SingleVarFuncObj* pFuncObj = getFuncObj();
00050 bool debug = isDebug();
00051 if (!pFuncObj)
00052 throw Exception("BisectionSearch::solve: no function object set");
00053
00054 if (debug)
00055 fprintf(stdout, "BisectionSearch::solve: function = %s\n", pFuncObj->getFuncString().c_str());
00056
00057 SingleVarFuncObj& F = *pFuncObj;
00058 NumericalDiffer diff;
00059 diff.setFuncObject(pFuncObj);
00060 double oldInterval = 0.0;
00061
00062 for (size_t i = 0; i < m_maxIteration; ++i)
00063 {
00064 if (debug)
00065 fprintf(stdout, "BisectionSearch::solve: ITERATION %d\n", i);
00066
00067 double interval = m_upperBound - m_lowerBound;
00068 if (interval < 3.89e-15 || oldInterval == interval)
00069 {
00070 if (i == 0)
00071 throw Exception("BisectionSearch::solve: interval is already too small in the first iteration");
00072
00073
00074
00075 return m_lowerBound;
00076 }
00077
00078 double x = m_lowerBound + interval/2.0;
00079 diff.setVariable(x);
00080 double ff = diff.run();
00081 if (debug)
00082 {
00083 fprintf(stdout, "BisectionSearch::solve: f(%g) = %g; f'(%g) = %g\n",
00084 x, F(x), x, ff);
00085 fprintf(stdout, "BisectionSearch::solve: range: %g - %g (interval = %g)\n",
00086 m_lowerBound, m_upperBound, interval);
00087 }
00088
00089 if ((ff > 0 ? ff : -ff) < 3.89e-15)
00090
00091 return x;
00092
00093 if (ff > 0)
00094
00095 m_upperBound = x;
00096 else
00097
00098 m_lowerBound = x;
00099
00100 oldInterval = interval;
00101 }
00102
00103 throw MaxIterationReached();
00104 return 0.0;
00105 }
00106
00107 }}