Esempio n. 1
0
void BackwardEulerUpdater::update( const std::vector<double> & uOld,
                                   std::vector<double>* uNew,
                                   const std::vector<double> & prem ) const
{
    int N = uOld.size()-1;
    double c = getAlpha();

    // Construct b-vector
    Eigen::VectorXd b = Eigen::VectorXd::Zero(N-1);
    for (int i=0; i<N-1; i++) { b(i) = uOld[i+1]; }

    b(0) += c*(*uNew)[0];
    b(N-2) += c*(*uNew)[N];
    
    // Construct early exercise premium vector
    Eigen::VectorXd p = Eigen::VectorXd::Zero(0);
    if ( prem.size()>0 ) {
        p = Eigen::VectorXd::Zero(N-1);
        for (int i=0; i<N-1; i++) { p(i) = prem[i+1]; }
    }
   
    // update 
    Eigen::VectorXd y = forward_subst(d_L, b);
    Eigen::VectorXd x = backward_subst(d_U, y, p);
    
    for (int i=0; i<N-1; i++) { (*uNew)[i+1] = x(i); }
}
Esempio n. 2
0
void CrankNicolsonUpdater::update( const std::vector<double> & uOld,
                                   std::vector<double>* uNew,
                                   const std::vector<double> & prem ) const
{
    int N = uOld.size()-1;
    double c = getAlpha();

    // uOld restricted in the interior region
    Eigen::VectorXd u = Eigen::VectorXd::Zero(N-1);
    for (int i=0; i<N-1; i++) { u(i) = uOld[i+1]; }

    // Construct b-vector
    Eigen::VectorXd b = d_B*u;

    b(0) += 0.5*c*((*uNew)[0]+uOld[0]);
    b(N-2) += 0.5*c*((*uNew)[N]+uOld[N]);
    
    // Construct early exercise premium vector
    Eigen::VectorXd p = Eigen::VectorXd::Zero(0);
    if ( prem.size()>0 ) {
        p = Eigen::VectorXd::Zero(N-1);
        for (int i=0; i<N-1; i++) { p(i) = prem[i+1]; }
    }
    
    // update 
    Eigen::VectorXd y = forward_subst(d_L, b);
    Eigen::VectorXd x = backward_subst(d_U, y, p);
    
    for (int i=0; i<N-1; i++) { (*uNew)[i+1] = x(i); }
}
TEST_F(TriangularSolveTest, BackwardSubstMatchEigenComputedResults)
{
    Eigen::MatrixXd U = Eigen::MatrixXd::Random(2,2);
    Eigen::VectorXd b = Eigen::VectorXd::Random(2);
    U.triangularView<Eigen::StrictlyLower>().setZero();
    Eigen::VectorXd x = backward_subst(U, b);
    Eigen::VectorXd y = U.triangularView<Eigen::Upper>().solve(b);
    double tol = 1e-16;
    EXPECT_NEAR((x-y).norm(), 0, tol);
}
Esempio n. 4
0
void solve_qr_decomp(double* qr, int m, int n, int ldim, double* b, double *x)
{
    double *z;
    int j, i;

    qr_transform(qr, m, n, ldim, b);
    printf("\nz:\n");
    print_matrix(b, n, 1);

    backward_subst(qr, n, ldim, b, x);
}
Eigen::VectorXd spd_solve(const Eigen::MatrixXd & A,
                          const Eigen::VectorXd & b)
{
    int n = b.size();
    assert(A.rows() == n);
    assert(A.cols() == n);

    Eigen::MatrixXd U = cholesky(A);
    Eigen::VectorXd y = forward_subst(U.transpose(), b);
    Eigen::VectorXd x = backward_subst(U, y);

    return x;
}
Esempio n. 6
0
int main(int argc, char* argv[])
{
    // Output precision
    int p=9;
    // Matrix dimension
    int N=9;
    // Matrix specification
    Eigen::MatrixXd A = Eigen::MatrixXd::Zero(N,N); 
    Eigen::MatrixXd A1 = Eigen::MatrixXd::Zero(N,N); 
    for (int i=0; i<N; i++) {
        A1(i,i) = 4.0;
        if (i>=1) A1(i,i-1) = -1.0;
        if (i>=2) A1(i,i-2) = 3.0;
        if (i<=6) A1(i,i+2) = -2.0;
    }
    // Could be AT+A or AT*A
    A = A1.transpose()+A1;
    // Vector specification
    Eigen::VectorXd b = Eigen::VectorXd::Zero(N);
    for (int i=0; i<N; i++) {
        b(i) = (i*i-9.0)/(i+5.0); 
    }

    // Cholesky decomposition
    Eigen::MatrixXd U = cholesky(A);
    Eigen::MatrixXd L = U.transpose();

    // Perform forward substitution and backward substitution
    // Using Eigen's library method: Eigen::VectorXd x = A.llt().solve(b);
    Eigen::VectorXd y = forward_subst(L, b);
    Eigen::VectorXd x = backward_subst(U, y);

    // Compute residual error
    double R = (A*x-b).norm();
    std::cout << "Residual error =, "
              << std::setprecision(p)
              << R
              << std::endl;

    // Compute L-inverse, U-inverse, and A-inverse
    Eigen::MatrixXd L_inv = Eigen::MatrixXd::Zero(N,N);
    Eigen::MatrixXd U_inv = Eigen::MatrixXd::Zero(N,N);
    Eigen::MatrixXd A_inv = Eigen::MatrixXd::Zero(N,N);
    // L-inverse
    for (int i=0; i<N; i++) {
        Eigen::VectorXd ei = Eigen::VectorXd::Zero(N);
        ei(i) = 1;
        Eigen::VectorXd x = forward_subst(L, ei);
        L_inv.col(i) = x;
    }
    // U-inverse
    for (int i=0; i<N; i++) {
        Eigen::VectorXd ei = Eigen::VectorXd::Zero(N);
        ei(i) = 1;
        Eigen::VectorXd x = backward_subst(U, ei);
        U_inv.col(i) = x;
    }
    // A-inverse
    for (int i=0; i<N; i++) {
        Eigen::VectorXd ei = Eigen::VectorXd::Zero(N);
        ei(i) = 1;
        Eigen::VectorXd y = forward_subst(L, ei);
        Eigen::VectorXd x = backward_subst(U, y);
        A_inv.col(i) = x;
    }
    
    // Compute residual error by matrix inverse
    Eigen::VectorXd v = A_inv*b;
    R = (b-A*v).norm();
    std::cout << "Residual error by inverse =, "
              << std::setprecision(p)
              << R
              << std::endl;

    std::cout << "Cholesky decomposition" << std::endl;
    for (int i=0; i<N; i++) {
        std::cout << " |, ";
        for (int j=0; j<N; j++) {
            std::cout << std::right 
                      << std::setw(p+3) 
                      << std::fixed 
                      << std::setprecision(p) 
                      << A(i,j) 
                      << ", ";
        }
        std::cout << " |, =, |, ";
        for (int j=0; j<N; j++) {
            std::cout << std::right 
                      << std::setw(p+3) 
                      << std::fixed 
                      << std::setprecision(p) 
                      << L(i,j) 
                      << ", ";
        }
        std::cout << " |, ";
        for (int j=0; j<N; j++) {
            std::cout << std::right 
                      << std::setw(p+3) 
                      << std::fixed 
                      << std::setprecision(p) 
                      << U(i,j) 
                      << ", ";
        }
        std::cout << " |, " << std::endl;
    }

    std::cout << "Linear solve - x:" << std::endl;
    for (int i=0; i<N; i++) {
        std::cout << std::right 
                  << std::setw(p+3) 
                  << std::fixed 
                  << std::setprecision(p) 
                  << x(i)
                  << std::endl; 
    }
    
    std::cout << "Inverse relations:" << std::endl;
    for (int i=0; i<N; i++) {
        std::cout << " |, ";
        for (int j=0; j<N; j++) {
            std::cout << std::right 
                      << std::setw(p+3) 
                      << std::fixed 
                      << std::setprecision(p) 
                      << A_inv(i,j) 
                      << ", ";
        }
        std::cout << " |, =, |, ";
        for (int j=0; j<N; j++) {
            std::cout << std::right 
                      << std::setw(p+3) 
                      << std::fixed 
                      << std::setprecision(p) 
                      << U_inv(i,j) 
                      << ", ";
        }
        std::cout << " |, ";
        for (int j=0; j<N; j++) {
            std::cout << std::right 
                      << std::setw(p+3) 
                      << std::fixed 
                      << std::setprecision(p) 
                      << L_inv(i,j) 
                      << ", ";
        }
        std::cout << " |, " << std::endl;
    }
    
    std::cout << "Linear solve by inversion- x:" << std::endl;
    for (int i=0; i<N; i++) {
        std::cout << std::right 
                  << std::setw(p+3) 
                  << std::fixed 
                  << std::setprecision(p) 
                  << v(i)
                  << std::endl; 
    }
    
    // Verify accuracy of matrix inverse
    std::cout << "L * L-inverse residual error =, "
              << std::scientific
              << std::setprecision(p)
              << (L*L_inv-Eigen::MatrixXd::Identity(N,N)).norm() 
              << std::endl;
    std::cout << "U * U-inverse residual error =, "
              << std::scientific
              << std::setprecision(p)
              << (U*U_inv-Eigen::MatrixXd::Identity(N,N)).norm() 
              << std::endl;
    std::cout << "A * A-inverse residual error =, "
              << std::scientific
              << std::setprecision(p)
              << (A*A_inv-Eigen::MatrixXd::Identity(N,N)).norm() 
              << std::endl;

    return 0;
}