使用 Eigen class 对向量中的某些数字求和

Using Eigen class to sum certain numbers in a vector

我是 C++ 的新手,我正在使用 Eigen 库。我想知道是否有办法对向量中的某些元素求和。例如,假设我有一个 100 乘 1 的向量,我只想对前 10 个元素求和。有没有办法使用 Eigen 库来做到这一点?

我想做的是:假设我有一个 1000 乘 1 的向量,我想取前 10 个元素的平均值,然后是接下来的 10 个元素,依此类推,并将其存储在一些向量。因此,我将有一个平均大小为 100 的向量。非常感谢任何想法或建议。

这是我的代码中的开始步骤。我有一个 1000 乘 1 的 S_temp4 向量。现在我初始化一个新的向量 S_A,我想将其作为平均值的向量。到目前为止,这是我凌乱的草率代码:(请注意,我的问题在于 crudeMonteCarlo 函数)

#include <iostream>
#include <cmath>
#include <math.h>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>
#include <time.h>

using namespace Eigen;
using namespace std;

void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n);
VectorXd time_vector(double min, double max, int n);
VectorXd call_payoff(VectorXd S, double K);

int main(){
    int N = 100;
    double K = 100;
    double r = 0.2;
    double S0 = 100;
    double sigma = 0.4;
    double T = 0.1;
    int n = 10;

    crudeMonteCarlo(N,K,r,S0,sigma,T,n);

    return 0;
}

VectorXd time_vector(double min, double max, int n){
    VectorXd m(n + 1);
     double delta = (max-min)/n;
     for(int i = 0; i <= n; i++){
             m(i) = min + i*delta;
     }
    return m;
}

MatrixXd generateGaussianNoise(int M, int N){
    MatrixXd Z(M,N);
    static random_device rd;
    static mt19937 e2(time(0));
    normal_distribution<double> dist(0.0, 1.0);
    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++){
            Z(i,j) = dist(e2);
        }
    }
    return Z;
}

VectorXd call_payoff(VectorXd S, double K){
    VectorXd C(S.size());
    for(int i = 0; i < S.size(); i++){
        if(S(i) - K > 0){
            C(i) = S(i) - K;
        }else{
            C(i) = 0.0;
        }
    }
    return C;
}

void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n){
    // Create time vector
    VectorXd tt = time_vector(0.0,T,n);
    VectorXd t(n);
    double dt = T/n;
    for(int i = 0; i < n; i++){
            t(i) = tt(i+1);
    }

    // Generate standard normal Z matrix
    //MatrixXd Z = generateGaussianNoise(N,n);

    // Generate the log normal stock process N times to get S_A for crude Monte Carlo
    MatrixXd SS(N,n+1);
    MatrixXd Z = generateGaussianNoise(N,n);
    for(int i = 0; i < N; i++){
        SS(i,0) = S0;
        for(int j = 1; j <= n; j++){
                SS(i,j) = SS(i,j-1)*exp((double) (r - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
        }
    }

    // This long bit of code gives me my S_A.....
    Map<RowVectorXd> S_temp1(SS.data(), SS.size());
    VectorXd S_temp2(S_temp1.size());
    for(int i = 0; i < S_temp2.size(); i++){
        S_temp2(i) = S_temp1(i);
    }
    VectorXd S_temp3(S_temp2.size() - N);
    int count = 0;
    for(int i = N; i < S_temp2.size(); i++){
        S_temp3(count) = S_temp2(i);
        count++;
    }
    VectorXd S_temp4(S_temp3.size());
    for(int i = 0; i < S_temp4.size(); i++){
        S_temp4(i) = S_temp3(i);
    }
    VectorXd S_A(N);
    S_A(0) = (S_temp4(0) + S_temp4(1) + S_temp4(2) + S_temp4(3) + S_temp4(4) + S_temp4(5) + S_temp4(6) + S_temp4(7) + S_temp4(8) + S_temp4(9))/(n);
    S_A(1) = (S_temp4(10) + S_temp4(11) + S_temp4(12) + S_temp4(13) + S_temp4(14) + S_temp4(15) + S_temp4(16) + S_temp4(17) + S_temp4(18) + S_temp4(19))/(n);
    int count1 = 0;
    for(int i = 0; i < S_temp4.size(); i++){
        S_A(count1) = 
    }



    // Calculate payoff of Asian option
    //VectorXd call_fun = call_payoff(S_A,K);




}

https://eigen.tuxfamily.org/dox/group__TutorialBlockOperations.html 的 Eigen 文档说,Eigen 块是矩阵或数组的矩形部分,由 matrix.block(i,j,p,q) 访问,其中 i 和 j 是起始值(例如 0 和 0),p和 q 是块大小(例如 10 和 1)。据推测,然后您将以 10 为步长迭代 i,并使用 std::accumulate 或者可能是显式求和来找到 matrix.block(i,0,10,1).

的平均值

这个问题包含了很多代码,这让你很难理解你想问的问题。考虑仅包括特定于您的问题的代码。

无论如何,您可以直接使用 Eigen 来非常简单地完成所有这些事情。在 Eigen 中,向量只是具有 1 列的矩阵,因此这里的所有推理都直接适用于您所写的内容。

const Eigen::Matrix<double, 100, 1> v = Eigen::Matrix<double, 100, 1>::Random();

const int num_rows = 10;
const int num_cols = 1;

const int starting_row = 0;
const int starting_col = 0;

const double sum_of_first_ten = v.block(starting_row, starting_col, num_rows, num_cols).sum();
const double mean_of_first_ten = sum_of_first_ten / num_rows;

总结:可以用.block得到一个块对象,.sum()对该块求和,然后常规除法得到均值。

您可以使用 Map 重塑输入,然后在没有任何循环的情况下一次完成所有子求和:

VectorXd A(1000);                           // input
Map<MatrixXd> B(A.data(), 10, A.size()/10); // reshaped version, no copy
VectorXd res = B.colwise().mean();          // partial reduction, you can also use .sum(), .minCoeff(), etc.