簡體   English   中英

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

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

我正在嘗試編寫一個程序,該程序將為 c++ 中的 kernel 估計器提供交叉驗證帶寬(大約有 20,000 個數據點,所以 ZA5CD8A07B40F6449056939C13140 太慢了)AE 我通過對留一估計器的目標的導數使用割線算法來做到這一點。 我的問題是,這個 function 將數據作為 arguments 數據,這些數據是從 Z628ZCB5675FFE884B 文件中提取的主 function

割線算法的 arguments 之一是 function,它采用雙精度並返回雙精度,但 function 我已經寫了一個像其他目標一樣的參數數據,選擇kernel function等)。

我需要能夠編寫一個 function 使用 function 定義目標,放入主要 function 的數據作為輸入,並從文件中提取雙倍變量。 有沒有辦法做到這一點?

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;
}

顯然,我省略了一些不重要的外圍功能的代碼。 我想是否有可能改變 secantmethod 算法,以便它期望采用 function 作為其輸入作為輸入的所有 cvobjective 作為輸入的東西,但我並不清楚我將如何做到這一點.

理想情況下,我可以在 main 內部創建一個 function 以便收入數組位於 function 的 scope 中,但我不是特別適合理解這個目的,或者他們不是特別適合理解這個目的。 如果做不到這一點,如果有辦法以上述方式更改割線方法,那也可以。

編輯:在上面的 cvobj 中沒有定義,目前用作占位符。 我希望它是這樣的

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

但顯然,當我嘗試這樣做時,它抱怨收入和 N 不在 function 的 scope 中。

所以我想我找到了一種解決方法,即定義 class

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

並更改 secantmethod 使其將 kernelwdata 作為輸入。 現在之前顯示的代碼看起來像

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;
}

我現在正在與 output 爭論它給了我(很確定某處的數學問題),而不是我還不能編譯的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM