#include <vector>
#include <cassert>

#include <iostream>

#include <Eigen/Dense>
#include <Eigen/Sparse>

// Flag for slope reconstruction type
enum class Slope { Zero, Reconstructed };

//! \breif Implements a piecewise cubic Herite interpolation on equidistant meshes.
class PCHI {
public:
    //! \brief Construct the slopes frome the data, either usinf dinite-differences or assuming f'(x_j) = 0
    //! \param[in] t vector of nodes (assumed equidistant and sorted)
    //! \param[in] y vector of values at nodes t
    //! \param[in] s Flag to set if you want to reconstruct or set slopes to zero
    PCHI(const Eigen::VectorXd & t, const Eigen::VectorXd & y, Slope s = Slope::Reconstructed)
        : t(t), y(y), c(t.size()) {
        // Sanity check
        n = t.size();
        assert( n == y.size() && "t and y must have same dimension." );
        assert( n >= 3 && "need at least two nodes." );
        h = t(1) - t(0);

        switch(s) {
            //// CASE: reconstruction of the slope, assuming f'(x_j) = 0 (O(1))
            case Slope::Zero:
                c = Eigen::VectorXd::Zero(n);
                break;
            //// CASE: reconstruction of the slope using a second order finite difference (O(h^2))
            case Slope::Reconstructed:
            default:
//                 c(0) = ( y(1) - y(0) ) / h; // First order
                c(0) = ( -1*y(2) + 4*y(1) - 3*y(0) ) / 2 / h;
                for(int i = 1; i < n-1; ++i) {
                    c(i) = ( y(i+1) - y(i-1) ) / 2 / h;
                }
//                 c(n-1) = ( y(n-1) - y(n-2) ) / h; // First order
                c(n-1) = ( 3*y(n-1) - 4*y(n-2) + 1*y(n-3) ) / 2 / h;
                break;
        }
    }

    //! \brief Evaluate the intepolant at the nodes x
    //! Input assumed sorted, unique and inside the interval
    //! \param[in] x vector of points t where to compute s(t)
    //! \return values of interpolant at x (vector)
    Eigen::VectorXd operator() (Eigen::VectorXd x) const {

        Eigen::VectorXd ret(x.size());
        // Stores the current interval index and some temporary variable
        int i_star = 0;
        double tmp,t1,y1,y2,c1,c2,a1,a2,a3;
        for(int j = 0; j < x.size(); ++j) {
            // Find interval and porting of hermloceval Matlab code 3.4.6
            if( t(i_star) < x(j) || i_star == 0) {
                ++i_star;
                t1 = t(i_star-1);
                y1 = y(i_star-1);
                y2 = y(i_star);
                c1 = c(i_star-1);
                c2 = c(i_star);
                a1 = y2 - y1;
                a2 = a1 - h*c1;
                a3 = h*c2 - a1 - a2;
            }
            // Compute s(x(j))
            tmp = ( x(j) - t1 ) / h;
            ret(j) = y1 + ( a1 + ( a2+a3*tmp ) * ( tmp - 1. ) ) * tmp;
        }

        return ret;
    }

private:
    // Provided nodes and values (t,y) to compute spline, same size Eigen vectors, c contains slopes
    Eigen::VectorXd t, y, c;
    // Difference t(i)-t(i-1) and coefficients of spline (s'(t_j))
    double h;
    // Size of t, y and c.
    int n;
};

// Interpoland
auto f = [] (double x) { return 1. / (1. + x*x); };
// auto f = [] (double x) {return cos(x); };

int main() {

    double a = 5; // Interval (-a,a) bounds
    int M = 1000; // Number of  points in which to evaluate

    // Number of subintervals for each test
    std::vector<int> N = {4,8,16,32,64,128,256,512};

    // Precompute values at which evaluate f
    Eigen::VectorXd x = Eigen::VectorXd::LinSpaced(M, -a, a);
    Eigen::VectorXd fx(x.size());
    for(int i = 0; i < x.size(); ++i) {
        fx(i) = f(x(i));
    }

    // Store error and rates
    std::vector<double> err, err_zero, rate, rate_zero;

    std::cout << "L^infty-error [reconstruction, zero] (rate / rate)" << std::endl;
    for(int n : N) {
        // Define subintervals and evaluate f there (find pairs (t,y))
        Eigen::VectorXd t = Eigen::VectorXd::LinSpaced(n, -a, a);
        Eigen::VectorXd y(t.size());
        for(int i = 0; i < t.size(); ++i) {
            y(i) = f(t(i));
        }

        // Construct PCHI with zero and reconstructed slopes
        PCHI P(t,y), Pz(t,y,Slope::Zero);

        // Compute infinity norm of error
        err.push_back((P(x) - fx).lpNorm<Eigen::Infinity>());
        err_zero.push_back((Pz(x) - fx).lpNorm<Eigen::Infinity>());

        // Store errors and rates
        std::cout << err.back()  << "    " << err_zero.back() ;
        if( err.size() > 1 ) {
            rate.push_back( log( *(err.end() - 2) / err.back()  ) / log(2) );
            rate_zero.push_back( log( *(err_zero.end() - 2) / err_zero.back() ) / log(2) );
            std::cout << " (" << rate.back() << " / " << rate_zero.back() << ")";
        }
        std::cout << std::endl;

    }
}

Nummerical Methods for CSE/PS9/solutions_ps9/piecewise_hermite_interpolation.cpp


#include <iostream>

#include <Eigen/Dense>

Eigen::MatrixXd Vandermonde(const Eigen::VectorXd &x, int n) {
  int m = x.size();
	Eigen::MatrixXd V(m, n);

	V.col(0) = Eigen::VectorXd::Ones(m);

  for(int i = 1; i < n; i++) {
    V.col(i) = V.col(i - 1).cwiseProduct(x);
  }

  return V;
}

Eigen::VectorXd r(const Eigen::VectorXd &x) {
	return (1.0 / (1.0 + 25.0 * x.array() * x.array())).matrix();
}

int main() {
	int n = 11;				// Number of polynomial coefficients
	int m;					// Number of samples
	Eigen::MatrixXd V;		// Vandermonde matrix
	Eigen::VectorXd x;		// Samples in [-1, 1]
	Eigen::VectorXd y;		// r(x)
	Eigen::VectorXd a(n);	// Polynomial coefficients

	Eigen::IOFormat PythonFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ";\n", "[", "]", "[", "]");

	std::cout << "Polynomial coefficients obtained by..." << std::endl;

	// Compute overfitted polynomial coefficients
	m = n;
	x.setLinSpaced(m, -1.0, 1.0);
  y = r(x);
  V = Vandermonde(x, n);
	a = V.fullPivLu().solve(y);

	std::cout << "...overfitting:" << std::endl;
	std::cout << a.transpose().format(PythonFmt) << std::endl;

	// Compute least squares polynomial coefficients
	m = 3 * n;
	x.setLinSpaced(m, -1.0, 1.0);

  y = r(x);
  V = Vandermonde(x, n);
  // no pivoting required gaussian elimination remains stable since V^TV is s.p.d
  a = (V.transpose() * V).llt().solve(V.transpose() * y);

	std::cout << "...least squares:" << std::endl;
	std::cout << a.transpose().format(PythonFmt) << std::endl;

	return 0;
}


#include <iostream>
#include "Log.h"
//using namespace std;
#include <ctime>
// Eigen libraries
#include <Eigen/Core>
// Algebraic operations on dense matrices (inverse, eigenvalues, etc.)
#include <Eigen/Dense>

#define MATRIX_SIZE 50

/****************************
* Basic usage of Eigen matrix
****************************/

int main( int argc, char** argv )
{
    //Set the log first
    za::my_logger::logger_type log = za::my_logger::get();
    za::Log logManager;
    logManager.set_log_file("./log/logEigenMatix.log");
    BOOST_LOG_SEV(log, za::report) <<"Basic Eigen lib Matrix demo\n";

    //All vectors and matrices in Eigen are Eigen::Matrix, which is a template class.
    //Its first three parameters are: data type, row, column
    // Declare a 2*3 float matrix
    Eigen::Matrix<float, 2, 3> matrix_23;

    // At the same time, Eigen provides many built-in types through typedef,
    // but the bottom layer is still Eigen::Matrix
    // For example, Vector3d is essentially Eigen::Matrix<double, 3, 1>,
    // which is a three-dimensional vector
    Eigen::Vector3d v_3d;
	// Same as
    Eigen::Matrix<float,3,1> vd_3d;

    // Matrix3d is essentially Eigen::Matrix<double, 3, 3>
    Eigen::Matrix3d matrix_33 = Eigen::Matrix3d::Zero(); //Initialized to zero
    // If you are not sure about the size of the matrix
    // you can use a dynamically sized matrix
    Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > matrix_dynamic;
    // Simple format for unknown size
    Eigen::MatrixXd matrix_x;
    // Check other type of dynamic matrix

    // The following is the operation of the Eigen array
     // Input data (initialization)
    matrix_23 << 1, 2, 3, 4, 5, 6;
    BOOST_LOG_SEV(log, za::report)  << "2 by 3 matrix initialization, row major:\n";
    // Output
    BOOST_LOG_SEV(log, za::report)  << matrix_23 << "\n";

    // Use () to access the elements in the matrix
    for (int i=0; i<matrix_23.rows(); i++)
    {
        for (int j=0; j < matrix_23.cols(); j++)BOOST_LOG_SEV(log, za::report) <<matrix_23(i,j)<<"\t";BOOST_LOG_SEV(log, za::report) <<"\n";
    }

    // Multiply matrix and vector (actually it is still matrix and matrix)
    v_3d << 3, 2, 1;
    vd_3d << 4,5,6;
    // But in Eigen you cannot mix two different types of matrices, like this is wrong
    // Eigen::Matrix<double, 2, 1> result_wrong_type = matrix_23 * v_3d;
    // should be explicitly converted
    Eigen::Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;
    BOOST_LOG_SEV(log, za::report)  << result << "\n";

    Eigen::Matrix<float, 2, 1> result2 = matrix_23 * vd_3d;
    BOOST_LOG_SEV(log, za::report)  << result2 << "\n";

    // Similarly you can't make a mistake about the dimensions of the matrix
    // Try to cancel the comment below and see what error Eigen will report
    // Eigen::Matrix<double, 2, 3> result_wrong_dimension = matrix_23.cast<double>() * v_3d;

    // some matrix operations
    // The four arithmetic operations will not be demonstrated, just use +-*/.。
    matrix_33 = Eigen::Matrix3d::Random();      // Random number matrix
    BOOST_LOG_SEV(log, za::report)  << matrix_33 << "\n" << "\n";

    BOOST_LOG_SEV(log, za::report)  << matrix_33.transpose() << "\n";      // Transpose
    BOOST_LOG_SEV(log, za::report)  << matrix_33.sum() << "\n";            // Sum
    BOOST_LOG_SEV(log, za::report)  << matrix_33.trace() << "\n";          // Trace
    BOOST_LOG_SEV(log, za::report)  << 10*matrix_33 << "\n";               // Multiplication
    BOOST_LOG_SEV(log, za::report)  << matrix_33.inverse() << "\n";        // Inverse
    BOOST_LOG_SEV(log, za::report)  << matrix_33.determinant() << "\n";    // Determinant

    // Eigenvalues
    // Real symmetric matrix can ensure the success of diagonalization
    Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigen_solver ( matrix_33.transpose()*matrix_33 );
    BOOST_LOG_SEV(log, za::report)  << "Eigen values = \n" << eigen_solver.eigenvalues() << "\n";
    BOOST_LOG_SEV(log, za::report)  << "Eigen vectors = \n" << eigen_solver.eigenvectors() << "\n";

    // Solving equations
    // We solve the equation matrix_NN * x = v_Nd
    // The size of N is defined in the previous macro, it is generated by a random number
    // Direct inversion is naturally the most straightforward, but the amount of inversion calculations is large

    Eigen::Matrix< double, MATRIX_SIZE, MATRIX_SIZE > matrix_NN;
    matrix_NN = Eigen::MatrixXd::Random( MATRIX_SIZE, MATRIX_SIZE );
    Eigen::Matrix< double, MATRIX_SIZE,  1> v_Nd;
    v_Nd = Eigen::MatrixXd::Random( MATRIX_SIZE,1 );

    clock_t time_stt = clock(); // timer
    // take inverse
    Eigen::Matrix<double,MATRIX_SIZE,1> x = matrix_NN.inverse()*v_Nd;
    BOOST_LOG_SEV(log, za::report)  <<"time use in normal inverse is " << 1000* (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms"<< "\n";

	// qr decomposition
    time_stt = clock();
    x = matrix_NN.colPivHouseholderQr().solve(v_Nd);
    BOOST_LOG_SEV(log, za::report)  <<"time use in Qr decomposition is " <<1000*  (clock() - time_stt)/(double)CLOCKS_PER_SEC <<"ms" << "\n";

    return 0;
}


/* ------------------------------------------------------------
 * @file: pseudoinversa.cpp
 * @dependencias: armadillo, matplotlibcpp
 * @version 0.1
 * ------------------------------------------------------------*/

// [1] $ g++ pseudoinversa.cpp -o psi.out -std=c++11
// [2] $ ./psi.out
// Nota: Asegurarse de tener armadillo bien instalado.

#include <armadillo>

using namespace std;
using namespace arma;

/**
 * @brief Calcula la aproximación a la solución de un sistema de ecuaciones por
 *        el método de la pseudoinversa.
 * @param A Matriz de coeficientes.
 * @param b Vector de términos independientes.
 * @param tol Tolerancia de la aproximación.
 * @param max_itr Iteraciones máximas.
 */
void pseudoinversa(mat A, vec b, double tol, int max_itr=15){
    int n = A.n_rows;
    int m = A.n_cols;
    double alpha = eig_sym(A*A.t()).max();

    mat I(n,m);
    I.eye();
    mat x = (1/alpha)*A.t();

    double error = tol;
    int k = 0;

    while (k < max_itr){
        x = x*(2*I-A*x);
        error = norm((A*x*A)-A);

        if (error < tol)
            break;
        k++;
    }
    mat x_p = x*b;

    // Mostrar los resultados
    x_p.print("x_p: \n");
    cout<<"Error: "<< norm(A*x_p-b)<<endl;

}

int main(int argc, char const *argv[])
{
    mat A = {{ 1, 2, 4},
             { 2,-1, 1},
             { 1, 0, 1}};
    vec b = {4,3,9};
    pseudoinversa(A,b,10e-8,3);
    return 0;
}

Catalogo/03. Sistemas de Ecuaciones/C++/pseudoinversa.cpp


// Group A - Exact Pricing Methods
//
// by Scott Sidoli
//
// 6-9-19
//
// Main.cpp
//
// In this work we create pricing methods for European options
// Questions for Group A are answered in the comments here in Main.cpp. We give an
// outline of file contents here:
//
// This is done by creating the EuropeanOption class in EuropeanOption.hpp. We outline
// array pricing. We organize the option data in a struct. This is contained in
// OptionData.hpp.

#include "EuropeanOption.hpp"
#include "MeshArray.hpp"
#include <boost/tuple/tuple_io.hpp>
#include <iomanip>

int main()
{
	// Group A =Exact Solutions of One-Factor Plain Options==================================================
	// 1 part a) Implement the above formula for call and put option pricing using data sets
	// Batch 1 to Batch 4. Check your answers.

	// Batch 1
	Time T1 = (Time) 0.25;
	Strike_Price K1 = (Strike_Price)65;
	Volatility sig1 = (Volatility) 0.30;
	rate r1 = (rate) 0.08;
	cost_of_carry b1 = (cost_of_carry) 0.08;
	curr_stock_price S1 = (curr_stock_price) 60.0;

	// Create option and set parameters
	EuropeanOption option1;
	option1.SetOption(T1, K1, sig1, r1, b1, S1);

	cout << "Batch 1 Call price: " << option1.CallPriceEuro() << endl;
	cout << "Batch 1 Put price: " << option1.PutPriceEuro() << endl;

	// Batch 2
	Time T2 = (Time) 1.0;
	Strike_Price K2 = (Strike_Price) 100.0;
	Volatility sig2 = (Volatility) 0.2;
	rate r2 = (rate) 0.00;
	cost_of_carry b2 = (cost_of_carry) 0.00;
	curr_stock_price S2 = (curr_stock_price) 100.0;

	// Create option and set parameters
	EuropeanOption option2;
	option2.SetOption(T2, K2, sig2, r2, b2, S2);

	cout << "Batch 2 Call price: " << option2.CallPriceEuro() << endl;
	cout << "Batch 2 Put price: " << option2.PutPriceEuro() << endl;

	// Batch 3
	Time T3 = (Time) 1.0;
	Strike_Price K3 = (Strike_Price) 10.0;
	Volatility sig3 = (Volatility) 0.50;
	rate r3 = (rate) 0.12;
	cost_of_carry b3 = (cost_of_carry) 0.12;
	curr_stock_price S3 = (curr_stock_price) 5.0;

	// Create option and set parameters
	EuropeanOption option3;
	option3.SetOption(T3, K3, sig3, r3, b3, S3);

	cout << "Batch 3 Call price: " << option3.CallPriceEuro() << endl;
	cout << "Batch 3 Put price: " << option3.PutPriceEuro() << endl;

	// Batch 4
	Time T4 = (Time) 30.0;
	Strike_Price K4 = (Strike_Price) 100.0;
	Volatility sig4 = (Volatility) 0.30;
	rate r4 = (rate) 0.08;
	cost_of_carry b4 = (cost_of_carry) 0.08;
	curr_stock_price S4 = (curr_stock_price) 100.0;

	// Create option and set parameters
	EuropeanOption option4;
	option4.SetOption(T4, K4, sig4, r4, b4, S4);

	cout << "Batch 4 Call price: " << option4.CallPriceEuro() << endl;
	cout << "Batch 4 Put price: " << option4.PutPriceEuro() << endl;

	cout << endl;
	//================================================================================================================================================================================
		// 1 b) Apply the put-call parity relationship lto compute the put prices given the call prices
		// We use our CalltoPutParity function.

	cout << "Using Parity: " << endl;
	cout << "Batch 1 Put Price: " << option1.CalltoPutParity() << endl;
	cout << "Batch 2 Put Price: " << option2.CalltoPutParity() << endl;
	cout << "Batch 3 Put Price: " << option3.CalltoPutParity() << endl;
	cout << "Batch 4 Put Price: " << option4.CalltoPutParity() << endl;

	cout << endl;

	// Now we check if the batches satisfy put-call parity.
	cout << "Batch 1 satisfies parity: " << (option1.ParityChecker() ? "True." : "False.") << endl;
	cout << "Batch 2 satisfies parity: " << (option2.ParityChecker() ? "True." : "False.") << endl;
	cout << "Batch 3 satisfies parity: " << (option3.ParityChecker() ? "True." : "False.") << endl;
	cout << "Batch 4 satisfies parity: " << (option4.ParityChecker() ? "True." : "False.") << endl;
	//================================================================================================================================================================================
		// 1 c) We compute the option prices for a monotonically increasing ranges of values for S, the current stock price.
		// Let S = 10, 11, 12, ... 50. We use our MeshArray.
	curr_stock_price S_start = (curr_stock_price) 10.0;
	curr_stock_price S_end = (curr_stock_price) 50.0;
	curr_stock_price S_interval = (curr_stock_price) 1.0;

	// Compute the Call prices and Put prices
	vector<curr_stock_price> S_array = MeshArray(S_start, S_end, S_interval);
	vector<double> S_CallPrices = option1.CallPriceEuro(S_array);
	vector<double> S_PutPrices = option1.PutPriceEuro(S_array);

	cout << endl;
	cout << "S - Value, Call Price, Put Price" << endl;
	PrintArray(S_array, S_CallPrices, S_PutPrices);

	cout << endl;

	// reset the option
	option1.SetOption(T1, K1, sig1, r1, b1, S1);
	//================================================================================================================================================================================
		// 1 d) We create a matrix pricer to determine prices as we vary two parameters. We use expiry time and volatility.

		// Create Vector of T-values. This is where we change our option parameter.
	Time T_start = (Time) 0.25;
	Time T_end = (Time) 5.0;
	Time T_interval = (Time) 0.25;
	vector<Time> T_array = MeshArray(T_start, T_end, T_interval);

	// Create Vector of sig-values. This is where we change our second option parameter.

	Volatility sig_start = (Volatility) 0.05;
	Volatility sig_end = (Volatility) 1.00;
	Volatility sig_interval = (Volatility) 0.05;
	vector<Volatility> sig_array = MeshArray(sig_start, sig_end, sig_interval);

	// Create two-dimensional array to store call prices and put prices
	typedef boost::tuple<double, double> CallPrice_PutPrice;
	const int num_rows = 50;
	const int num_columns = 50;
	CallPrice_PutPrice PriceMatrix[num_rows][num_columns]; // Price matrix stores call and put price when parameter I takes value x and parameter J takes value y.
														   // In this example we use expiry time and volatility.

	cout << "(Time, Volatility, (Call Price Put Price))" << endl;

	for (int i = 0; i < T_array.size(); ++i)
	{
		option1.SetOption(T_array[i]);

		for (int j = 0; j < sig_array.size(); ++j)
		{
			option1.SetOption(sig_array[j]);
			PriceMatrix[i][j] = CallPrice_PutPrice(option1.CallPriceEuro(), option1.PutPriceEuro());

			cout << "(" << T_array[i] << ", " << sig_array[j] << ", " << PriceMatrix[i][j] << ")" << endl;
		}
	}
	cout << endl;

	// reset the option
	option1.SetOption(T1, K1, sig1, r1, b1, S1);
	//==============================================================================================================================================================================
		// Group A =Option Sensitivities, aka the Greeks ==================================================
		// 2 a) We implement formula for gamma for call and put future option pricing. We also compute
		// Delta for call and Delta for put.
	EuropeanOption greek_option;
	Time T_greek = (Time) 0.5;
	Strike_Price K_greek = (Strike_Price)100;
	Volatility sig_greek = (Volatility) 0.36;
	rate r_greek = (rate) 0.1;
	cost_of_carry b_greek = (cost_of_carry)0;
	curr_stock_price S_greek = (curr_stock_price)105;

	greek_option.SetOption(T_greek, K_greek, sig_greek, r_greek, b_greek, S_greek);

	cout << "Call Gamma: " << greek_option.CallPutGammaEuro() << endl;
	cout << "Call Delta: " << greek_option.CallDeltaEuro() << endl;
	cout << "Put Delta: " << greek_option.PutDeltaEuro() << endl;
	//================================================================================================================================================================================
		// 2 b) In the same spirit as the first part, we use our previous code to compute the call delta
		// price for a monotonically increasing range of underlying values of S. We take S to range from
		// 10 up to 50. We use S_array from the previous question.

	vector<double> delta_call_array = greek_option.CallDeltaEuro(S_array);

	cout << "S - Value, Call Delta" << endl;
	PrintArray(S_array, delta_call_array);

	cout << endl;

	// reset the option
	greek_option.SetOption(T_greek, K_greek, sig_greek, r_greek, b_greek, S_greek);
	//================================================================================================================================================================================
		// 2 c) We create a new matrix that holds gamma's as we input a matrix of parameters. As before,
		// we use expiry time and volatility.

	cout << "(Time, Volatility, Gamma)" << endl;
	double Gamma_Matrix[num_rows][num_columns];

	for (int i = 0; i < T_array.size(); ++i)
	{
		greek_option.SetOption(T_array[i]);			// Set the ith row by using the expiry time. Setting the row means we set the option parameter.

		for (int j = 0; j < sig_array.size(); ++j)
		{
			greek_option.SetOption(sig_array[j]);	// Set the column by using the volatility. Here, we set the option parameter with column value.
			Gamma_Matrix[i][j] = greek_option.CallPutGammaEuro();

			cout << "(" << T_array[i] << ", " << sig_array[j] << ", " << Gamma_Matrix[i][j] << ")" << endl;
		}
	}
	cout << endl;
	// reset the option
	greek_option.SetOption(T_greek, K_greek, sig_greek, r_greek, b_greek, S_greek);
	//================================================================================================================================================================================
		// 2 d) We repeat parts a) and b) but now we use the formulas for the appoximations.

	curr_stock_price h = (curr_stock_price) 0.05;

	cout << "Gamma and Delta from the exact formula: " << endl;
	cout << "Gamma: " << greek_option.CallPutGammaEuro() << endl;
	cout << "Delta for call: " << greek_option.CallDeltaEuro() << endl;
	cout << "Delta for put: " << greek_option.PutDeltaEuro() << endl;

	cout << endl;

	cout << "Gamma and Delta from divided difference approximation: " << endl;
	cout << "Gamma: " << greek_option.CallPutGammaEuro(h) << endl;
	cout << "Delta for call: " << greek_option.CallDeltaEuro(h) << endl;
	cout << "Delta for put: " << greek_option.PutDeltaEuro(h) << endl;

	return 0;
}


#include <iostream>
#include <Eigen/Dense>
#include "gaussQuad.hpp"

using namespace Eigen;

const double PI = 3.141592653589793;

// small helper function to evaluate f_alpha_(x)
double f(VectorXd alpha, double x) {
	return std::exp(alpha(0) + alpha(1) * x + alpha(2) * x * x);
}

// rho(x) = (1, x, x^2)^T
VectorXd rho(double x) {
	VectorXd r(3);
	r << 1, x, x * x;
	return r;
}

// helper function to compute the jacobian of F
MatrixXd m_rho(double x) {
	MatrixXd m(3, 3);
	double x2 = x * x;
	double x3 = x * x * x;
	double x4 = x * x * x * x;

	m << 1,  x,  x2,
	     x,  x2, x3,
	     x2, x3, x4;

	return m;
}

// maps quadrature weights and nodes to arbitrary intervals [a, b]
struct QuadRule map_to_interval(const QuadRule& qr, const int a, const int b) {
	struct QuadRule m_qr;
	m_qr.nodes = VectorXd::Zero(qr.nodes.size());
	m_qr.weights = VectorXd::Zero(qr.weights.size());

	// map nodes from [-1, 1] to [a, b]
	for(int i = 0; i < qr.nodes.size(); i++) {
		m_qr.nodes(i) = (0.5 * (1 - qr.nodes(i)) * a) + (0.5 * (1 + qr.nodes(i)) * b);
	}

	// scale the weights with |[a, b]| / |[-1, 1]|
	for(int i = 0; i < qr.weights.size(); i++) {
		m_qr.weights(i) = 0.5 * (b - a) * qr.weights(i);
	}

	return m_qr;
}

// routine: evalF
// " Computes F(\alpha) "
// (in)  qr: quad nodes and weights
// (in)  \alpha: model parameters
// (in)  u: vector of moments
// (out) F(\alpha)
VectorXd evalF(const QuadRule& qr, const VectorXd& alpha, const VectorXd& u) {

	int m = alpha.size();
	VectorXd F = VectorXd::Zero(m);

	const QuadRule m_qr = map_to_interval(qr, -PI / 2, PI / 2);

	// calculate the integral with the quadrature
	for(int i = 0; i < m_qr.nodes.size(); i++) {
		double s = m_qr.nodes(i);
		double x = std::tan(s);
		F += (m_qr.weights(i) * f(alpha, x) * (1 + x * x)) * rho(x);
	}

	F -= u;

	return F;
}

// routine: evalJ
// " Computes the Jacobian of $F(\alpha)$ "
// (in)  qr: quad nodes and weights
// (in)  alpha: model parameters
// (out) jacobian: Jacobian
MatrixXd evalJ(const QuadRule& qr, const VectorXd& alpha, const VectorXd& u) {

	int m = alpha.size();
	MatrixXd jacobian = MatrixXd::Zero(m, m);

	const QuadRule m_qr = map_to_interval(qr, -PI / 2, PI / 2);

	for(int i = 0; i < m_qr.nodes.size(); i++) {
		double s = m_qr.nodes(i);
		double x = std::tan(s);
		jacobian += (m_qr.weights(i) * f(alpha, x) * (1 + x * x)) * m_rho(x);
	}

	return jacobian;
}

// routine: newtonMethod
// " Solves the non-linear system using Newton method "
// (in)  qr: quad nodes and weights
// (in)  u: vector of moments
// (in)  atol: absolute tolerance
// (in)  rtol: relative tolerance
// (in)  maxItr: maximum iterations
// (in/out) alpha\_: model parameters
void newtonMethod(const QuadRule& qr, const VectorXd& u, const double atol, const double rtol, const int maxItr, VectorXd& alpha_) {

	for(int i = 0; i < maxItr; i++) {
		MatrixXd J = evalJ(qr, alpha_, u);
		VectorXd F = evalF(qr, alpha_, u);

		VectorXd correction_term = J.fullPivLu().solve(F);

		// what kind of stopping criterion is this ?
		// souldn't it just be: correction_term.norm() <= rtol * alpha_ like in the lecture notes p.249 ?
		if(correction_term.norm() <= atol || F.norm() <= rtol * u.norm()) {
			return;
		}

		alpha_ -= correction_term;
	}
}

// -- DO NOT CHANGE THIS ROUTINE --
// routine: testEvalF
// " test evalF computation "
// (in) alpha: model parameters
// (in) u: vector of moments
// (in) nQuad: number of quad nodes and weights
void testEvalF(const VectorXd& alpha, const VectorXd& u, const int nQuad) {

	QuadRule qr;
	gaussQuad(nQuad, qr);

	VectorXd F = evalF(qr, alpha, u);
	std::cout << "Norm of F: " << F.norm() << ", should be small" << std::endl;
}

// routine: main
int main() {

	int nQ = 40; // number of Gauss points

	// -- DO NOT CHANGE THIS TEST SNIPPET --
	// test evalF
	// optimal model parameters corresponding to a moment vector are given
	VectorXd u_test(3), alpha_test(3);
	u_test << 1, 0, 1;
	alpha_test << -0.9189385332, 0, -0.5;
	testEvalF (alpha_test, u_test, nQ);

	// subproblem (h)
	VectorXd u(3);
	u << 1, -1, 2;

	VectorXd alpha(3);
	alpha << 0, 0, -0.2;

	double atol = 1e-8;
	double rtol = 1e-6;
	int maxItr = 100;

	QuadRule qr;
	gaussQuad(nQ, qr);
	newtonMethod(qr, u, atol, rtol, maxItr, alpha);

	std::cout << alpha.transpose() << std::endl;
}

// END OF FILE


#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <iostream>
#include <vector>

using namespace Eigen;
using namespace std;

//! \brief Compute the matrix C from A.
//! \param[in] A Matrix $n \times n$
//! \param[out] C MatrixXd with $C=A\otimes I+I\otimes A$.

SparseMatrix<double> buildC(const MatrixXd &A)
{
    int n=A.rows();

    Eigen::SparseMatrix<double> C(n*n,n*n);
    std::vector<Triplet<double> > triplets;
    MatrixXd I=MatrixXd::Identity(n,n);

    for (int i=0; i<n; i++) {
      for (int j=0; j<n; j++) {
        if (i==j){
          for (int k1=0; k1<n; k1++) {
            for (int k2=0; k2<n; k2++) {
              Triplet<double>
              triplet(i*n+k1,j*n+k2,A(i,j)*I(k1,k2)+A(k1,k2));
              triplets.push_back(triplet);
             }
          }
        }
        else {
          for (int k=0; k<n ; k++) {
            Triplet<double> triplet(i*n+k,j*n+k,A(i,j));
            triplets.push_back(triplet);
          }
        }
      }
    }
    C.setFromTriplets(triplets.begin(), triplets.end());
    C.makeCompressed();
    return C;
}

//! \brief Solve the Lyapunov system
//! \param[in] A Matrix $n \times n$
//! \param[out] X MatrixXd, the solution.

void solveLyapunov(const MatrixXd &A, MatrixXd &X)
{
    int n=A.rows();
    SparseMatrix <double> C;
    C=buildC(A);
    MatrixXd I=MatrixXd::Identity(n,n);
    VectorXd b(n*n);
    b=Map<MatrixXd>(I.data(),n*n,1);
    VectorXd vecX(n*n);
    SparseLU<SparseMatrix <double> > solver;
    solver.compute(C) ;
    vecX = solver.solve(b);
    X=Map<MatrixXd>(vecX.data(),n,n);
}

int main(){

    // test buildC
    int n=5;
    MatrixXd A(n,n);
    A<<10, 2, 3, 4, 5, 6, 20, 8, 9, 1, 1, 2, 30, 4, 5, 6, 7, 8, 20, 0, 1, 2, 3, 4, 10;

    SparseMatrix <double> C;
    C=buildC(A);
    cout<<"C= "<<C<<endl;

    // solve lynear system
    MatrixXd X(n,n);
    solveLyapunov(A,X);
    cout<<"X= "<<X<<endl;
    MatrixXd I=MatrixXd::Identity(n,n);

    // test to verify the solution
    cout<<(A*X+X*A.transpose()-I).norm()<<endl;
}

Nummerical Methods for CSE/solutions/solution_2/solveLyapunov.cpp


#include <stdio.h>
#include <math.h>
#include <Eigen/Core>

float deg2rad(float orientation){

   return orientation*M_PI /180.0;
}

Eigen::Matrix3f Rx(float angle)
{

  Eigen::Matrix3f R;
  R.setIdentity();
  R <<   1 ,     0  ,          0,
         0 , cos(angle) ,  -sin(angle) ,
         0 , sin(angle) ,  cos(angle)   ;
return R;

}

Eigen::Matrix3f Ry(float angle)
{
  Eigen::Matrix3f R;
  R.setIdentity();

  R << cos(angle) ,   0   ,   sin(angle),
        0             , 1     ,  0 ,
        -sin(angle)  , 0 ,  cos(angle)   ;

return R;

}

Eigen::Matrix3f Rz(float angle)
{

  Eigen::Matrix3f R;
  R.setIdentity();

  R << cos(angle) ,   -sin(angle)   ,  0,
       sin(angle)     , cos(angle)    ,  0 ,
       0              , 0 ,          1   ;

return R;
}

void fromRotationToRPYAngle(float& roll,float&  pitch, float& yaw,const Eigen::Matrix3f R)
{

  //yaw   = atan2(R(1,0), R(0,0)  );
  //pitch = atan2( -R(2,0)  , sqrt( pow((R(2,1)),2) + pow(R(2,2),2)) );
  //roll  = atan2( R(2,1) , R(2,2) );

  yaw=atan2(R(1,0),R(0,0));
  pitch=atan2( -R(2,0)   ,   sqrt(  pow(R(2,1),2)+ pow(R(2,2),2)    )  );
  roll=atan2(R(2,1),R(2,2));

}


/*
This example demonstrates the basic operations of Eigen matrix.
*/
#include <iostream>

using namespace std;

#include <ctime>

// Eigen core
#include <Eigen/Core>
// Eigen dense matrix (inverse, eigenvalues, etc.)
#include <Eigen/Dense>
using namespace Eigen;

#define MATRIX_SIZE 50

int main(int argc, char **argv) {
    // All vectors and matrices in Eigen are Eigen::Matrix, which is a template
    // class. Its first three parameters are: data type, row, column Declare a 2*3
    // float matrix
    Matrix<float, 2, 3> matrix_23;

    // At the same time, Eigen provides many built-in types via typedef, but the
    // bottom layer is still Eigen::Matrix. For example, Vector3d is essentially
    // Eigen::Matrix<double, 3, 1>, which is a three-dimensional vector.
    Vector3d v_3d;
    // This is the same
    Matrix<float, 3, 1> vd_3d;

    // Matrix3d is essentially Eigen::Matrix<double, 3, 3>
    Matrix3d matrix_33 = Matrix3d::Zero(); // initialized to zero
    // If you are not sure about the size of the matrix, you can use a matrix of
    // dynamic size
    Matrix<double, Dynamic, Dynamic> matrix_dynamic;
    // simpler
    MatrixXd matrix_x;
    // There are still many types of this kind. We don't list them one by one.

    // Here is the operation of the Eigen matrix
    // input data (initialization)
    matrix_23 << 1, 2, 3, 4, 5, 6;
    // output
    cout << "matrix 2x3 from 1 to 6: \n" << matrix_23 << endl;

    // Use () to access elements in the matrix
    cout << "print matrix 2x3: " << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++)
        cout << matrix_23(i, j) << "\t";
        cout << endl;
    }

    // We can easily multiply a matrix with a vector (but actually still matrices and matrices)
    v_3d << 3, 2, 1;
    vd_3d << 4, 5, 6;

    // In Eigen you can't mix two different types of matrices, like this is
    // wrong Matrix<double, 2, 1> result_wrong_type = matrix_23 * v_3d;
    // It should be explicitly converted
    Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;
    cout << "[1,2,3;4,5,6]*[3,2,1]=" << result.transpose() << endl;

    Matrix<float, 2, 1> result2 = matrix_23 * vd_3d;
    cout << "[1,2,3;4,5,6]*[4,5,6]: " << result2.transpose() << endl;

    // Also you can't misjudge the dimensions of the matrix
    // Try canceling the comments below to see what Eigen will report.
    // Eigen::Matrix<double, 2, 3> result_wrong_dimension =
    // matrix_23.cast<double>() * v_3d;

    // some matrix operations
    // The basic operations are not demonstrated, just use +-*/ operators.
    matrix_33 = Matrix3d::Random(); // Random Number Matrix
    cout << "random matrix: \n" << matrix_33 << endl;
    cout << "transpose: \n" << matrix_33.transpose() << endl;
    cout << "sum: " << matrix_33.sum() << endl;
    cout << "trace: " << matrix_33.trace() << endl;
    cout << "times 10: \n" << 10 * matrix_33 << endl;
    cout << "inverse: \n" << matrix_33.inverse() << endl;
    cout << "det: " << matrix_33.determinant() << endl;

    // Eigenvalues
    // Real symmetric matrix can guarantee successful diagonalization
    SelfAdjointEigenSolver<Matrix3d> eigen_solver(matrix_33.transpose() *
	    matrix_33);
    cout << "Eigen values = \n" << eigen_solver.eigenvalues() << endl;
    cout << "Eigen vectors = \n" << eigen_solver.eigenvectors() << endl;

    // Solving equations
    // We solve the equation of matrix_NN * x = v_Nd
    // The size of N is defined in the previous macro, which is generated by a
    // random number Direct inversion is the most direct, but the amount of
    // inverse operations is large.

    Matrix<double, MATRIX_SIZE, MATRIX_SIZE> matrix_NN =
	    MatrixXd::Random(MATRIX_SIZE, MATRIX_SIZE);
    matrix_NN =
	    matrix_NN * matrix_NN.transpose(); // Guarantee semi-positive definite
    Matrix<double, MATRIX_SIZE, 1> v_Nd = MatrixXd::Random(MATRIX_SIZE, 1);

    clock_t time_stt = clock(); // timing
    // Direct inversion
    Matrix<double, MATRIX_SIZE, 1> x = matrix_NN.inverse() * v_Nd;
    cout << "time of normal inverse is "
	    << 1000 * (clock() - time_stt) / (double)CLOCKS_PER_SEC << "ms" << endl;
    cout << "x = " << x.transpose() << endl;

    // Usually solved by matrix decomposition, such as QR decomposition, the speed
    // will be much faster
    time_stt = clock();
    x = matrix_NN.colPivHouseholderQr().solve(v_Nd);
    cout << "time of Qr decomposition is "
	    << 1000 * (clock() - time_stt) / (double)CLOCKS_PER_SEC << "ms" << endl;
    cout << "x = " << x.transpose() << endl;

    // For positive definite matrices, you can also use cholesky decomposition to
    // solve equations.
    time_stt = clock();
    x = matrix_NN.ldlt().solve(v_Nd);
    cout << "time of ldlt decomposition is "
	    << 1000 * (clock() - time_stt) / (double)CLOCKS_PER_SEC << "ms" << endl;
    cout << "x = " << x.transpose() << endl;

    return 0;
}


#include "ode45.hpp"

#include <iostream>
#include <iomanip>

#include <Eigen/Dense>
#include <Eigen/QR>

//! \file stabrk.cpp Solution for Problem 1, PS13, involving ode45 and matrix ODEs

//! \brief Solve matrix IVP Y' = -(Y-Y')*Y using ode45 up to time T
//! \param[in] Y0 Initial data Y(0) (as matrix)
//! \param[in] T final time of simulation
//! \return Matrix of solution of IVP at t = T
Eigen::MatrixXd matode(const Eigen::MatrixXd & Y0, double T) {

    auto F = [] (const Eigen::MatrixXd & M) { return -(M  - M.transpose())*M; };
    ode45<Eigen::MatrixXd> O(F);

    // Set tolerances
    O.options.atol = 10e-10;
    O.options.rtol = 10e-8;

    // Return only matrix at T, (solution is vector of pairs (y(t_k), t_k) for each step k
    return O.solve(Y0, T).back().first;
}

//! \brief Find if invariant is preserved after evolution with matode
//! \param[in] Y0 Initial data Y(0) (as matrix)
//! \param[in] T final time of simulation
//! \return true if invariant was preserved (up to round-off), i.e. if norm was less than 10*eps
bool checkinvariant(const Eigen::MatrixXd & M, double T) {
    Eigen::MatrixXd N(3,3);

    N = matode(M, T);

    if( (N.transpose()*N-M.transpose()*M).norm() < 10 * std::numeric_limits<double>::epsilon() ) {
        return true;
    } else {
        return false;
    }
}

//! \brief Implement ONE step of explicit Euler applied to Y0, of ODE Y' = A*Y
//! \param[in] A matrix A of the ODE
//! \param[in] Y0 Initial state
//! \param[in] h step size
//! \return next step
Eigen::MatrixXd expeulstep(const Eigen::MatrixXd & A, const Eigen::MatrixXd & Y0, double h) {
    return Y0 + h*A*Y0;
}

//! \brief Implement ONE step of implicit Euler applied to Y0, of ODE Y' = A*Y
//! \param[in] A matrix A of the ODE
//! \param[in] Y0 Initial state
//! \param[in] h step size
//! \return next step
Eigen::MatrixXd impeulstep(const Eigen::MatrixXd & A, const Eigen::MatrixXd & Y0, double h) {
    return (Eigen::MatrixXd::Identity(3,3) - h*A).partialPivLu().solve(Y0);
}

//! \brief Implement ONE step of implicit midpoint ruler applied to Y0, of ODE Y' = A*Y
//! \param[in] A matrix A of the ODE
//! \param[in] Y0 Initial state
//! \param[in] h step size
//! \return next step
Eigen::MatrixXd impstep(const Eigen::MatrixXd & A, const Eigen::MatrixXd & Y0, double h) {
    return (Eigen::MatrixXd::Identity(3,3) - h*0.5*A).partialPivLu().solve(Y0+h*0.5*A*Y0);
}

int main() {

    double T = 1;
    unsigned int n = 3;

    Eigen::MatrixXd M(n,n);
    M << 8,1,6,3,5,7,4,9,2;

    std::cout << "SUBTASK 1. c)" << std::endl;
    // Test preservation of orthogonality

    // Build Q
    Eigen::HouseholderQR<Eigen::MatrixXd> qr(M.rows(), M.cols());
    qr.compute(M);
    Eigen::MatrixXd Q = qr.householderQ();

    // Build A
    Eigen::MatrixXd A(n,n);
    A << 0, 1, 1, -1, 0, 1, -1, -1, 0;
    Eigen::MatrixXd I = Eigen::MatrixXd::Identity(n,n);

    // Norm of Y'Y-I for 20 steps
    Eigen::MatrixXd Mexpeul = Q, Mimpeul = Q, Mimp = Q;
    double h = 0.01;
    std::vector<int> sep = {8,15,15,15};
    std::cout << "Evolution of norm(Y_k'*Y_k - I) for three methods:" << std::endl;
    std::cout   << std::setw(sep[0]) << "step"
                << std::setw(sep[1]) << "exp. Eul"
                << std::setw(sep[2]) << "imp. Eul"
                << std::setw(sep[3]) << "IMP"
                << std::endl;
    std::cout   << std::setw(sep[0]) << "-1"
                << std::setw(sep[1]) << (Mexpeul.transpose()*Mexpeul - I).norm()
                << std::setw(sep[2]) << (Mimpeul.transpose()*Mimpeul - I).norm()
                << std::setw(sep[3]) << (Mimp.transpose()*Mimp - I).norm()
                << std::endl;
    for(unsigned int j = 0; j < 20; ++j) {
        Mexpeul = expeulstep(A, Mexpeul, h);
        Mimpeul = impeulstep(A, Mimpeul, h);
        Mimp = impstep(A, Mimp, h);

        std::cout   << std::setw(sep[0]) << j
                    << std::setw(sep[1]) << (Mexpeul.transpose()*Mexpeul - I).norm()
                    << std::setw(sep[2]) << (Mimpeul.transpose()*Mimpeul - I).norm()
                    << std::setw(sep[3]) << (Mimp.transpose()*Mimp - I).norm()
                    << std::endl;
    }

    std::cout << "SUBTASK 1. d)" << std::endl;
    // Test implementation of ode45

    std::cout << "M = " << std::endl << M << std::endl;
    Eigen::MatrixXd  N = matode(M, T);
    std::cout << "N = " << std::endl << N << std::endl;

    std::cout << "SUBTASK 1. g)" << std::endl;
    // Test whether invariant was preserved or not

    bool is_invariant = checkinvariant(N, T);

    if( is_invariant ) {
        std::cout << "Invariant was preserved." << std::endl;
    } else {
        std::cout << "Invariant was NOT preserved." << std::endl;
    }

    return 0;
}

Nummerical Methods for CSE/PS13/solutions_ps13/matrix_ode.cpp


/*
 * Copyright John Maddock, 2017
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 * This example Illustrates numerical integration via Gauss and Gauss-Kronrod quadrature.
 */

#include <iostream>
#include <cmath>
#include <limits>
#include <boost/math/quadrature/gauss.hpp>
#include <boost/math/quadrature/gauss_kronrod.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/relative_difference.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>

void gauss_examples()
{
   //[gauss_example

   /*`
   We'll begin by integrating t[super 2] atan(t) over (0,1) using a 7 term Gauss-Legendre rule,
   and begin by defining the function to integrate as a C++ lambda expression:
   */
   using namespace boost::math::quadrature;

   auto f = [](const double& t) { return t * t * std::atan(t); };

   /*`
   Integration is simply a matter of calling the `gauss<double, 7>::integrate` method:
   */

   double Q = gauss<double, 7>::integrate(f, 0, 1);

   /*`
   Which yields a value 0.2106572512 accurate to 1e-10.

   For more accurate evaluations, we'll move to a multiprecision type and use a 20-point integration scheme:
   */

   using boost::multiprecision::cpp_bin_float_quad;

   auto f2 = [](const cpp_bin_float_quad& t) { return t * t * atan(t); };

   cpp_bin_float_quad Q2 = gauss<cpp_bin_float_quad, 20>::integrate(f2, 0, 1);

   /*`
   Which yields 0.2106572512258069881080923020669, which is accurate to 5e-28.
   */

   //]

   std::cout << std::setprecision(18) << Q << std::endl;
   std::cout << boost::math::relative_difference(Q, (boost::math::constants::pi<double>() - 2 + 2 * boost::math::constants::ln_two<double>()) / 12) << std::endl;

   std::cout << std::setprecision(34) << Q2 << std::endl;
   std::cout << boost::math::relative_difference(Q2, (boost::math::constants::pi<cpp_bin_float_quad>() - 2 + 2 * boost::math::constants::ln_two<cpp_bin_float_quad>()) / 12) << std::endl;
}

void gauss_kronrod_examples()
{
   //[gauss_kronrod_example

   /*`
   We'll begin by integrating exp(-t[super 2]/2) over (0,+[infin]) using a 7 term Gauss rule
   and 15 term Kronrod rule,
   and begin by defining the function to integrate as a C++ lambda expression:
   */
   using namespace boost::math::quadrature;

   auto f1 = [](double t) { return std::exp(-t*t / 2); };

   //<-
   double Q_expected = sqrt(boost::math::constants::half_pi<double>());
   //->

   /*`
   W'll start off with a one shot (ie non-adaptive)
   integration, and keep track of the estimated error:
   */
   double error;
   double Q = gauss_kronrod<double, 15>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 0, 0, &error);

   /*`
   This yields Q = 1.25348207361, which has an absolute error of 1e-4 compared to the estimated error
   of 5e-3: this is fairly typical, with the difference between Gauss and Gauss-Kronrod schemes being
   much higher than the actual error.  Before moving on to adaptive quadrature, lets try again
   with more points, in fact with the largest Gauss-Kronrod scheme we have cached (30/61):
   */
   //<-
   std::cout << std::setprecision(16) << Q << std::endl;
   std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl;
   std::cout << fabs(Q - Q_expected) << std::endl;
   std::cout << error << std::endl;
   //->
   Q = gauss_kronrod<double, 61>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 0, 0, &error);
   //<-
   std::cout << std::setprecision(16) << Q << std::endl;
   std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl;
   std::cout << fabs(Q - Q_expected) << std::endl;
   std::cout << error << std::endl;
   //->
   /*`
   This yields an absolute error of 3e-15 against an estimate of 1e-8, which is about as good as we're going to get
   at double precision

   However, instead of continuing with ever more points, lets switch to adaptive integration, and set the desired relative
   error to 1e-14 against a maximum depth of 5:
   */
   Q = gauss_kronrod<double, 15>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 5, 1e-14, &error);
   //<-
   std::cout << std::setprecision(16) << Q << std::endl;
   std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl;
   std::cout << fabs(Q - Q_expected) << std::endl;
   std::cout << error << std::endl;
   //->
   /*`
   This yields an actual error of zero, against an estimate of 4e-15.  In fact in this case the requested tolerance was almost
   certainly set too low: as we've seen above, for smooth functions, the precision achieved is often double
   that of the estimate, so if we integrate with a tolerance of 1e-9:
   */
   Q = gauss_kronrod<double, 15>::integrate(f1, 0, std::numeric_limits<double>::infinity(), 5, 1e-9, &error);
   //<-
   std::cout << std::setprecision(16) << Q << std::endl;
   std::cout << boost::math::relative_difference(Q, Q_expected) << std::endl;
   std::cout << fabs(Q - Q_expected) << std::endl;
   std::cout << error << std::endl;
   //->
   /*`
   We still achieve 1e-15 precision, with an error estimate of 1e-10.
   */
   //]
}

int main()
{
   gauss_examples();
   gauss_kronrod_examples();
   return 0;
}


//  This function computes the autocorrelation function for
//  the Mersenne random number generator with a uniform distribution
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <random>
#include <armadillo>
#include <string>
#include <cmath>
using namespace  std;
using namespace arma;
// output file
ofstream ofile;

//     Main function begins here
int main(int argc, char* argv[])
{
  int MonteCarloCycles;
  string filename;
  if (argc > 1) {
    filename=argv[1];
    MonteCarloCycles = atoi(argv[2]);
    string fileout = filename;
    string argument = to_string(MonteCarloCycles);
    fileout.append(argument);
    ofile.open(fileout);
  }

  // Compute the variance and the mean value of the uniform distribution
  // Compute also the specific values x for each cycle in order to be able to
  // compute the covariance and the correlation function

  vec X  = zeros<vec>(MonteCarloCycles);
  double MCint = 0.;      double MCintsqr2=0.;
  std::random_device rd;
  std::mt19937_64 gen(rd());
  // Set up the uniform distribution for x \in [[0, 1]
  std::uniform_real_distribution<double> RandomNumberGenerator(0.0,1.0);
  for (int i = 0;  i < MonteCarloCycles; i++){
    double x =   RandomNumberGenerator(gen);
    X(i) = x;
    MCint += x;
    MCintsqr2 += x*x;
  }
  double Mean = MCint/((double) MonteCarloCycles );
  MCintsqr2 = MCintsqr2/((double) MonteCarloCycles );
  double STDev = sqrt(MCintsqr2-Mean*Mean);
  double Variance = MCintsqr2-Mean*Mean;
  //   Write mean value and variance
  cout << " Sample variance= " << Variance  << " Mean value = " << Mean << endl;
  // Now we compute the autocorrelation function
  vec autocorrelation = zeros<vec>(MonteCarloCycles);
  for (int j = 0; j < MonteCarloCycles; j++){
    double sum = 0.0;
    for (int k = 0; k < (MonteCarloCycles-j); k++){
      sum  += (X(k)-Mean)*(X(k+j)-Mean);
    }
    autocorrelation(j) = sum/Variance/((double) MonteCarloCycles );
    ofile << setiosflags(ios::showpoint | ios::uppercase);
    ofile << setw(15) << setprecision(8) << j;
    ofile << setw(15) << setprecision(8) << autocorrelation(j) << endl;
  }
  // Now compute the exact covariance using the autocorrelation function
  double Covariance = 0.0;
  for (int j = 0; j < MonteCarloCycles; j++){
    Covariance  += autocorrelation(j);
  }
  Covariance *=  2.0/((double) MonteCarloCycles);
  // Compute now the total variance, including the covariance, and obtain the standard deviation
  double TotalVariance = (Variance/((double) MonteCarloCycles ))+Covariance;
  cout << " Covariance = " << Covariance << " Totalvariance= " << TotalVariance << " Sample Variance/n= " << (Variance/((double) MonteCarloCycles )) << endl;
  cout << " STD from sample variance= " << sqrt(Variance/((double) MonteCarloCycles )) << " STD with covariance = " << sqrt(TotalVariance) << endl;
  ofile.close();  // close output file
  return 0;
}  // end of main program


//
//  main.cpp
//  Assignment 4 - Even More Triangles!
//
//  Created by - on 2016/10/19.
//  Copyright © 2016 Eddie of The Ren. All rights reserved.
//

#include <iostream>
//#include "stdafx.h"
using namespace std;
#include <stdio.h>      /* printf */
#include <math.h>
//#include <boost/lexical_cast.hpp>
#include <string>
#include <cstdlib>

int getNum() {
    //User inputs a number and returns its value
    double inputNum = 0;
    cin >> inputNum;
    return inputNum;
}

bool thisIsTheEnd(double a, double b, double c) {
    //Checks if all three numbers are 0 and displays an approximate end message if true
    if (a == b && b == c && c == 0) {
        cout<< a << " " << b << " " << c <<" Program was terminated by user" << endl;
        cout << ""<< endl;

        exit(0);
        return true;
    } else {
        return false;
    }
}

bool checkValid (double x, double y, double z) {

    if ((x > y + z)||(y>x+z) || (z > x + y)){
        //Checks if one side of the triangle is greater than the other two combined
        cout<< x << " " << y << " " << z <<" Triangle cannot be formed" << endl;
        return false;
    } else if ((x <=0)|| (y <=0) || (z<=0) ) {
        //Checks if one side of the triangle is 0 or negative
        cout<< x << " " << y << " " << z <<" Triangle cannot be formed - Invalid Length entry" << endl;
        return false;
    }

    else {
        return true;
    }

}

string sideClass(double x, double y, double z) {
    //Classifies the triangles by their side lengths
    if ((x == y) && (y==z)) {
        return "Equilateral";
    } else if ((x != y) && (y != z) && (z != x)) {
        return "Scalene";
    } else {
        return "Isoceles";
    }

}

string angleClass(double x, double y, double z) {
    //Classifies triangles by their largest angles.
    double largest = 3122;
    double meh = 12342;
    double meh2 = 12342;

    //Finds the largest side of the triangle
    if ((x>y) && (x>z)) {
        largest = x;
        meh = y;
        meh2 = z;
    } else if ((y>x) && (y>z)) {
        largest = y;
        meh = x;
        meh2 = z;
    } else if ((z>x) && (z > y)) {
        largest = z;
        meh = x;
        meh2 = y;
    }

    //Uses the pythogorean theory to determine if the triangle is right, acute or obtuse
    if ((largest*largest) == (meh*meh) + (meh2*meh2)) {
        return "Right";
    } else if ((largest*largest) > (meh*meh) + (meh2*meh2)) {
        return "Obtuse";
    } else if ((largest*largest) < (meh*meh) + (meh2*meh2)) {
        return "Acute";
    } else {
        //Eddie is not always perfect
        return "Crap I screwed up";
    }
}

int main(int argc, const char * argv[]) {

    bool validity = false;
    double firstNum = 0;
    double secondNum = 0;
    double thirdNum = 0;
    string sClass = "Derp";
    string aClass = "Derpity Derp";

    do {
        //Continues asking for input as long as the input values are invalid. when 0 0 0 is entered the program ends
        cout << "Provide three side lengths, x, y and z. - 0 0 0 to terminate." << endl;

        firstNum = getNum();
        secondNum = getNum();
        thirdNum = getNum();

        thisIsTheEnd(firstNum, secondNum, thirdNum);
        validity = checkValid(firstNum, secondNum, thirdNum);

    } while (validity == false);
    //sClass and aClass are the angle and side lengths
    sClass = sideClass(firstNum, secondNum, thirdNum);
    aClass = angleClass(firstNum, secondNum, thirdNum);

    //Outputs the results of the calculations for side and angle classificaitons
    if (checkValid(firstNum, secondNum, thirdNum) == true) {
        cout<< "Length x: "<< firstNum << " Length Y: " << secondNum << " Length Z: " << thirdNum << " Triangle Possible " << sClass << " " << aClass << endl;
    }

    //Finds perimeter and outputs it
    double perimeter = firstNum + secondNum + thirdNum;
    cout << "The perimeter of the triangle is " << perimeter<< endl;

    //Finds semi-perimeter and outputs it
    double semiPerimeter = 0;
    semiPerimeter = perimeter/2;
    //cout << "Calculation No.2 - Semi-Perimeter" << endl;
    cout << "The semi-perimeter of the triangle is " << semiPerimeter<< endl;

    //Finds the total area and outputs it
    double totalArea = 0;
    double s = semiPerimeter;
    totalArea = sqrt((s*(s-firstNum)*(s-secondNum)*(s-thirdNum)));
    //cout << "Calculation No.3 - Area " << endl;
    cout << "The area of the triangle is " << totalArea << endl;

    //Finds the radius of the circumsized circle and outputs it
    double radiusCircumsized = 0;
    double a = totalArea;
    radiusCircumsized = ((firstNum * secondNum * thirdNum)/(4*a));
    //cout << "Calculation No.4 - Radius of Circumsized Circle " << endl;
    cout << "The radius of the circumsized circle is " << radiusCircumsized << endl;

    //FInds the radius of the inscribed circle and outputs it
    double radiusInscribed = 0;
    radiusInscribed = ((2*a)/(perimeter));
    // cout << "Calculation No.5 - Radius of Inscribed Circle " << endl;
    cout << "The radius of the inscribed circle is " << radiusInscribed << endl;

    double num1 = firstNum;
    double num2 = secondNum;
    double num3 = thirdNum;
    double angleX = 0;
    double angleY = 0;
    double angleZ = 0;
    double x1 = firstNum;
    double y1 = secondNum;
    double z1 = thirdNum;

    cout << ""<<  endl;
    double theta = 0;

    //Uses the cosine formula to find the angle of each side length
    theta = ((((y1)*(y1))+((z1)*(z1))-((x1)*(x1)))/(2*z1*y1));
    angleX = acos(theta) * 180/3.141592653589793238463;

    theta = ((((x1)*(x1))+((z1)*(z1))-((y1)*(y1)))/(2*z1*x1));
    angleY = acos(theta) * 180/3.141592653589793238463;

    theta = ((((y1)*(y1))+((x1)*(x1))-((z1)*(z1)))/(2*x1*y1));
    angleZ = acos(theta) * 180/3.141592653589793238463;

    //Outputs the angle calculations.
    cout << "Calculation No.6 - Finding The Angles " << endl;
    cout << "AngleX = " << angleX << endl;
    cout << "AngleY = " << angleY << endl;
    cout << "AngleZ = " << angleZ << endl;

    return 0;
}

Assignment 4 Even More Triangles/Assignment 4/main.cpp


#include <Eigen/Dense>
#include <iostream>

using namespace std;
using namespace Eigen;

void legvals(const VectorXd &x, MatrixXd &Lx, MatrixXd &DLx){
    int n = Lx.cols()-1;
    int N = x.size();
	for (int i=0;i<N;i++){
		Lx(i,0)=1.;
		Lx(i,1)=x(i);
		DLx(i,0)=0;
		DLx(i,1)=1.;
		for (int j=2;j<n+1;j++){
			Lx(i,j)=((2*j-1.)/j)*x(i)*Lx(i,j-1)-((j-1.)/j)*Lx(i,j-2);
			DLx(i,j)=((2*j-1.)/j)*(Lx(i,j)+x(i)*DLx(i,j-1))-((j-1.)/j)*DLx(i,j-2);
		}

	}

}

double Pnx (double x, int n){
	if (n==0){return 1.;}
	else if(n==1){return x;}
	else{
		return (((2*n-1.)/n)*x*Pnx(x,n-1)-((n-1.)/n)*Pnx(x,n-2));
	}
}

// Find the Gauss points using the secant method with regula falsi. The standard secant method may be obtained by commenting out lines 50 and 52.
MatrixXd gaussPts(int n, double rtol=1e-10, double atol=1e-12) {
	MatrixXd Pkn(n,n);
	double f0, fn,x0,x1,s;
	for (int k=1;k<n+1;k++){// k de 1-n
		for (int j=1;j<k+1;j++){ // j de 1 - k

			if (j==1) x0 = -1.;
            else      x0 = Pkn(j-2,k-2);
            if (j==k) x1 = 1.;
            else      x1 = Pkn(j-1,k-2);

			f0 = Pnx(x0,k);
			for (int i=0;i<1e4;i++){
				fn=Pnx(x1,k);
				s=fn*(x1-x0)/(fn-f0);
				if (Pnx(x1 - s,k)*fn<0) { x0 = x1; f0 = fn;} // without this correstion, the zero KI8-6 is not a zero, because the initial guess is to far away for the sought zero ---> not the case of a local convergence (I got 0.273438)
				// x0 = x1; f0 = fn;
                x1=x1-s;
				if (abs(s)<max(atol,rtol*min(abs(x0),abs(x1)))){Pkn(j-1,k-1)=x1;break;}
			}
		}

}
return Pkn;

}
// Test the implementation.
int main(){
    int n = 8;
    MatrixXd zeros = gaussPts(n);
    cout<<"Zeros: "<<endl<< zeros <<endl;

    for (int k=1; k<n+1; k++) {
        VectorXd xi = zeros.block(0, k-1, k, 1);
        MatrixXd Lx(k,n+1), DLx(k,n+1);
        legvals(xi, Lx, DLx);
        cout<<"Values of the "<<k<<"-th polynomial in the calculated zeros: "<<endl;
        cout<<Lx.col(k).transpose() <<endl;
    }
}

Nummerical Methods for CSE/PS10/legendre.cpp


// SPDX-License-Identifier: Apache-2.0
// Copyright 2021 - 2021, the Anboto author and contributors
#include <Core/Core.h>
#include <Eigen/Eigen.h>

using namespace Upp;

#ifdef USE_FFTW
#include <fftw3.h>
#endif

using namespace Eigen;

void FFTTests()
{
	UppLog() << "\nFFT sample\nGets the FFT of equation"
			  "\n f(t) = 2*sin(2*PI*t/50 - PI/3) + 5*sin(2*PI*t/30 - PI/2) + 30*sin(2*PI*t/10 - PI/5)"
			  "\nsampled with a frequency of 14 samples/second";

	int numData = 8000;
	double samplingFrecuency = 14;

    // Filling the data series
    VectorXd timebuf(numData);
    {
	    double t = 0;
	    for (int i = 0; i < numData; ++i, t = i/samplingFrecuency)
	       	timebuf[i] = 2*sin(2*M_PI*t/50 - M_PI/3) + 5*sin(2*M_PI*t/30 - M_PI/2) + 30*sin(2*M_PI*t/10 - M_PI/5);
    }

    // FFT
    VectorXcd freqbuf;
    FFT<double> fft;
    fft.SetFlag(fft.HalfSpectrum);
    fft.fwd(freqbuf, timebuf);

	// Filter the FFT. Frequencies between 1/25 and 1/35 Hz are removed
	// Original FFT is not changed for saving it later
	VectorXcd freqbuf2(freqbuf.size());
	{
	    for (int i = 0; i < freqbuf.size(); ++i) {
	        double freq = i*samplingFrecuency/numData;
	        double T = 1/freq;
	        if (T > 25 && T < 35)
	            freqbuf2[i] = 0;
	        else
	            freqbuf2[i] = freqbuf[i];
	    }
	}

	// Inverse filtered FFT to get filtered series
	VectorXd timebuf2(numData);
	fft.inv(timebuf2, freqbuf2);

	String csvSep = ";";

	// Saving original and filtered FFT
	{
	    String str;
	    str << "Frec" << csvSep << "T" << csvSep << "fft" << csvSep << "Filtered fft";
	    for (int i = 0; i < freqbuf.size(); ++i) {
	        double freq = i*samplingFrecuency/numData;
	        double T = 1/freq;
	        str << "\n" << freq << csvSep << (freq > 0 ? FormatDouble(T) : "") << csvSep
	        			<< 2*std::abs(freqbuf[i])/numData << csvSep
	        			<< 2*std::abs(freqbuf2[i])/numData;
	    }
	    String fftFileName = GetExeDirFile("fft.csv");
	    UppLog() << "\nFFT saved in '" << fftFileName << "'";
	    VERIFY(SaveFile(fftFileName, str));
	}

	// Saving original and filtered series
	{
	    String str;
	    str << "Time" << csvSep << "Data" << csvSep << "Filtered data";
	    double t = 0;
	    for (int i = 0; i < numData; ++i, t = i*1/samplingFrecuency)
	       	str << "\n" << t << csvSep << timebuf[i] << csvSep << timebuf2[i];;
	    String dataFileName = GetExeDirFile("data.csv");
	    UppLog() << "\nSource data saved in '" << dataFileName << "'";
	    VERIFY(SaveFile(dataFileName, str));
    }
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <boost/functional/hash.hpp>

using namespace std;

// https://www.geeksforgeeks.org/count-maximum-points-on-same-line/
// method to find maximum colinear point

int maxPointOnSameLine(vector< pair<int, int> > points)
{
    int N = points.size();
    if (N < 2)
        return N;

    int maxPoint = 0;
    int curMax, overlapPoints, verticalPoints;

    // here since we are using unordered_map which is based on hash function
    // But by default we don't have hash function for pairs so we'll use hash function defined in Boost library
    unordered_map<pair<int, int>, int, boost::hash<pair<int, int>>> slopeMap;

    // looping for each point
    for (int i = 0; i < N; i++)
    {
        curMax = overlapPoints = verticalPoints = 0;

        // looping from i + 1 to ignore same pair again
        for (int j = i + 1; j < N; j++)
        {
            // If both point are equal then just  increase overlapPoint count
            if (points[i] == points[j])
                overlapPoints++;

            // If x co-ordinate is same, then both point are vertical to each other
            else if (points[i].first == points[j].first)
                verticalPoints++;

            else
            {
                int yDif = points[j].second - points[i].second;
                int xDif = points[j].first - points[i].first;
                int g = __gcd(xDif, yDif);

                // reducing the difference by their gcd
                yDif /= g;
                xDif /= g;

                // increasing the frequency of current slope in map
                slopeMap[make_pair(yDif, xDif)]++;
                curMax = max(curMax, slopeMap[make_pair(yDif, xDif)]);
            }
            curMax = max(curMax, verticalPoints);
        }

        // updating global maximum by current point's maximum
        maxPoint = max(maxPoint, curMax + overlapPoints + 1);

        // printf("maximum colinear point which contains current point are : %d\n", curMax + overlapPoints + 1);
        slopeMap.clear();
    }

    return maxPoint;
}

int main()
{
    const int N = 6;
    int arr[N][2] = {{-1, 1}, {0, 0}, {1, 1}, {2, 2}, {3, 3}, {3, 4}};
    vector< pair<int, int> > points;
    for (int i = 0; i < N; i++) {
        points.push_back(make_pair(arr[i][0], arr[i][1]));
    }
    cout << maxPointOnSameLine(points) << endl;
    return 0;
};

/***  Java Implementation
    //https://www.interviewbit.com/problems/points-on-the-straight-line/
    public int maxPoints(ArrayList<Integer> a, ArrayList<Integer> b) {
        if (a.size() == 0) {
            return 0;
        }
        if (a.size() == 1 && b.size() == 1) {
            return 1;
        }
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < a.size(); i++) {
            int x1 = a.get(i);
            int y1 = b.get(i);

            HashMap<Double, Integer> map = new HashMap<Double, Integer>();
            int samePoint = 1; // 1 is taken point itself
            int infValue = 0;

            for (int j = i + 1; j < a.size(); j++) {
                int x2 = a.get(j);
                int y2 = b.get(j);

                if ((x1 == x2) && (y1 == y2)) {
                    samePoint += 1;
                } else if (x2 - x1 == 0) {
                    infValue++;
                } else {
                    double slope = 0.0;
                    if (y1 != y2) {
                        slope = (double) (y2 - y1) / (double) (x2 - x1);
                    }
                    if (map.containsKey(slope)) {
                        map.put(slope, map.get(slope) + 1);
                    } else {
                        map.put(slope, 1);
                    }
                }
            }
            if ((infValue + samePoint) > max) {
                max = infValue + samePoint;
            }
            for (Integer value : map.values()) {
                max = Math.max(value + samePoint, max);
            }
        }
        return max;
    }

*/


#include <iostream>
#include <iomanip>
#include<vector>
#include<string>
#include <cmath>

#include <Eigen/Dense>

void newton3d(Eigen::VectorXd& x,
              double tolerance,
              std::function<Eigen::VectorXd(const Eigen::VectorXd&)> F,
              std::function<Eigen::MatrixXd(const Eigen::VectorXd&)> DF
              )

{
	Eigen::VectorXd x_prev, s;

    std::vector<double> errors;
	errors.push_back((F(x)).norm());
	do	{
        x_prev = x;
		s = DF(x).lu().solve(F(x));
	  	x = x-s; // newton iteration
	} while (s.norm() > tolerance*x.norm());
}

int main()
{
    // F
    auto F = [](const Eigen::VectorXd &x){
   		Eigen::VectorXd res(3);
        res << 0.2*x(0)-0.2*x(1)-3,
        0.4*x(1)-0.2*x(0)-0.3*x(2)+1e-13*(exp(19*x(1)-1)),
        -0.2*x(1)+0.3*x(2);
        return res;
	};
	// jacobian of F
	auto DF= [] (const Eigen::VectorXd &x){
    	Eigen::MatrixXd J(3,3);
		J << 0.2, -0.2, 0,
		  	 -0.2, 0.4 + 19*1e-13*exp(19*x(1)), -0.3,
               0, -0.2, 0.3;
	  	return J;
	};

    Eigen::VectorXd x(3);
	x << 16.0, 2.0, 2.0; // initial value
    double tolerance = 1e-14;
	newton3d(x, tolerance, F, DF);

    std::cout << std::setprecision(17) << "solution = " << x << std::endl;
    std::cout << std::setprecision(17) << "error norm = " << F(x).norm() << std::endl;
}


#include<vector>
#include<iostream>
#include<cmath>
//#include <boost/numeric/ublas/matrix.hpp>
//#include <boost/numeric/ublas/io.hpp>
#include <armadillo>

using namespace std;
using namespace arma;
//using namespace boost::numeric::ublas;

/*
Uzawa's method: Minimize the quadratic functional (Av,v) - (b,v) with the constraints: Cv <= d.
Here A must be symmetric positive definite and has dim = n.
Note A is square since it is symmetric.
There are m constraints and hence C is an mxn matrix.

Lagrange is an mx1 vector of lagrange multipliers
p is a parameter used in the convergence algorithm. It must be within certain bounds
to ensure convergence of the algorithm.
Some of the mat variables below are actually vectors. We leave them as nx1 mats for simplicity.

REFERENCE:
Introduction to Numerical Linear Algebra and Optimization. Philippe G. Ciarlet.
*/

mat UzawasMethod(mat A, mat b, mat C, mat d, double p, int iterations)
{

    int dim = A.n_rows;
    int dualDim = C.n_rows;
    mat Lagrange(dualDim,1);
    mat solution(dim,1);

    for(int i=0;i<iterations;i++)
    {
        for(int j=0;j<dualDim;j++)
        {
            mat temp = C*solution - d;
            Lagrange(j,0) = max(Lagrange(j,0) + p*(temp)(j,0),0.0);
        }
        solution = solve(A,b - C.t()*Lagrange);
    }
    return solution;
}

/*EXAMPLE
Minimize 2x_1^2 + x_2^2 with respect to x_2 >= x_1 + 1

mat a(2,2);
    a(0,0) = 2; a(0,1) = 0;
    a(1,0) = 0; a(1,1) = 1;

mat b(2,1);
    b(0,0) = 0;
    b(1,0) = 0;

mat c(1,2);
    c(0,0) = 1; c(0,1) = -1;

mat d(1,1);
    d(0,0) = -1;

    mat s = UzawasMethod(a,b,c,d,.1,40);
    cout << s;

One can check directly using Lagrange Multiplier techniques that
the solution given by the code for this example is indeed correct.
x_1 = -1/3,  x_2 = 2/3
*/


/* ------------------------------------------------------------
 * @file: jacobi.cpp
 * @dependencias: armadillo, matplotlibcpp
 * @version 0.1
 * ------------------------------------------------------------*/

// [1] $ g++ jacobi.cpp -o jac.out -std=c++11 -I/usr/include/python3.8 -lpython3.8
// [2] $ ./jac.out
// Nota: Asegurarse de tener armadillo bien instalado.

#include <armadillo>
#include "matplotlibcpp.h"

using namespace std;
using namespace arma;
namespace plt = matplotlibcpp;

/**
 * @brief Indica si una matriz es diagonal dominante
 * @param M Matriz de coeficientes, debe ser cuadrada.
 * @return True si la matriz es diagonal dominante, False si no lo es.
 */
bool dominant_diagonal(mat M){
    int n = M.n_rows;
    double d_value, row_sum;

    for (int i = 0; i < n; i++){
        d_value = M(i,i);
        row_sum = 0;
        for (int j = 0; j < n; j++){
            row_sum += abs(M(i,j));
        }

        if (abs(d_value) < row_sum-abs(d_value))
            return false;
    }

    return true;
}

/**
 * @brief Retorna la matriz superior
 */
mat upper_mat(mat A){
    int n = A.n_rows;
    mat U(n,n);
    U.zeros();

    for(int i = 0; i < n; i++){
        for (int j = i; j < n; j++){
            if (i == j){
                continue;
            }
            U(i,j) = A(i,j);
        }
    }

    return U;
}

/**
 * @brief Retorna la matriz diagonal
 */
mat diag_mat(mat A){
    int n = A.n_rows;
    mat D(n,n);
    D.zeros();

    for(int i = 0; i < n; i++){
        D(i,i) = A(i,i);
    }

    return D;
}

/**
 * @brief Retorna la matriz inferior
 */
mat lower_mat(mat A){
    int n = A.n_rows;
    mat L(n,n);
    L.zeros();

    for(int i = 0; i < n; i++){
        for (int j = 0; j < i; j++){
            L(i,j) = A(i,j);
        }
    }

    return L;
}

/**
 * @brief Grafica el error en funcion de la cantidad de iteraciones.
 * @param x Set de valores del eje x.
 * @param y Set de valores del eje y.
 */
void plot(vector<double> x, vector<double> y){

    plt::named_plot("Error |Ax-b|",x,y);
    plt::title("Error Jacobi");
    plt::legend();
    plt::show();
}

/**
 * @brief Calcula la aproximación a la solución de un sistema de ecuaciones por
 *        el método de Jacobi.
 * @param A Matriz de coeficientes.
 * @param b Vector de términos independientes.
 * @param x_o Vector de valor inicial.
 * @param tol Tolerancia de la aproximación.
 * @param max_itr Iteraciones máximas.
 */
void jacobi(mat A, vec b, vec x_o, double tol, int max_itr=100){

    if (!dominant_diagonal(A)){
        cout<<"[Error] La matriz no es diagonal dominante."<<endl;
        return;
    }

    mat L = lower_mat(A);
    mat D = diag_mat(A);
    mat U = upper_mat(A);

    vec x = x_o;
    int k = 0;

    mat T = -D.i()*(L+U);
    vec c = D.i()*b;

    vector<double> errors, itr;
    double error = tol;

    while(error > tol && k < max_itr){
        x = T*x + c;
        error = norm(A*x-b);
        errors.push_back(error);
        itr.push_back(k);
        k++;
    }

    x.print("x: ");
    plot(itr,errors);
}

int main(int argc, char const *argv[])
{
    mat M = {{5,1,1},{1,5,1},{1,1,5}};
    vec b = {7,7,7};
    vec x_o = {0,0,0};
    jacobi(M,b,x_o,5);

    return 0;
}

Catalogo/03. Sistemas de Ecuaciones/C++/jacobi.cpp


#include <iostream>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

void main(int argc, char** argv) {
	{
		cout << "Matrix3f A, Vector3f b" << endl;
		Matrix3f A;
		Vector3f b;

		A << 1, 2, 3, 4, 5, 6, 7, 8, 10;
		b << 3, 3, 4;
		cout << "Matrix3f A: \n" << A << endl;
		cout << "Vector3f b: \n" << b << endl;

		Vector3f x = A.colPivHouseholderQr().solve(b);
		cout << "Solution:\n" << x << endl;
	}
	{
		cout << "Matrix2f A, b" << endl;
		Matrix2f A, b;
		A << 2, -1, -1, 3;
		b << 1, 2, 3, 1;

		cout << "Matrix2f A: \n" << A << endl;
		cout << "Matrix2f b: \n" << b << endl;
		Matrix2f x = A.ldlt().solve(b);
		cout << "Solution: \n" << x << endl;
	}

	{
		cout << "Checking if a solution really exists" << endl;
		MatrixXd A = MatrixXd::Random(100, 100);
		MatrixXd b = MatrixXd::Random(100, 50);

		MatrixXd x = A.fullPivLu().solve(b);
		double relative_error = (A*x - b).norm() / b.norm();
		cout << "Relative error :\n" << relative_error << endl;
	}

	{
		cout << "Computing eigenvalues and eigenvectors" << endl;
		Matrix2f A;
		A << 1, 2, 2, 3;
		cout << "Matrix2f A:\n" << A << endl;

		SelfAdjointEigenSolver<Matrix2f> eigensolver(A);
		if (eigensolver.info() != Success) {
			cout << "EigenSolver failed" << endl;
		}
		else {
			cout << "Eigenvalues of A: \n" << eigensolver.eigenvalues() << endl;
			cout << "Matrix whose columns are eigenvectors of A: \n" << eigensolver.eigenvectors() << endl;
		}
	}
	{
		cout << "Least squares solving" << endl;
		MatrixXf A = MatrixXf::Random(3, 2);
		cout << "MatrixXf A: \n" << A << endl;
		VectorXf b = VectorXf::Random(3);
		cout << "VectorXf b: \n" << b << endl;
		cout << "The least-squares solution is: \n" << A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
	}
	{
		cout << "Separating the computation from the construction" << endl;
		Matrix2f A, b;
		LLT<Matrix2f> llt;
		A << 2, -1, -1, 3;
		b << 1, 2, 3, 1;
		cout << "A:\n" << A << endl;
		cout << "b:\n" << b << endl;
		cout << "Computing LLT decomposition..." << endl;
		llt.compute(A);
		cout << "The solution is: \n" << llt.solve(b) << endl;
		A(1, 1)++;
		cout << "The matrix A is now: \n" << A << endl;
		cout << "Computing LLT decomposition..." << endl;
		llt.compute(A);
		cout << "The solution is: \n" << llt.solve(b) << endl;
	}

	{
		Matrix3f A;
		A << 1, 2, 5,
			2, 1, 4,
			3, 0, 3;
		cout << "Here is the matrix A:\n" << A << endl;
		FullPivLU<Matrix3f> lu_decomp(A);
		cout << "The rank of A is " << lu_decomp.rank() << endl;
		cout << "Here is a matrix whose columns form a basis of the null-space of A:\n"
			<< lu_decomp.kernel() << endl;
		cout << "Here is a matrix whose columns form a basis of the column-space of A:\n"
			<< lu_decomp.image(A) << endl; // yes, have to pass the original A
	}

	{
		cout << "Inplace matrix decompositions" << endl;
		cout << "Useful when dealing with huge matrices and or when the memory is limited" << endl;

		MatrixXd A(2, 2);
		A << 2, -1, 1, 3;
		cout << "A:\n" << A << endl;
		PartialPivLU<Ref<MatrixXd>> lu(A);
		cout << "Matrix A after decomposition: \n" << A << endl;
		cout << "Here is the matrix storing the L and U factors: \n" << lu.matrixLU() << endl;
		cout << "Use lu object to solve the Ax=b problem: " << endl;
		VectorXd b(2); b << 1, 2;
		VectorXd x = lu.solve(b);
		MatrixXd A0(2, 2); A0 << 2, -1, 1, 3; // only for verification of the result.
		cout << "Residual: " << (A0 * x - b).norm() << endl;
	}

	system("pause");
}


#include <Eigen/Dense>
#include <iostream>
#include <vector>

 #include "timer.h"

using namespace Eigen;
using namespace std;

//! \brief Compute the Matrix product $A \times B$ using Strassen's algorithm.
//! \param[in] A Matrix $2^k \times 2^k$
//! \param[in] B Matrix $2^k \times 2^k$
//! \param[out] Matrix product of A and B of dim $2^k \times 2^k$

MatrixXd strassenMatMult(const MatrixXd & A, const MatrixXd & B)
{
    int n=A.rows();
    MatrixXd C(n,n);

    if (n==2)
    {
        C<< A(0,0)*B(0,0) + A(0,1)*B(1,0),
            A(0,0)*B(0,1) + A(0,1)*B(1,1),
            A(1,0)*B(0,0) + A(1,1)*B(1,0),
            A(1,0)*B(0,1) + A(1,1)*B(1,1);
        return C;
    }

    else
    {   MatrixXd Q0(n/2,n/2),Q1(n/2,n/2),Q2(n/2,n/2),Q3(n/2,n/2),
        Q4(n/2,n/2),Q5(n/2,n/2),Q6(n/2,n/2);

        MatrixXd A11=A.topLeftCorner(n/2,n/2);
        MatrixXd A12=A.topRightCorner(n/2,n/2);
        MatrixXd A21=A.bottomLeftCorner(n/2,n/2);
        MatrixXd A22=A.bottomRightCorner(n/2,n/2);

        MatrixXd B11=B.topLeftCorner(n/2,n/2);
        MatrixXd B12=B.topRightCorner(n/2,n/2);
        MatrixXd B21=B.bottomLeftCorner(n/2,n/2);
        MatrixXd B22=B.bottomRightCorner(n/2,n/2);

        Q0=strassenMatMult(A11+A22,B11+B22);
        Q1=strassenMatMult(A21+A22,B11);
        Q2=strassenMatMult(A11,B12-B22);
        Q3=strassenMatMult(A22,B21-B11);
        Q4=strassenMatMult(A11+A12,B22);
        Q5=strassenMatMult(A21-A11,B11+B12);
        Q6=strassenMatMult(A12-A22,B21+B22);

        C<< Q0+Q3-Q4+Q6 ,
        Q2+Q4,
        Q1+Q3,
        Q0+Q2-Q1+Q5;
        return C;
    }
}

int main(void)
{
    srand((unsigned int) time(0));

    //check if strassenMatMult works
    int k=2;
    int n=pow(2,k);
    MatrixXd A=MatrixXd::Random(n,n);
    MatrixXd B=MatrixXd::Random(n,n);
    MatrixXd AB(n,n), AxB(n,n);
    AB=strassenMatMult(A,B);
    AxB=A*B;
    cout<<"Using Strassen's method, A*B="<<AB<<endl;
    cout<<"Using standard method, A*B="<<AxB<<endl;
    cout<<"The norm of the error is "<<(AB-AxB).norm()<<endl;

    //compare runtimes of strassenMatMult and of direct multiplication

    unsigned int repeats = 10;
    timer<> tm_x, tm_strassen;
    std::vector<int> times_x, times_strassen;

    for(unsigned int k = 4; k <= 10; k++) {
        tm_x.reset();
        tm_strassen.reset();
        for(unsigned int r = 0; r < repeats; ++r) {
            unsigned int n = pow(2,k);
            A = MatrixXd::Random(n,n);
            B = MatrixXd::Random(n,n);
            MatrixXd AB(n,n);

            tm_x.start();
            AB=A*B;
            tm_x.stop();

            tm_strassen.start();
            AB=strassenMatMult(A,B);
            tm_strassen.stop();
        }
        std::cout << "The standard matrix multiplication took:       " << tm_x.avg().count() / 1000000. << " ms" << std::endl;
        std::cout << "The Strassen's algorithm took:       " << tm_strassen.avg().count() / 1000000. << " ms" << std::endl;

        times_x.push_back( tm_x.avg().count() );
        times_strassen.push_back( tm_strassen.avg().count() );
    }

    for(auto it = times_x.begin(); it != times_x.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    for(auto it = times_strassen.begin(); it != times_strassen.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

}

Nummerical Methods for CSE/solutions/solution_0/strassen.cpp


#include <Eigen/Dense>
#include <unsupported/Eigen/MatrixFunctions>
#include <iostream>
#include <vector>
#include <iomanip>

using namespace Eigen;
using namespace std;

// This C++ function phim gives the function phi used for the construction of the exponential Euler single step method for an autonomous ODE.
MatrixXd  phim(MatrixXd Z) {
    int n = Z.cols();
    assert( n == Z.rows() && "Matrix must be square.");
    MatrixXd C(2*n,2*n);
    C << Z, MatrixXd::Identity(n,n), MatrixXd::Zero(n,2*n);
    return C.exp().block(0,n,n,n);
}

// This function calculates a single step of the exponential Euler method, where y0 is the initial state, f and df are object with evaluation operators representing f and df, and h is the stepsize.
template <class Function, class Function2>
VectorXd ExpEulStep(VectorXd y0, Function f, Function2 df, double h) {
   return  y0 + h * phim( h * df(y0)) * f(y0);
}

// Test the exponential Euler method with the logistic ODE and determine the approximated order of algebraic convergence.
int main() {
    double T = 1;
    VectorXd y0(1); y0 << 0.1;
    auto f = [] (VectorXd y) {return y(0)*(1-y(0));};
    auto df = [] (VectorXd y) {VectorXd dfy(1); dfy << 1-2*y(0); return dfy;};
    double exactyT = y0(0)/(y0(0)+(1-y0(0))*exp(-T));

    vector<double> error(15);

    for (int j=0; j < 15; j++) {
        int N = pow(2,j+1);
        double h = T / N;
        VectorXd y = y0;
        for (int k=0; k < N; k++) y = ExpEulStep(y,f,df,h);

        error[j] = abs(y(0) - exactyT);
        cout << left << setw(3) << setfill(' ') << "N = ";
        cout << left << setw(7) << setfill(' ') << N;
        cout << left << setw(8) << setfill(' ') << "Error = ";
        cout << left << setw(13) << setfill(' ') << error[j];
        if (j > 0)  cout << left << setw(10) << setfill(' ') << "Approximated order = " << log(error[j-1]/error[j])/log(2) <<endl;
        else cout << endl;
    }
}

Nummerical Methods for CSE/PS13/solutions_ps13/ExpEul.cpp


#include <Eigen/Dense>
#include <iostream>
#include <cassert>

/**
 * @brief Resolve given polynom at x value
 *
 * @param p
 * @param x
 * @return double
 */
double evalPolynomial(const Eigen::VectorXd &p, const double x) {
    double result = 0;
    double power_x = 1;
    for (unsigned int i = 0; i < p.size(); i++) {
        result += p[i] * power_x;
        power_x *= x;
    }
    return result;
}

/**
 * @brief Multiply given polynom by X at value power
 *
 * @param p
 * @param value
 * @return Eigen::VectorXd
 */
Eigen::VectorXd multiplyPolynomByX(const Eigen::VectorXd &p, const unsigned int value) {
    Eigen::VectorXd result(p.size() + value);
    for (unsigned int i = 0; i < value; i++) {
        result[i] = 0;
    }
    for (unsigned int i = value; i < result.size(); i++) {
        result[i] = p[i - value];
    }
    return result;
}

/**
 * @brief Multiply given polynom by given constant
 *
 * @param p
 * @param value
 * @return Eigen::VectorXd
 */
Eigen::VectorXd multiplyPolynomByConstant(Eigen::VectorXd p, const unsigned int value) {
    for (unsigned int i = 0; i < p.size(); i++) {
        p[i] *= value;
    }
    return p;
}

/**
 * @brief Substract p1 polynom by p2
 *
 * @param p1
 * @param p2
 * @return Eigen::VectorXd
 */
Eigen::VectorXd substractPolynoms(const Eigen::VectorXd& p1, const Eigen::VectorXd& p2) {
    assert(p1.size() == p2.size() && "To be substracted, polynoms must be same size");
    Eigen::VectorXd result(p1.size());
    result[0] = -p2[0];
    result[result.size() - 1] = p1[result.size() - 1];

    for (unsigned int i = 1; i < result.size() - 1; i++) {
        result[i] = p1[i] - p2[i];
    }
    return result;
}

/**
 * @brief Returns a polynom from its root values
 *
 * @param roots
 * @return Eigen::VectorXd
 */
Eigen::VectorXd polynomialFromRoots(const Eigen::VectorXd &roots) {
    Eigen::VectorXd p = Eigen::VectorXd::Ones(roots.size() + 1);

    // For the first root
    p(0) = -roots(0);

    // For the other roots
    for (unsigned int i = 0; i < roots.size(); i++) {
        for (unsigned int j = i; j > 0; j--) {
            p(j) = p(j-1)-roots(i)*p(j);
        }
        p(0) *= -roots(i);
    }

    return p;
}

/**
 * @brief
 *
 * @param p - Polynom to solve
 * @return Eigen::VectorXd
 */
Eigen::VectorXd findRoots(const Eigen::VectorXd &p, unsigned int nbIter) {
    Eigen::VectorXd pUnit = p / p(p.size() - 1);
    Eigen::MatrixXd c = Eigen::MatrixXd::Zero(p.size() - 1, p.size() - 1);
    c.bottomLeftCorner(c.rows() - 1, c.cols() - 1).setIdentity();
    c.rightCols(1) = -pUnit.head(pUnit.size() - 1);

    // Iterative solver
    for (size_t i = 0; i < nbIter; i++) {
        Eigen::HouseholderQR<Eigen::MatrixXd> qr(c);
        Eigen::MatrixXd q = qr.householderQ();
        Eigen::MatrixXd r = qr.matrixQR().triangularView<Eigen::Upper>();
        c = r * q;
    }

    return c.diagonal();
}

/**
 * @brief Returns the derivate of a polynom
 *
 * @param p
 * @return Eigen::VectorXd
 */
Eigen::VectorXd derivative(const Eigen::VectorXd& p) {
    Eigen::VectorXd derivate(p.size() - 1);
    for (unsigned int i = 0; i < derivate.size(); ++i) {
        derivate(i) = (i + 1) * p(i + 1);
    }
    return derivate;
}

/**
 * @brief
 *
 * @param p
 * @param roots
 * @return Eigen::VectorXd
 */
Eigen::VectorXd rootsRafinement(const Eigen::VectorXd& p, Eigen::VectorXd roots, const unsigned int nbIter = 10) {
    Eigen::VectorXd pDerivative = derivative(p);

    for (unsigned int i = 0; i < roots.size(); i++) {
        if (abs(roots(i)) > 0) {
            for (unsigned int j = 0; j < nbIter; j++) {
                roots(i) = roots(i) - ( evalPolynomial(p, roots(i)) / evalPolynomial(pDerivative, roots(i)) );
            }
        }
    }

    return roots;
}

int main(int argc, char const *argv[]) {
    Eigen::VectorXd myRoot(5);
    myRoot << 1, 2, 2, 3, 4;
    auto myPolynom = polynomialFromRoots(myRoot);

    auto foundRoot = findRoots(myPolynom, 10);
    auto foundRootRaf = rootsRafinement(myPolynom, foundRoot, 50);

    std::cout << foundRootRaf << std::endl;
    return 0;
}


#include <iostream>
#include <Eigen/Dense>
#include <vector>

void choleskyDecompositionExample()
{
/*
Positive-definite matrix:
    Matrix Mnxn is said to be positive definite if the scalar zTMz is strictly positive for every non-zero
    column vector z n real numbers. zTMz>0

Hermitian matrix:
    Matrix Mnxn is said to be positive definite if the scalar z*Mz is strictly positive for every non-zero
    column vector z n real numbers. z*Mz>0
    z* is the conjugate transpose of z.

Positive semi-definite same as above except zTMz>=0 or  z*Mz>=0

    Example:
            ┌2  -1  0┐
        M=  |-1  2 -1|
            |0 - 1  2|
            └        ┘
          ┌ a ┐
        z=| b |
          | c |
          └   ┘
        zTMz=a^2 +c^2+ (a-b)^2+ (b-c)^2

Cholesky decomposition:
Cholesky decomposition of a Hermitian positive-definite matrix A is:
    A=LL*

    L is a lower triangular matrix with real and positive diagonal entries
    L* is the conjugate transpose of L
*/

    Eigen::MatrixXd A(3,3);
    A << 6, 0, 0, 0, 4, 0, 0, 0, 7;
    Eigen::MatrixXd L( A.llt().matrixL() );
    Eigen::MatrixXd L_T=L.adjoint();//conjugate transpose

    std::cout << "L" << std::endl;
    std::cout << L << std::endl;
    std::cout << "L_T" << std::endl;
    std::cout << L_T << std::endl;
    std::cout << "A" << std::endl;
    std::cout << A << std::endl;
    std::cout << "L*L_T" << std::endl;
    std::cout << L*L_T << std::endl;

}

void qRDecomposition(Eigen::MatrixXd &A,Eigen::MatrixXd &Q, Eigen::MatrixXd &R)
{
    /*
        A=QR
        Q: is orthogonal matrix-> columns of Q are orthonormal
        R: is upper triangulate matrix
        this is possible when columns of A are linearly indipendent
    */

    Eigen::MatrixXd thinQ(A.rows(),A.cols() ), q(A.rows(),A.rows());

    Eigen::HouseholderQR<Eigen::MatrixXd> householderQR(A);
    q = householderQR.householderQ();
    thinQ.setIdentity();
    Q = householderQR.householderQ() * thinQ;
    R=Q.transpose()*A;
}

void qRExample()
{

    Eigen::MatrixXd A;
    A.setRandom(3,4);

    std::cout<<"A" <<std::endl;
    std::cout<<A <<std::endl;
    Eigen::MatrixXd Q(A.rows(),A.rows());
    Eigen::MatrixXd R(A.rows(),A.cols());

    /////////////////////////////////HouseholderQR////////////////////////
    Eigen::MatrixXd thinQ(A.rows(),A.cols() ), q(A.rows(),A.rows());

    Eigen::HouseholderQR<Eigen::MatrixXd> householderQR(A);
    q = householderQR.householderQ();
    thinQ.setIdentity();
    Q = householderQR.householderQ() * thinQ;

    std::cout << "HouseholderQR" <<std::endl;

    std::cout << "Q" <<std::endl;
    std::cout << Q <<std::endl;

    R = householderQR.matrixQR().template  triangularView<Eigen::Upper>();
    std::cout << R<<std::endl;
    std::cout << R.rows()<<std::endl;
    std::cout << R.cols()<<std::endl;

    R=Q.transpose()*A;
// 	std::cout << "R" <<std::endl;
// 	std::cout << R<<std::endl;

    std::cout << "A-Q*R" <<std::endl;
    std::cout << A-Q*R <<std::endl;

    /////////////////////////////////ColPivHouseholderQR////////////////////////
    Eigen::ColPivHouseholderQR<Eigen::MatrixXd> colPivHouseholderQR(A.rows(), A.cols());
    colPivHouseholderQR.compute(A);
    //R = colPivHouseholderQR.matrixR().template triangularView<Upper>();
    R = colPivHouseholderQR.matrixR();
    Q = colPivHouseholderQR.matrixQ();

    std::cout << "ColPivHouseholderQR" <<std::endl;

    std::cout << "Q" <<std::endl;
    std::cout << Q <<std::endl;

    std::cout << "R" <<std::endl;
    std::cout << R <<std::endl;

    std::cout << "A-Q*R" <<std::endl;
    std::cout << A-Q*R <<std::endl;

    /////////////////////////////////FullPivHouseholderQR////////////////////////
    std::cout << "FullPivHouseholderQR" <<std::endl;

    Eigen::FullPivHouseholderQR<Eigen::MatrixXd> fullPivHouseholderQR(A.rows(), A.cols());
    fullPivHouseholderQR.compute(A);
    Q=fullPivHouseholderQR.matrixQ();
    R=fullPivHouseholderQR.matrixQR().template  triangularView<Eigen::Upper>();

    std::cout << "Q" <<std::endl;
    std::cout << Q <<std::endl;

    std::cout << "R" <<std::endl;
    std::cout << R <<std::endl;

    std::cout << "A-Q*R" <<std::endl;
    std::cout << A-Q*R <<std::endl;

}

void lDUDecomposition()
{
/*

    L: lower triangular matrix L
    U: upper triangular matrix U
    D: is a diagonal matrix
    A=LDU

*/
}

void lUDecomposition()
{
/*
    L: lower triangular matrix L
    U: upper triangular matrix U
    A=LU
*/
}

/*
function [U]=gramschmidt(V)
[n,k] = size(V);
U = zeros(n,k);
U(:,1) = V(:,1)/norm(V(:,1));
for i = 2:k
    U(:,i)=V(:,i);
    for j=1:i-1
        U(:,i)=U(:,i)-(U(:,j)'*U(:,i) )/(norm(U(:,j)))^2 * U(:,j);
    end
    U(:,i) = U(:,i)/norm(U(:,i));
end
end

*/

void householderTransformation()
{

}
//http://eigen.tuxfamily.org/dox/group__DenseDecompositionBenchmark.html

void denseDecompositions()
{
    //LLT
    //LDLT
    //PartialPivLU
    //FullPivLU
    //HouseholderQR
    //ColPivHouseholderQR
    //CompleteOrthogonalDecomposition
    //FullPivHouseholderQR
    //JacobiSVD
    //BDCSVD
}
int main()
{

}


#include <Eigen/Core>
#include <iostream>
#include <LBFGSB.h>

using namespace LBFGSpp;

typedef double Scalar;
typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;

// Example from the roptim R package
// f(x) = (x[0] - 1)^2 + 4 * (x[1] - x[0]^2)^2 + ... + 4 * (x[end] - x[end - 1]^2)^2
class Rosenbrock
{
private:
    int n;
public:
    Rosenbrock(int n_) : n(n_) {}
    Scalar operator()(const Vector& x, Vector& grad)
    {
        Scalar fx = (x[0] - 1.0) * (x[0] - 1.0);
        grad[0] = 2 * (x[0] - 1) + 16 * (x[0] * x[0] - x[1]) * x[0];
        for(int i = 1; i < n; i++)
        {
            fx += 4 * std::pow(x[i] - x[i - 1] * x[i - 1], 2);
            if(i == n - 1)
            {
                grad[i] = 8 * (x[i] - x[i - 1] * x[i - 1]);
            } else {
                grad[i] = 8 * (x[i] - x[i - 1] * x[i - 1]) + 16 * (x[i] * x[i] - x[i + 1]) * x[i];
            }
        }
        return fx;
    }
};

int main()
{
    const int n = 25;
    LBFGSBParam<Scalar> param;
    LBFGSBSolver<Scalar> solver(param);
    Rosenbrock fun(n);

    // Variable bounds
    Vector lb = Vector::Constant(n, 2.0);
    Vector ub = Vector::Constant(n, 4.0);
    // The third variable is unbounded
    lb[2] = -std::numeric_limits<Scalar>::infinity();
    ub[2] = std::numeric_limits<Scalar>::infinity();
    // Initial values
    Vector x = Vector::Constant(n, 3.0);
    // Make some initial values at the bounds
    x[0] = x[1] = 2.0;
    x[5] = x[7] = 4.0;

    Scalar fx;
    int niter = solver.minimize(fun, x, fx, lb, ub);

    std::cout << niter << " iterations" << std::endl;
    std::cout << "x = \n" << x.transpose() << std::endl;
    std::cout << "f(x) = " << fx << std::endl;

    return 0;
}


//#include <DES.h>
#include <NTL/ZZ.h>
#include <RSA.h>
#include <X917.h>
#include <fstream>
#include <json.hpp>
#include <random>
#include <sstream>
#include <string>
using nlohmann::json;
using namespace NTL;
using namespace std;
namespace RSA {
template <typename T> string tostr(T t) {
	stringstream buf;
	buf << t;
	return buf.str();
}
ZZ atozz(string in) {
	ZZ zz;
	stringstream buf(in);
	buf >> zz;
	return zz;
}
bool is_Prime(const ZZ &n, long t) {
	if (n <= 1)
		return 0;
	// first, perform trial division by primes up to 2000
	PrimeSeq s; // a class for quickly generating primes in sequence
	long p;
	p = s.next(); // first prime is always 2
	while (p && p < 2000) {
		if ((n % p) == 0)
			return (n == p);
		p = s.next();
	}
	// second, perform t Miller-Rabin tests
	ZZ x;
	int i;
	for (i = 0; i < t; i++) {
		x = RandomBnd(n); // random number between 0 and n-1
		if (MillerWitness(n, x))
			return 0;
	}
	return 1;
}

ZZ getPrime(int bits) {
	ZZ prim;
	while (1) {
		prim = X917rand(bitset<64>(rand()), bits / 64);
		if (is_Prime(prim, bits))
			break;
	}
	return prim;
}
void savePrivateKey(privateKey const &key, std::string const &file) {
	json keyJson;
	keyJson["p"] = tostr(key.p);
	keyJson["q"] = tostr(key.q);
	keyJson["d"] = tostr(key.d);
	ofstream out(file, ios::out);
	out << keyJson.dump();
	out.close();
	return;
}
void savePublicKey(publicKey const &key, std::string const &file) {
	json keyJson;
	keyJson["n"] = tostr(key.n);
	keyJson["e"] = tostr(key.e);
	ofstream out(file, ios::out);
	out << keyJson.dump();
	out.close();
	return;
}
int loadPrivateKey(privateKey &priK, std::string const &file) {
	try {
		json keyJson;
		ifstream in(file, ios::in);
		in >> keyJson;
		in.close();
		priK.d = atozz(keyJson["d"].get<string>());
		priK.p = atozz(keyJson["p"].get<string>());
		priK.q = atozz(keyJson["q"].get<string>());
	} catch (exception const &e) {
		return 1;
	}
	return 0;
}
int loadPublicKey(publicKey &pubK, std::string const &file) {
	try {
		json keyJson;
		ifstream in(file, ios::in);
		in >> keyJson;
		in.close();
		pubK.e = atozz(keyJson["e"].get<string>());
		pubK.n = atozz(keyJson["n"].get<string>());
	} catch (exception const &e) {
		return 1;
	}
	return 0;
}

void makeKey(privateKey &priK, publicKey &pubK, int bits) {
	ZZ &p = priK.p, &q = priK.q, &n = pubK.n, &d = priK.d, &e = pubK.e;
	// p
	p = getPrime(bits);
	// q
	q = getPrime(bits);
	// n
	n = priK.p * priK.q;
	// e,d
	ZZ phyN = (p - 1) * (q - 1);
	while (1) {
		e = RandomBnd(phyN);
		if (InvModStatus(d, e, phyN) == 0)
			break;
	}
	return;
}
ZZ encipher(NTL::ZZ data, publicKey const &key) {
	return PowerMod(data, key.e, key.n);
}
ZZ decipher(NTL::ZZ data, privateKey const &key) {
	return PowerMod(data, key.d, key.p * key.q);
}
} // namespace RSA


// haversine.cpp
//
// Haversine Formula Implementation
//
// The Haversine formula can be used to compute an estimated distance between
// two points on a sphere. This program provides the ability to compute an
// estimated distance between two points on the Earth from their respective
// latitudes and longitudes.
//
// This implementation assumes that the Earth is a perfect sphere, with a
// radius of 6378 km (3963 miles)

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <boost/math/constants/constants.hpp>

int main(int argc, char* argv[]) {

	// Validate usage
	if (argc != 5) {
		std::cout << "Usage: haversine lat1 lon1 lat2 lon2" << std::endl;
		return -1;
	}

	double lat_1_deg, lon_1_deg, lat_2_deg, lon_2_deg;
	sscanf(argv[1], "%lf", &lat_1_deg);
	sscanf(argv[2], "%lf", &lon_1_deg);
	sscanf(argv[3], "%lf", &lat_2_deg);
	sscanf(argv[4], "%lf", &lon_2_deg);

	std::cout << "Calculating distance between ("
			  << std::setprecision(9) << lat_1_deg << ","
			  << std::setprecision(9) << lon_1_deg << ")" << " and ("
			  << std::setprecision(9) << lat_2_deg << ","
			  << std::setprecision(9) << lon_2_deg << ")" << std::endl;

	// Convert coordinates to radians (rad = deg * (pi / 2))
	double lat_1_rad, lon_1_rad, lat_2_rad, lon_2_rad;
	lat_1_rad = lat_1_deg * (boost::math::constants::pi<double>() / 180);
	lon_1_rad = lon_1_deg * (boost::math::constants::pi<double>() / 180);
	lat_2_rad = lat_2_deg * (boost::math::constants::pi<double>() / 180);
	lon_2_rad = lon_2_deg * (boost::math::constants::pi<double>() / 180);

	// Determine latitude and longitude deltas
	double delta_lat, delta_lon;
	delta_lat = lat_1_rad - lat_2_rad;
	delta_lon = lon_1_rad - lon_2_rad;

	// Calculate sin^2 (delta / 2) for both lat and long
	double sdlat = pow(sin(delta_lat / 2), 2);
	double sdlon = pow(sin(delta_lon / 2), 2);

	// Radius of the Earth (approximate)
	const double radius_earth_miles = 3963;
	const double radius_earth_km = 6378;

	// http://en.wikipedia/org/wiki/Haversine_formula
	// d=2r*asin(sqrt(sin^2((lat1-lat2)/2)+cos(l1)cos(l2)sin^2((lon2-lon1)/2)))
	//  if t = sqrt(sin^2((lat1-lat2)/2)+cos(l1)cos(l2)sin^2((lon2-lon1)/2)
	//  -> d = 2 * radius_earth * asin (t)
	double t = sqrt(sdlat + (cos(lat_1_rad) * cos(lat_2_rad) * sdlon));
	double distance_miles = 2 * radius_earth_miles * asin(t);
	double distance_km = 2 * radius_earth_km * asin(t);

	// Output results
	std::cout << "Distance: " << std::endl;
	std::cout << "  " << std::setprecision(4) << distance_miles
					  << " miles" << std::endl;
	std::cout << "  " << std::setprecision(4) << distance_km
					  << " kilometers" << std::endl;

	return 0;
}


// Copyright Nick Thompson 2017.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <iostream>
#include <string>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/math/special_functions/legendre_stieltjes.hpp>

using boost::math::legendre_p;
using boost::math::legendre_p_zeros;
using boost::math::legendre_p_prime;
using boost::math::legendre_stieltjes;
using boost::multiprecision::cpp_bin_float_quad;
using boost::multiprecision::cpp_bin_float_100;

template<class Real>
void gauss_konrod_rule(size_t order)
{
    std::cout << std::setprecision(std::numeric_limits<Real>::digits10);
    std::cout << std::fixed;
    auto gauss_nodes = boost::math::legendre_p_zeros<Real>(order);
    auto E = legendre_stieltjes<Real>(order + 1);
    std::vector<Real> gauss_weights(gauss_nodes.size(), std::numeric_limits<Real>::quiet_NaN());
    std::vector<Real> gauss_konrod_weights(gauss_nodes.size(), std::numeric_limits<Real>::quiet_NaN());
    for (size_t i = 0; i < gauss_nodes.size(); ++i)
    {
        Real node = gauss_nodes[i];
        Real lp = legendre_p_prime<Real>(order, node);
        gauss_weights[i] = 2/( (1-node*node)*lp*lp);
        // P_n(x) = (2n)!/(2^n (n!)^2) pi_n(x), where pi_n is the monic Legendre polynomial.
        gauss_konrod_weights[i] = gauss_weights[i] + static_cast<Real>(2)/(static_cast<Real>(order+1)*legendre_p_prime(order, node)*E(node));
    }

    std::cout << "Gauss Nodes:\n";
    for (auto const & node : gauss_nodes)
    {
        std::cout << node << "\n";
    }

    std::cout << "Gauss Weights:\n";
    for (auto const & weight : gauss_weights)
    {
        std::cout << weight << "\n";
    }

    std::cout << "Gauss-Konrod weights: \n";
    for (auto const & w : gauss_konrod_weights)
    {
        std::cout << w << "\n";
    }

    auto konrod_nodes = E.zeros();
    std::vector<Real> konrod_weights(konrod_nodes.size());
    for (size_t i = 0; i < konrod_weights.size(); ++i)
    {
        Real node = konrod_nodes[i];
        konrod_weights[i] = static_cast<Real>(2)/(static_cast<Real>(order+1)*legendre_p(order, node)*E.prime(node));
    }

    std::cout << "Konrod nodes:\n";
    for (auto node : konrod_nodes)
    {
        std::cout << node << "\n";
    }

    std::cout << "Konrod weights: \n";
    for (auto const & w : gauss_konrod_weights)
    {
        std::cout << w << "\n";
    }

}

int main()
{
    std::cout << "Gauss-Konrod 7-15 Rule:\n";
    gauss_konrod_rule<cpp_bin_float_100>(7);

    std::cout << "\n\nGauss-Konrod 10-21 Rule:\n";
    gauss_konrod_rule<cpp_bin_float_100>(10);

    std::cout << "\n\nGauss-Konrod 15-31 Rule:\n";
    gauss_konrod_rule<cpp_bin_float_100>(15);

    std::cout << "\n\nGauss-Konrod 20-41 Rule:\n";
    gauss_konrod_rule<cpp_bin_float_100>(20);

    std::cout << "\n\nGauss-Konrod 25-51 Rule:\n";
    gauss_konrod_rule<cpp_bin_float_100>(25);

    std::cout << "\n\nGauss-Konrod 30-61 Rule:\n";
    gauss_konrod_rule<cpp_bin_float_100>(30);

}