# Rosenbrock curved valley sample

Does anyone have some sample code showing how to solve the ‘Rosenbrocks’ curved valley’ problem with root Minuit?

Regards
Lars Schouw

Hi Lars,

here is a simple macro which solve the Rosenbrock Curved Valley problem using the ROOT Minuit. Please let me know if you have any further problems,

Best Regards, Lorenzo
testRosenbrockCurvedValley.C (1.61 KB)

Lars,

forgot to mention, that as it is, the example works only with the new ROOT version 5.06.00, since it uses the new Minuit2
If you want to use it with the older versions of ROOT, just replace line 65```void testRosenbrockCurvedValley() { DoFit("Minuit2",5,5); }```with```void testRosenbrockCurvedValley() { DoFit("Minuit",5,5); }```

and it will work using the class TMinuit

Lorenzo

Lorenzo,

Thank you for a great example.
I have tested it out today.

I have to run the code 15 - 20 times before it converges to the correct result 1,1

Do you know what the doFit parameters 5,5 does?
In the minuit source code it says to start at -1.2, 1.0 if I do that it never finds the correct result 1,1

I double checked theresult in Mathematica and gsl and it seems to work there straight out of the box.

Regards
Lars Schouw

Lars,

the parameter 5,5 are the initial values, where to start the minimization.
If you start lets say between -10 and 10 for both parameter it should alway work and reach the 1,1 point. If you start further away, you would need to increase the number of function calls to higher values (more than 1000), given the paticular property of that function.
If you think youor result is not accurate enough, you need to increase the tolerance, i.e. minimum expected distance to the minimum value of the function which will stop the minimization process.
You can do that in the example I sent you before, by doing, before calling MIGRAD,

arglist[0] = 5000; // number of function calls
arglist[1] = 0.01; // tolerance
minuit2->ExecuteCommand(“MIGRAD”,arglist,2);

Cheers,

Lorenzo

I still do not get 1,1 as a result but something close, with telling me that it does not converge.

I have also tried out the SIMPLEX minimization method, as well as directly from C++ using the Mingrad library without any louck so far.

root [25] .x testRosenbrockCurvedValley.C
TFitterMinuit - Minimize with max iterations 5000 edmval 0.01
VariableMetricBuilder: call limit exceeded.
MnHesse: 2nd derivative zero for parameter 2
MnHesse fails and will return diagonal matrix
TFitterMinuit::Minimization DID not converge !
Hesse is not valid
Minuit2 : minimum values for 5,5
par0 = 0.999997
par1 = 0.999995

Regards
Lars Schouw

Hi Lars,

what is your starting point: -5,5 ? It looks like you are starting from a different point.
If I run the program I sent you, with starting values -5,5 and tolerance 0.01, you should get:

Processing testRosenbrockCurvedValley.C…
creating FitterMinuit
TFitterMinuit - Minimize with max iterations 5000 edmval 0.01
Minimum Found
FVAL = 4.39881e-11
Edm = 4.40223e-11
Nfcn = 299
x = 1 +/- 1.00484
y = 1 +/- 2.0122
Minuit2 : minimum values for 5,5
par0 = 1
par1 = 1

If you start from a point furtehr away, as I said before, you need more iterations to reach the minimum. In case, please send me your running script.
Regards, Lorenzo

Here you go.

``````#include "TH1.h"
#include "TF1.h"
#include "TStopwatch.h"
#include "TMinuit.h"
#include "TVirtualFitter.h"
#include "TCanvas.h"
#include "TF2.h"
#include "TH1F.h"
#include "TCanvas.h"
#include "TH2F.h"
#include "TLegend.h"
#include "math.h"
#include "TSystem.h"
#include "TStyle.h"
#include <iostream>

void RosenbrockCurvedValley(Int_t & /*nPar*/, Double_t * /*grad*/ , Double_t &fval, Double_t *x, Int_t /*iflag */  ) {

fval = 100*(x[1] - x[0]*x[0])*(x[1] - x[0]*x[0]) + (1 - x[0])*(1 - x[0]);
return;
}

void DoFit(const char *fitterType="Minuit2",double par1 = 0, double par2 = 0) {

Double_t foundMinimum[2];
Double_t arglist[100];
arglist[0] = 0;

// create fitter instance using type fitter
TVirtualFitter::SetDefaultFitter(fitterType);
TVirtualFitter * minuit2 = TVirtualFitter::Fitter(0,2);
arglist[0] = 1;
// set print level
minuit2->ExecuteCommand("SET PRINT",arglist,2);
// set initial prameters
minuit2->SetParameter(0, "x", par1,   0.0001, 0,0);
minuit2->SetParameter(1, "y", par2,   0.0001, 0,0);
// set function to minimize
minuit2->SetFCN(RosenbrockCurvedValley);
// minimize

arglist[0] = 5000; // number of function calls
arglist[1] = 0.01; // tolerance
minuit2->ExecuteCommand("MIGRAD",arglist,2);
//minuit2->ExecuteCommand("SIMPLEX",arglist,2);
// get minimum values
foundMinimum[0] = minuit2->GetParameter(0);
foundMinimum[1] = minuit2->GetParameter(1);

std::cout << " " << fitterType << " :" << " minimum values for " << par1 << "," << par2 << std::endl;
std::cout << " par0 = " << foundMinimum[0] << std::endl;
std::cout << " par1 = " << foundMinimum[1] << std::endl;

}

void testRosenbrockCurvedValley() {
DoFit("Minuit2",5,5);
//DoFit("Minuit2",-1.2,1.0);
}

#ifndef __CINT__
int main() {

testRosenbrockCurvedValley();
}
#endif``````

Works source code attached.
had to change to
minuit2->SetParameter(0, “x”, par1, 0.1, 0,0);
minuit2->SetParameter(1, “y”, par2, 0.1, 0,0);

for clearnign the minimization btween sessions
minuit2->Clear() at the end of the DoFit() function
had to be added.

Source code attached.

Lars
testRosenbrockCurvedValley.C (1.81 KB)