Help with use of functors in Minimization


frainj
04-21-2008, 04:57 PM
My aim is to estimate a form of GARCH process where the innovations have an alpha-stable distribution. Due to processing times I have transfered much of my work from R or Mathematica to C++. To ensure that the process is working I have decided to first estimate a standard GARCH(1,1) process with normal innovations using Maximum Likelihood. The Likelihood function (given the data) is defined as a functor in the structure param_ll. The final line of the program tries to call the minimize function from the Amoeba struct on page 505 of NR3. It returns a message

no matching function for call to 'Amoeba::minimize(VecDoub&,Doub&,main()::param_ll&)'

The someQuadrature example on page 22 appears to imply that this code should work. I have also tried to use the quasi-Newton methods on pages 521-525 of NR3 trying to use the instructions on page 23 but I can not understand them.

If these questions are silly may I apologise but I would appreciate any help. I have purchased copies of both Stroustrup anp Lippman et al. as recommended in NR3.and have tried to find answers there. Does anyone know of a better reference for one who, at various stages, has over the last 40+ years worked in Fortran, PL1, Pascal and various packages such as R Matlab Gauss etc. where 'functional' programming is the rule. I can see the advantages of OOP etc. but I am having extreme problems getting my mind around some of the concepts.

Best Regards

John C Frain





#include <cstdlib>
#include <iostream>

#include "C:\WORK\CPP_general\nr_301\include\nr3.h"
#include "C:\WORK\CPP_general\nr_301\include\amoeba.h"
#include "C:\WORK\CPP_general\nr_301\include\moment.h"
#include "C:\WORK\CPP_general\nr_301\include\erf.h"

#include "garchfit.h"

using namespace std;

Int main()
{
// read data and load file
Int nrow,ncol;
string txt;
ifstream fp("loss.dat");
fp >> nrow >> ncol;
cout << "matrix is " << nrow << " by " << ncol << "\n" ;
if (fp.fail()){
cout << "Data file loss.dat not found" << endl;
return 1;
}
//NR::nrerror("Data file loss.dat not found");

NRmatrix<Doub> inputmat(nrow,ncol); // matrix to hold input data

// Read file
for (Int ii=0;ii<nrow;ii++){
getline(fp,txt);
for (Int jj=0;jj<ncol;jj++) {
fp >> inputmat[ii][jj];
}
}


NRvector<Doub> returns(nrow);
for (Int ii=0;ii<nrow;ii++){
returns[ii] = inputmat[ii][3];
}

// Set up functor to estimate GARCH(1,1) likelihood

struct param_ll{
NRvector<Doub> x;
Int nobs;
param_ll(const NRvector<Doub> xx, const Int nnobs) : x(xx), nobs(nnobs) {}
Doub operator () (const Doub omega, const Doub alpha1, const Doub beta1){
//
Doub ave, adev, sdev, var, skew, curt;
moment(x, ave, adev, sdev, var, skew, curt);
// To hold variances
VecDoub sigmasq(nobs,0.0);
sigmasq[0] = sdev*sdev;
cout <<"test1 " <<nobs << endl;
Doub ll=0.0;
for (Int ii=1 ; ii <nobs ; ii++){
sigmasq[ii] = omega + alpha1 * pow( x[ii-1], 2.0) +
beta1 * sigmasq[ii-1];
ll += log(pdf1( x[ii],ave,sqrt(sigmasq[ii])));
//cout << "log(dnorm(" << x[ii] << ",mean = " << ave << ", sd = "<< sqrt(sigmasq[ii])<< "))"<< endl;
//cout << "Loglikelihood of observation is "
<< log(pdf1( x[ii],ave,sqrt(sigmasq[ii]))) << endl;
}
//cout << "Value of Loglikelihood Function is " << ll << endl;
ll = - ll ; // Return - likelihood
return ll ;
}
};
param_ll loglik1(returns, nrow);
cout<< "testing "<< loglik1(.1, .15, .75)<< endl;

VecDoub point(3);
point[0] = 0.1; point[1]= 0.15 ;point[2]= 0.75;
Doub del = .05;
const Doub ftol = 1.0e-8;
Amoeba am(ftol);
am.minimize(point,del,loglik1);
return 0;
}

davekw7x
04-21-2008, 07:07 PM
no matching function for call to 'Amoeba::minimize(VecDoub&,Doub&,main()::param_ll&)'


First, as a matter of style, I would take the param_ll struct definition outside main.

Secondly, note that the function that is the third argument in your call to initialize has a single parameter that is a vector (that's how it is used inside the minimize function), not three separate doubles.

So, if I understand your intent, with minor changes to your work, I might try:


// Your standard #includes and nr3 #includes
#include "garchfit.h"

using namespace std;

struct param_ll {
VecDoub x;
Int nobs;
param_ll(VecDoub_I xx, Int nnobs):x(xx), nobs(nnobs) { }
//Had threee parameters: omega, const Doub alpha1, const Doub beta1)
Doub operator () (VecDoub_I params)

{
Doub omega = params[0];
Doub alpha1 = params[1];
Doub beta1 = params[2];
Doub ave, adev, sdev, var, skew, curt;
moment(x, ave, adev, sdev, var, skew, curt);

VecDoub sigmasq(nobs, 0.0);
sigmasq[0] = sdev * sdev;
cout << "test1 " << nobs << endl;
Doub ll = 0.0;
for (Int ii = 1; ii < nobs; ii++) {
sigmasq[ii] = omega + alpha1 * pow(x[ii - 1], 2.0) +
beta1 * sigmasq[ii - 1];
ll += log(pdf1(x[ii], ave, sqrt(sigmasq[ii])));
}
ll = -ll;
return ll;
}
};

Int main()
{
// read data and load file
Int nrow, ncol;
.
.
.
param_ll loglik1(returns, nrow);
VecDoub point(3);
point[0] = 0.1;
point[1] = 0.15;
point[2] = 0.75;
Doub del = .05;
const Doub ftol = 1.0e-8;
Amoeba am(ftol);
am.minimize(point, del, loglik1);
return 0;
} // end of main()


It compiles cleanly with GNU g++ as well as with recent copies of Borland and Microsoft compilers that I have.

Of course, I have no way of testing it.

Regards,

Dave

frainj
04-23-2008, 09:13 AM
Thanks very much for the help. The Nedler-Mead method is working well. You have saved me a lot of wasted effort.

The GARCH likelihood function in my original message has a small error.

John Frain

davekw7x
04-23-2008, 10:07 AM
Thanks very much....

You are very welcome.

I didn't want to clutter up my previous response with extra information, but in your initial post, you mentioned a problem with the quasi-Newton method.

If you are still interested, there was a functor example for dfpmin() in a recent thread here: function class construction (http://www.nr.com/forum/showthread.php?t=1360)


Regards,

Dave

amirvahid
01-30-2013, 10:43 AM
Where is the garchfit.h file BTW?