Number GoldenSection::findMinimum() { Interval currentInterval; currentInterval.leftBorder = m_sourceInterval.leftBorder + m_ratio * (m_sourceInterval.rightBorder - m_sourceInterval.leftBorder); currentInterval.rightBorder = m_sourceInterval.leftBorder + m_sourceInterval.rightBorder - currentInterval.leftBorder; Number delta = 0; do { if (calculateFunction(currentInterval.leftBorder) <= calculateFunction(currentInterval.rightBorder)) { m_sourceInterval.rightBorder = currentInterval.rightBorder; currentInterval.rightBorder = currentInterval.leftBorder; currentInterval.leftBorder = m_sourceInterval.leftBorder + m_sourceInterval.rightBorder - currentInterval.leftBorder; } else { m_sourceInterval.leftBorder = currentInterval.leftBorder; currentInterval.leftBorder = currentInterval.rightBorder; currentInterval.rightBorder = m_sourceInterval.leftBorder + m_sourceInterval.rightBorder - currentInterval.rightBorder; } delta = fabs(m_sourceInterval.leftBorder - m_sourceInterval.rightBorder); } while (delta > m_accuracy); return (m_sourceInterval.leftBorder + m_sourceInterval.rightBorder) / 2; }
Number Integral::findAreaOnInterval(Number left, Number right) { Number middle = left + (right - left) / 2; Number functionLeft = calculateFunction(left); Number functionMiddle = calculateFunction(middle); Number functionRight = calculateFunction(right); Number step = right - left; return (step / 6.0) * (functionLeft + 4 * functionMiddle + functionRight); }
Number Derivative::findSolution(Number point) { Number result = 0; result -= calculateFunction(point + 2 * smallNumber(point)); result += 8 * calculateFunction(point + smallNumber(point)); result -= 8 * calculateFunction(point - smallNumber(point)); result += calculateFunction(point - 2 * smallNumber(point)); result /= 12 * smallNumber(point); return result; }
double Funktion::newtonIntervall(Intervall searchRootHere, Funktion derivate){ Intervall x(searchRootHere.getInf(),searchRootHere.getSup()); while(x.getInf()!=x.getSup()){ x = (x.x_()-calculateFunction(x.x_())/derivate.fInt(x))&&x; if(x.getInf()!=x.getInf()) return NAN; } return x.getInf(); }
Number Enumerative::findMinimum() { Number minimumPoint = m_sourceInterval.leftBorder + (m_sourceInterval.rightBorder - m_sourceInterval.leftBorder) / (m_iterationsCount + 1); Number functionMinumum = calculateFunction(minimumPoint); for (int i = 1; i <= m_iterationsCount; i++) { Number currentPoint = m_sourceInterval.leftBorder + i * (m_sourceInterval.rightBorder - m_sourceInterval.leftBorder) / (m_iterationsCount + 1); if (calculateFunction(currentPoint) < functionMinumum) { functionMinumum = calculateFunction(currentPoint); minimumPoint = currentPoint; } } return minimumPoint; }
Intervall Funktion::fInt(Intervall x, double acc=.001){ double inf = calculateFunction(x.getSup()); double sup = calculateFunction(x.getSup()); for(double i=x.getInf();i<x.getSup();i+=acc){ if(calculateFunction(i)<inf) inf = calculateFunction(i); else if(calculateFunction(i)>sup) sup = calculateFunction(i); } return Intervall(inf,sup); }
QList<Number> HookeJeeves::findMinimum() { QList<Number> currentPoint = m_sourcePoint; forever { for (int i = 0; i < currentPoint.size(); i++) { if (calculateFunction(increaseDirection(currentPoint, i)) < calculateFunction(currentPoint)) { currentPoint = increaseDirection(currentPoint, i); } else if (calculateFunction(decreaseDirection(currentPoint, i)) < calculateFunction(currentPoint)) { currentPoint = decreaseDirection(currentPoint, i); } } if (calculateFunction(currentPoint) < calculateFunction(m_sourcePoint)) { QList<Number> oldSourcePoint = m_sourcePoint; m_sourcePoint = currentPoint; for (int i = 0; i < currentPoint.size(); i++) { currentPoint[i] = m_sourcePoint[i] + m_accelerationCoefficient * (m_sourcePoint[i] - oldSourcePoint[i]); } } else { bool isFinish = true; for (int i = 0; i < m_stepSizes.size(); i++) { if (m_stepSizes[i] > m_stopValue) { isFinish = false; m_stepSizes[i] = m_stepSizes[i] / m_decreaseCoefficient; } } if (isFinish) { // Exit condition return m_sourcePoint; } else { currentPoint = m_sourcePoint; } } } }
/** Do MC/simulated annealing to refine parameters * * Helpful: double curchi2 = calculateD2TOFFunction(mFunction, domain, values, rawY, rawE); */ double RefinePowderInstrumentParameters2::doSimulatedAnnealing(map<string, Parameter> inparammap) { // 1. Prepare/initialization // Data structure const MantidVec& dataY = m_dataWS->readY(m_wsIndex); size_t numpts = dataY.size(); vector<double> vecY(numpts, 0.0); // Monte Carlo strategy and etc. vector<vector<string> > mcgroups; setupRandomWalkStrategy(inparammap, mcgroups); int randomseed = getProperty("MonteCarloRandomSeed"); srand(randomseed); double temperature = getProperty("AnnealingTemperature"); if (temperature < 1.0E-10) throw runtime_error("Annealing temperature is too low."); int maxiterations = getProperty("MonteCarloIterations"); if (maxiterations <= 0) throw runtime_error("Max iteration cannot be 0 or less."); // Book keeping map<string, Parameter> parammap; duplicateParameters(inparammap, parammap); // vector<pair<double, map<string, Parameter> > > bestresults; map<string, Parameter> bestresult; // size_t maxnumresults = 10; // 2. Set up parameters and get initial values m_bestChiSq = DBL_MAX; m_bestChiSqStep = -1; m_bestChiSqGroup = -1; double chisq0 = calculateFunction(parammap, vecY); double chisq0x = calculateFunctionError(m_positionFunc, m_dataWS, m_wsIndex); g_log.notice() << "[DBx510] Starting Chi^2 = " << chisq0 << " (homemade) " << chisq0x << " (Levenber-marquadt)" << endl; bookKeepMCResult(parammap, chisq0, -1, -1, bestresult); // bestresults, maxnumresults); // 3. Monte Carlo starts double chisqx = chisq0; int numtotalacceptance = 0; int numrecentacceptance = 0; int numrecentsteps = 0; map<string, Parameter> propparammap; // parameters with proposed value duplicateParameters(parammap, propparammap); for (int istep = 0; istep < maxiterations; ++istep) { for (int igroup = 0; igroup < static_cast<int>(mcgroups.size()); ++igroup) { // a) Propose value proposeNewValues(mcgroups[igroup], parammap, propparammap, chisqx); // , prevbetterchi2); // b) Calcualte function and chi^2 double propchisq = calculateFunction(propparammap, vecY); /* stringstream dbss; dbss << "[DBx541] New Chi^2 = " << propchisq << endl; vector<string> paramnames = m_positionFunc->getParameterNames(); for (size_t i = 0; i < paramnames.size(); ++i) { string parname = paramnames[i]; double curvalue = parammap[parname].value; double propvalue = propparammap[parname].value; dbss << parname << ":\t\t" << setw(20) << propvalue << "\t\t<-----\t\t" << curvalue << "\t Delta = " << curvalue-propvalue << endl; } g_log.notice(dbss.str()); */ // c) Determine to accept change bool acceptpropvalues = acceptOrDenyChange(propchisq, chisqx, temperature); // d) Change current chi^2, apply change, and book keep if (acceptpropvalues) { setFunctionParameterValues(m_positionFunc, propparammap); chisqx = propchisq; bookKeepMCResult(parammap, chisqx, istep, igroup, bestresult); // s, maxnumresults); } // e) MC strategy control ++ numtotalacceptance; ++ numrecentacceptance; ++ numrecentsteps; } // f) Annealing if (numrecentsteps >= 10) { double acceptratio = static_cast<double>(numrecentacceptance)/static_cast<double>(numrecentsteps); if (acceptratio < 0.2) { // i) Low acceptance, need to raise temperature temperature *= 2.0; } else if (acceptratio >= 0.8) { // ii) Temperature too high to accept too much new change temperature /= 2.0; } // iii) Reset counters numrecentacceptance = 0; numrecentsteps = 0; } } // 4. Apply the best result // sort(bestresults.begin(), bestresults.end()); setFunctionParameterValues(m_positionFunc, bestresult); double chisqf = m_bestChiSq; g_log.warning() << "[DBx544] Best Chi^2 From MC = " << m_bestChiSq << endl; // 5. Use regular minimzer to try to get a better result string fitstatus; double fitchisq; bool goodfit = doFitFunction(m_positionFunc, m_dataWS, m_wsIndex, "Levenberg-MarquardtMD", 1000, fitchisq, fitstatus); bool restoremcresult = false; if (goodfit) { map<string, Parameter> nullmap; fitchisq = calculateFunction(nullmap, vecY); if (fitchisq > chisqf) { // Fit is unable to achieve a better solution restoremcresult = true; } else { m_bestChiSq = fitchisq; } } else { // Fit is bad restoremcresult = true; } g_log.warning() << "[DBx545] Restore MC Result = " << restoremcresult << endl; if (restoremcresult) { setFunctionParameterValues(m_positionFunc, bestresult); } chisqf = m_bestChiSq; // 6. Final result double chisqfx = calculateFunctionError(m_positionFunc, m_dataWS, m_wsIndex); map<string, Parameter> emptymap; double chisqf0 = calculateFunction(emptymap, vecY); g_log.notice() << "Best Chi^2 (L-V) = " << chisqfx << ", (homemade) = " << chisqf0 << endl; g_log.warning() << "Data Size = " << m_dataWS->readX(m_wsIndex).size() << ", Number of parameters = " << m_positionFunc->getParameterNames().size() << endl; return chisqf; }