+SimulatedAnnealingSolver::SimulatedAnnealingSolver(const Ptr<SimulatedAnnealingSolverSystem>& system)
+{
+ impl = new Impl(system);
+}
+
+SimulatedAnnealingSolver::SimulatedAnnealingSolver(const SimulatedAnnealingSolver& b)
+{
+ if (b.impl) b.impl->addref();
+ release();
+ impl = b.impl;
+}
+
+void SimulatedAnnealingSolver::release()
+{
+ if (impl) { impl->release(); impl = NULL; }
+}
+
+void SimulatedAnnealingSolver::setIterPerStep(int ite)
+{
+ CV_Assert(impl);
+ CV_Assert(ite>0);
+ impl->iterPerStep = ite;
+}
+
+int SimulatedAnnealingSolver::run()
+{
+ CV_Assert(impl);
+ CV_Assert(impl->initialT>impl->finalT);
+ double Ti = impl->initialT;
+ double previousEnergy = impl->energy();
+ int exchange = 0;
+ while (Ti > impl->finalT)
+ {
+ for (int i = 0; i < impl->iterPerStep; i++)
+ {
+ impl->changeState();
+ double newEnergy = impl->energy();
+ if (newEnergy < previousEnergy)
+ {
+ previousEnergy = newEnergy;
+ exchange++;
+ }
+ else
+ {
+ double r = impl->rEnergy.uniform(0.0, 1.0);
+ if (r < std::exp(-(newEnergy - previousEnergy) / Ti))
+ {
+ previousEnergy = newEnergy;
+ exchange++;
+ }
+ else
+ {
+ impl->reverseState();
+ }
+ }
+
+ }
+ Ti *= impl->coolingRatio;
+ }
+ impl->finalT = Ti;
+ return exchange;
+}
+
+void SimulatedAnnealingSolver::setEnergyRNG(const RNG& rng)
+{
+ CV_Assert(impl);
+ impl->rEnergy = rng;
+}
+
+void SimulatedAnnealingSolver::setInitialTemperature(double x)
+{
+ CV_Assert(impl);
+ CV_Assert(x>0);
+ impl->initialT = x;
+}
+
+void SimulatedAnnealingSolver::setFinalTemperature(double x)
+{
+ CV_Assert(impl);
+ CV_Assert(x>0);
+ impl->finalT = x;
+}
+
+double SimulatedAnnealingSolver::getFinalTemperature()
+{
+ CV_Assert(impl);
+ return impl->finalT;
+}
+
+void SimulatedAnnealingSolver::setCoolingRatio(double x)
+{
+ CV_Assert(impl);
+ CV_Assert(x>0 && x<1);
+ impl->coolingRatio = x;
+}
+
+class SimulatedAnnealingANN_MLP : public SimulatedAnnealingSolverSystem
+{
+protected:
+ ml::ANN_MLP& nn;
+ Ptr<ml::TrainData> data;
+ int nbVariables;
+ vector<double*> adrVariables;
+ RNG rVar;
+ RNG rIndex;
+ double varTmp;
+ int index;
+public:
+ SimulatedAnnealingANN_MLP(ml::ANN_MLP& x, const Ptr<ml::TrainData>& d) : nn(x), data(d)
+ {
+ initVarMap();
+ }
+ ~SimulatedAnnealingANN_MLP() {}
+protected:
+ void changeState()
+ {
+ index = rIndex.uniform(0, nbVariables);
+ double dv = rVar.uniform(-1.0, 1.0);
+ varTmp = *adrVariables[index];
+ *adrVariables[index] = dv;
+ }
+
+ void reverseState()
+ {
+ *adrVariables[index] = varTmp;
+ }
+
+ double energy() const { return nn.calcError(data, false, noArray()); }
+
+protected:
+ void initVarMap()
+ {
+ Mat l = nn.getLayerSizes();
+ nbVariables = 0;
+ adrVariables.clear();
+ for (int i = 1; i < l.rows-1; i++)
+ {
+ Mat w = nn.getWeights(i);
+ for (int j = 0; j < w.rows; j++)
+ {
+ for (int k = 0; k < w.cols; k++, nbVariables++)
+ {
+ if (j == w.rows - 1)
+ {
+ adrVariables.push_back(&w.at<double>(w.rows - 1, k));
+ }
+ else
+ {
+ adrVariables.push_back(&w.at<double>(j, k));
+ }
+ }
+ }
+ }
+ }
+
+};
+
+double ANN_MLP::getAnnealInitialT() const
+{
+ const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ return this_->getAnnealInitialT();
+}
+
+void ANN_MLP::setAnnealInitialT(double val)
+{
+ ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ this_->setAnnealInitialT(val);
+}
+
+double ANN_MLP::getAnnealFinalT() const
+{
+ const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ return this_->getAnnealFinalT();
+}
+
+void ANN_MLP::setAnnealFinalT(double val)
+{
+ ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ this_->setAnnealFinalT(val);
+}
+
+double ANN_MLP::getAnnealCoolingRatio() const
+{
+ const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ return this_->getAnnealCoolingRatio();
+}
+
+void ANN_MLP::setAnnealCoolingRatio(double val)
+{
+ ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ this_->setAnnealCoolingRatio(val);
+}
+
+int ANN_MLP::getAnnealItePerStep() const
+{
+ const ANN_MLP_ANNEAL* this_ = dynamic_cast<const ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ return this_->getAnnealItePerStep();
+}
+
+void ANN_MLP::setAnnealItePerStep(int val)
+{
+ ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ this_->setAnnealItePerStep(val);
+}
+
+void ANN_MLP::setAnnealEnergyRNG(const RNG& rng)
+{
+ ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
+ if (!this_)
+ CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+ this_->setAnnealEnergyRNG(rng);
+}
+
+class ANN_MLPImpl : public ANN_MLP_ANNEAL