简体   繁体   English

如何使用在主 function (c++) 中创建的 object 定义 function?

[英]How can I define a function using an object created in the main function (c++)?

I'm trying to write a program that will give me the cross-validation bandwidth for a kernel estimator in c++ (there are around 20,000 data points so Matlab is way too slow).我正在尝试编写一个程序,该程序将为 c++ 中的 kernel 估计器提供交叉验证带宽(大约有 20,000 个数据点,所以 ZA5CD8A07B40F6449056939C13140 太慢了)AE I'm doing this by using a secant algorithm on the derivative of the objective of the leave-one-out estimator.我通过对留一估计器的目标的导数使用割线算法来做到这一点。 My problem is that this function takes as arguments the data, which is pulled in the main function from a csv file.我的问题是,这个 function 将数据作为 arguments 数据,这些数据是从 Z628ZCB5675FFE884B 文件中提取的主 function

One of the arguments of the secant algorithm is a function that takes a double and returns a double, but the function I've written for the objective's derivative has to take a whole host of other crap that mathematically we'd consider parameters (things like the data, the choice of kernel function, etc.).割线算法的 arguments 之一是 function,它采用双精度并返回双精度,但 function 我已经写了一个像其他目标一样的参数数据,选择kernel function等)。

I need to be able to write a function that uses the function defining the objective, puts in the data that the main function pulls from the file, and takes as its only input a double variable.我需要能够编写一个 function 使用 function 定义目标,放入主要 function 的数据作为输入,并从文件中提取双倍变量。 Is there a way of doing this?有没有办法做到这一点?

double cvobjective(double data[], int n, double (*k)(double), double (*kd)(double), double h)
{
    double cvob = 0;
    double xi;
    double xj;
    for(int i = 0; i < n; ++i)
    {
        xi = data[i];
        double sumki = 0;
        double sumkdi = 0;
        for(int j = 0; j < n; ++j) //find sum of k((xj-xi)/h) and k'((xj-xi)/h)*(xj-xi)
        {
            xj = data[j];
            sumki = sumki + k((xj-xi)/h);
            sumkdi = sumkdi + kd((xj-xi)/h)*(xj-xi);
        }
        sumki = sumki-k(0);//gets rid of the terms where i=j
        sumkdi = sumkdi-kd(0);
        cvob = cvob - reciprocal(sumki)*(reciprocal(h)*sumki+reciprocal(pow(h,2))*sumkdi);
    }
    return cvob;
}

double secantmethod(double (*obj)(double), double init, double tolerance, int giveup)
{
    double x = init;
    double old = init+1;
    double newp;
    double fold = obj(old);
    double fnew;

    for(int i=0;i<giveup;++i)
    {
        fnew = obj(x);
        if(abs(fnew-fold)<tolerance)
        {
            cout << "Objective values get too close after " << i << " iterations." << endl;
            break;
        }
        newp = newp - (x-old)*reciprocal(fnew-fold)*fnew;
        old = x;
        x = newp;
        cout << "Estimate is currently: " << x << endl;
        fold = fnew;

        if(abs(fnew)<tolerance)
            break;
        if(i == giveup - 1)
            cout << "Secant algorithm did not converge." << endl;
    }
    return newp;
}

int main()
{
    const int N = 19107;
    double incomes[N];
    std::ifstream ifile("incomes.csv", std::ios::in);
    std::vector<double> scores;

    //check to see that the file was opened correctly:
    if (!ifile.is_open()) {
        std::cerr << "There was a problem opening the input file.\n";
        exit(1);//exit or do additional error checking
    }

    double num = 0.0;
    //keep storing values from the text file so long as data exists:
    while (ifile >> num) {
        scores.push_back(num);
    }

    //verify that the scores were stored correctly:
    for (int i = 0; i < scores.size(); ++i) {
        incomes[i]=scores[i];
    }

    double sv = silverman(incomes,N);
    double cvbandwidth = secantmethod(cvobj,sv,0.000001,100);
    cout << setprecision(10) << cvbandwidth << endl;
    return 0;
}

Obviously I've left out some of the code for the more peripheral functions that aren't important.显然,我省略了一些不重要的外围功能的代码。 I thought about if it would be possible to change the secantmethod algorithm so that it expected to take a function that had as its input all of the things that cvobjective has as inputs but it wasn't immediately clear to me how I'd do that.我想是否有可能改变 secantmethod 算法,以便它期望采用 function 作为其输入作为输入的所有 cvobjective 作为输入的东西,但我并不清楚我将如何做到这一点.

Ideally I'd be able to create a function inside of main so that the incomes array was in the scope of that function, but either I don't understand lambdas properly or they aren't particularly suited to this purpose.理想情况下,我可以在 main 内部创建一个 function 以便收入数组位于 function 的 scope 中,但我不是特别适合理解这个目的,或者他们不是特别适合理解这个目的。 Failing that, if there's a way for changing secantmethod in the way described above, that would also work.如果做不到这一点,如果有办法以上述方式更改割线方法,那也可以。

EDIT: In the above cvobj isn't defined and currently serves as a placeholder.编辑:在上面的 cvobj 中没有定义,目前用作占位符。 What I'd like it to be is something like我希望它是这样的

double cvobj(double h)
return cvobjective(incomes,N,normpdf,normpdfdiff,h);

but obviously when I try that, it complains that incomes and N aren't in the scope of the function.但显然,当我尝试这样做时,它抱怨收入和 N 不在 function 的 scope 中。

So I think I found a workaround, which was to define the class所以我想我找到了一种解决方法,即定义 class

class kernelwdata
{
public:
    double observations[N];
    double cvobj(double h)
    {
        return cvobjective(observations,N,normpdf,normpdfdiff,h);
    }
};

and change secantmethod so that it takes kernelwdata as the input.并更改 secantmethod 使其将 kernelwdata 作为输入。 Now the code shown before looks like现在之前显示的代码看起来像

double cvobjective(double data[], int n, double (*k)(double), double (*kd)(double), double h)
{
    double cvob = 0;
    double xi;
    double xj;
    for(int i = 0; i < n; ++i)
    {
        xi = data[i];
        double sumki = 0;
        double sumkdi = 0;
        for(int j = 0; j < n; ++j) //find sum of k((xj-xi)/h) and k'((xj-xi)/h)*(xj-xi)
        {
            xj = data[j];
            if(j==i)
                xj=xi+1;
            sumki = sumki + k((xj-xi)/h);
            sumkdi = sumkdi + kd((xj-xi)/h)*(xj-xi);
        }
        sumki = sumki-k(1/h);//gets rid of the terms where i=j
        sumkdi = sumkdi-kd(1/h);
        cvob = cvob - reciprocal(sumki)*(reciprocal(h)*sumki+reciprocal(pow(h,2))*sumkdi);
    }
    return cvob;
}

class kernelwdata
{
public:
    double observations[N];
    double cvobj(double h)
    {
        return cvobjective(observations,N,normpdf,normpdfdiff,h);
    }
};

double secantmethod(kernelwdata obj, double init, double tolerance, int giveup)
{
    double x = init;
    double old = init+1;
    double newp;
    double fold = obj.cvobj(old);
    double fnew;

    for(int i=0;i<giveup;++i)
    {
        fnew = obj.cvobj(x);
        cout << "fold is " << fold << " and fnew is " << fnew << endl;
        if(abs(fnew-fold)<tolerance)
        {
            cout << "Objective values get too close after " << i << " iterations." << endl;
            break;
        }
        newp = newp - (x-old)*reciprocal(fnew-fold)*fnew;
        old = x;
        x = newp;
        cout << "Estimate is currently: " << x << endl;
        fold = fnew;

        if(abs(fnew)<tolerance)
            break;
        if(i == giveup - 1)
            cout << "Secant algorithm did not converge." << endl;
    }
    return newp;
}

double silverman(double data[], int n)
{
    double mean = 0;
    for(int counter = 0; counter < n; ++counter)
        mean = mean+data[counter]/n;
    double sigmahat = 0;
    for(int counter = 0; counter < n; ++counter)
    {
        sigmahat = sigmahat + pow(data[counter]-mean,2);
    }
    sigmahat = sigmahat/(n-1);
    sigmahat = sqrt(sigmahat);
    double m = (double) n;
    return sigmahat*pow(m,-0.2);
}

int main()
{
    kernelwdata incomes;
    std::ifstream ifile("incomestest.csv", std::ios::in);
    std::vector<double> scores;

    //check to see that the file was opened correctly:
    if (!ifile.is_open()) {
        std::cerr << "There was a problem opening the input file.\n";
        exit(1);//exit or do additional error checking
    }

    double num = 0.0;
    //keep storing values from the text file so long as data exists:
    while (ifile >> num) {
        scores.push_back(num);
    }

    //verify that the scores were stored correctly:
    for (int i = 0; i < scores.size(); ++i) {
        incomes.observations[i]=scores[i];
    }

    //double sv = silverman(incomes.observations,N);
    double cvbandwidth = secantmethod(incomes,10,0.000001,100);
    cout << "The cross-validation bandwidth is: " << setprecision(10) << cvbandwidth << endl;
    return 0;
}

and I'm now arguing with the output it's giving me (pretty sure a maths problem somewhere) rather than not being a thing I can compile yet.我现在正在与 output 争论它给了我(很确定某处的数学问题),而不是我还不能编译的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获得在 main() function 中构造的 class 的创建的 object? - How can I get the created object of the class that is constructed in main() function? 如何在主 function 之外创建 object? - How object can be created outside main function? 我们可以在C ++的主要功能之后定义结构吗? - Can we define structs after the main function in C++? C ++:如何在不创建对象的情况下在main函数中调用方法 - c++ : how can I call a method in main function without creating an object 如何在主函数之外的 C++ 中为 goto 定义标签? - How to define labels for goto in C++ outside main function? C ++使用模板函数,定义一个在主函数中具有ostream类变量的构造函数 - C++ using template function, define a constructor having ostream class variable in main function c ++:函数使用main中定义的对象的方法 - c++: Function using method of object defined in main 在c ++中,main函数是编程如何将其更改为其他函数的入口点? - in c++ main function is the entry point to program how i can change it to an other function? 我怎样才能制作一个 C++ function,它可以使用 gdb 漂亮地打印每个 object? - How can I make a C++ function that can pretty print every object, using gdb? "为什么我可以在 C++ 中的函数中定义结构和类?" - Why can I define structures and classes within a function in C++?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM