Background:
I am writing the least squares algorithm into a class in C++ and I want to make sure that what I am doing is the most efficient and hopefully fast. I used the Eigen library to write all the sub-routines to price the American option contracts. I have not completed the algorithm yet but I have a majority of the sub-routines done, and tested them to make sure they are working correctly.
Question:
I am getting this unknown error from Eigen when I build it on Eclipse:
c:\mingw\include\c++\6.2.0\eigen\src/Core/PlainObjectBase.h:774:7: error: static assertion failed: FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED
EIGEN_STATIC_ASSERT(is_integer,
I am not sure what the problem is.
Here is my header file:
#include <vector>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#ifndef LSM_H
#define LSM_H
class LSM {
public:
// Overload Constructor
LSM(const double, const double, const double, const int, const int, const double, const double, const int, const int);
// Destructor
~LSM();
// Generate the Laguerre Polynomials
Eigen::MatrixXd Laguerre(Eigen::VectorXd, const int);
// Generate Gaussian noise
// Generate M paths of stock prices (Geometric Brownian Motion)
Eigen::VectorXd GBM(const int, const int, const double, const double, const double, const double, const double);
// Generate time paths
Eigen::VectorXd timepaths(const double, const double, const double);
// Payoff of call option
Eigen::VectorXd callPayoff(Eigen::VectorXd, const double);
// Payoff of put option
Eigen::VectorXd putPayoff(Eigen::VectorXd, const double);
// Find function for finding the paths that are in the money (call option)
Eigen::VectorXd Findcallpath(Eigen::VectorXd, const double);
// Find function for finding the paths that are in the money (put option)
Eigen::VectorXd Findputpath(Eigen::VectorXd, const double);
// Find price of call given path
Eigen::VectorXd Findcallprices(Eigen::VectorXd, Eigen::VectorXd);
// Find price of put given path
Eigen::VectorXd Findputprices(Eigen::VectorXd, Eigen::VectorXd);
// Find return of call (stock price - strike price)
Eigen::VectorXd Findcallreturn(Eigen::VectorXd, const double);
// Find return of put (strike price - stock price)
Eigen::VectorXd Findputreturn(Eigen::VectorXd, const double);
// Using Two-sided Jacobi SVD decomposition of a rectangular matrix
Eigen::VectorXd Jacobi(Eigen::MatrixXd, Eigen::VectorXd);
private:
// Member variables
double new_r;
double new_q;
double new_sigma;
int new_T;
int new_N;
double new_K;
double new_S0;
int new_M;
int new_R;
};
#endif
Here is the associated .cpp file:
#include <iostream>
#include <vector>
#include <random>
#include <time.h>
#include <math.h>
#include "LSM.h"
#include <Eigen/Dense>
#include <Eigen/Geometry>
LSM::LSM( const double r, const double q, const double sigma, const int T, const int N, const double K, const double S0, const int M, const int R){
new_r = r;
new_q = q;
new_sigma = sigma;
new_T = T;
new_N = N;
new_K = K;
new_S0 = S0;
new_M = M;
new_R = R;
/* Eigen::VectorXd V(4);
V(0) = 100;
V(1) = 102;
V(2) = 103;
V(3) = 104;
Eigen::MatrixXd A = Laguerre(2,V);
std::cout << A << std::endl;*/
/* Eigen::VectorXd v;
v = GBM(new_M, new_N, new_T, new_r, new_q, new_sigma, new_S0);
std::cout << v << std::endl;*/
/* Eigen::VectorXd S(3);
S(0) = 101;
S(1) = 102;
S(2) = 105;
S = Findcallpath(S,102);
std::cout << S << std::endl;*/
Eigen::VectorXd S = GBM(new_M, new_N, new_T, new_r, new_q, new_sigma, new_S0);
Eigen::VectorXd t = timepaths(0,new_T,new_N);
Eigen::VectorXd P = putPayoff(S,new_K); // Payoff at time T
for(int i = new_N; i >= 2; i--){
}
}
LSM::~LSM(){
}
Eigen::MatrixXd LSM::Laguerre(Eigen::VectorXd X, const int R){
int n = X.rows();
int m = R + 1;
Eigen::MatrixXd value(n, m);
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(R == 1){
value(i,0) = 1.0;
value(i,1) = -X(i) + 1.0;
}
else if(R == 2){
value(i,0) = 1.0;
value(i,1) = -X(i) + 1.0;
value(i,2) = 1.0/2.0*(2 - 4*X(i) + X(i)*X(i));
}
else if(R == 3){
value(i,0) = 1.0;
value(i,1) = -X(i) + 1.0;
value(i,2) = 1.0/2.0*(2 - 4*X(i) + X(i)*X(i));
value(i,3) = 1.0/6.0*(6.0 - 18.0*X(i,0) + 9.0*X(i)*X(i) - pow((double)X(i,0),3.0));
}
}
}
return value;
}
Eigen::VectorXd LSM::timepaths(const double min, const double max, const double N){
Eigen::VectorXd m(N + 1);
double delta = (max-min)/N;
for(int i = 0; i <= N; i++){
m(i) = min + i*delta;
}
return m;
}
Eigen::VectorXd LSM::GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0){
double dt = T/N;
Eigen::VectorXd Z(M);
Eigen::VectorXd S(M);
S(0) = S0;
std::mt19937 e2(time(0));
std::normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
Z(i) = dist(e2);
}
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < M; i++){
S(i) = S(i-1) * drift * exp(vol * Z(i));
}
return S;
}
Eigen::VectorXd LSM::callPayoff(Eigen::VectorXd S, const double K){
Eigen::VectorXd C(S.size());
for(int i = 0; i < S.size(); i++){
if(S(i) - K > 0){
C(i) = S(i) - K;
}else{
C(i) = 0.0;
}
}
return C;
}
Eigen::VectorXd LSM::putPayoff(Eigen::VectorXd S, const double K){
Eigen::VectorXd P(S.size());
for(int i = 0; i < S.size(); i++){
if(K - S(i) > 0){
P(i) = K - S(i);
}else{
P(i) = 0.0;
}
}
return P;
}
Eigen::VectorXd LSM::Findcallpath(Eigen::VectorXd S, const double K){
Eigen::VectorXd path(S.size());
int count = 0;
for(int i = 0; i < S.size(); i++){
if(S(i) - K > 0){
path(count) = i;
count++;
}
}
path.conservativeResize(count);
return path;
}
Eigen::VectorXd LSM::Findputpath(Eigen::VectorXd S, const double K){
Eigen::VectorXd path(S.size());
int count = 0;
for(int i = 0; i < S.size(); i++){
if(K - S(i) > 0){
path(count) = i;
count++;
}
}
path.conservativeResize(count);
return path;
}
Eigen::VectorXd Findcallprices(Eigen::VectorXd path, Eigen::VectorXd S){
Eigen::VectorXd C(path.size());
for(int i = 0; i < path.size(); i++){
C(i) = S(path(i));
}
return C;
}
Eigen::VectorXd Findputprices(Eigen::VectorXd path, Eigen::VectorXd S){
Eigen::VectorXd P(path.size());
for(int i = 0; i < path.size(); i++){
P(i) = S(path(i));
}
return P;
}
Eigen::VectorXd LSM::Jacobi(Eigen::MatrixXd L, Eigen::VectorXd Y){
Eigen::VectorXd reg(L.rows());
return reg = L.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Y);
}
Eigen::VectorXd LSM::Findcallreturn(Eigen::VectorXd S, const double K){
Eigen::VectorXd C_return(S.size());
for(int i = 0; i < S.size(); i++){
C_return(i) = (S(i) - K);
}
return C_return;
}
Eigen::VectorXd LSM::Findputreturn(Eigen::VectorXd S, const double K){
Eigen::VectorXd P_return(S.size());
for(int i = 0; i < S.size(); i++){
P_return(i) = (K - S(i));
}
return P_return;
}
You just have to follow your compiler error message to find the offending line in your code, which is in the function LSM::timepaths where you are passing a double to construct a VectorXd:
VectorXd LSM::timepaths(const double min, const double max, const double N)
{
VectorXd m(N + 1);
[...]
Should be:
VectorXd m(int(N) + 1);
For the record, after copying your code within a .cpp file, the compiler says:
../eigen/Eigen/src/Core/PlainObjectBase.h:779:27: error: no member named 'FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED' in 'Eigen::internal::static_assertion<false>'
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
^
../eigen/Eigen/src/Core/Matrix.h:296:22: note: in instantiation of function template specialization 'Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::_init1<double>' requested here
Base::template _init1<T>(x);
^
foo.cpp:166:21: note: in instantiation of function template specialization 'Eigen::Matrix<double, -1, 1, 0, -1, 1>::Matrix<double>' requested here
Eigen::VectorXd m(N + 1);
^
This cannot be more explicit.
Edit: there are more issues, like indexing a VectorXd with double:
Eigen::VectorXd C, S, path;
C(i) = S(path(i));
Please use Eigen::VectorXi or std::vector<int> to hold indexes.
Related
I am trying to compare the ODE-solver of GSL with odeint from boost for multi-dimensional systems, and therefore wrote a short test program:
#include <iostream>
#include <cmath>
#include <vector>
#include <chrono>
#include <boost/numeric/odeint.hpp>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
constexpr int bench_rounds = 10000;
constexpr int dim = 100;
typedef std::vector<double> state_type;
struct simulation_parameters{
int dimension = dim; /* number of differential equations */
double eps_abs = 1.e-8; /* absolute error requested */
double eps_rel = 1.e-11; /* relative error requested */
double tmin = 0.; /* starting t value */
double tmax = 10.; /* final t value */
double delta_t = 1e-2;
double h = 1e-6; /* starting step size for ode solver */
};
struct push_back_state_and_time
{
std::vector< state_type >& m_states;
std::vector< double >& m_times;
push_back_state_and_time( std::vector< state_type > &states , std::vector< double > × )
: m_states( states ) , m_times( times ) { }
void operator()( const state_type &x , double t )
{
m_states.push_back( x );
m_times.push_back( t );
}
};
int gsl_rhs (double t, const double y[], double f[], void *params_ptr)
{
/* get parameter(s) from params_ptr; here, just a double */
double mu = *(double *) params_ptr;
/* evaluate the right-hand-side functions at t */
for(size_t i = 0; i < dim; ++i)
f[i] = -2 * M_PI * y[i];
return GSL_SUCCESS; /* GSL_SUCCESS defined in gsl/errno.h as 0 */
};
void boost_rhs(const state_type &y, state_type &f, const int t){
(void) t;
for(size_t i = 0; i < y.size(); ++i)
f[i] = -2 * M_PI * y[i];
}
class boost_calculator{
public:
boost_calculator(const size_t n_dimensions) : n_dimensions(n_dimensions) {};
void operator()(const state_type &x, state_type &dx, const double){
dx.resize(n_dimensions);
for(size_t i = 0; i < n_dimensions; ++i)
dx[i] = -2 * M_PI * x[i];
}
private:
size_t n_dimensions;
};
double exact_solution(const double t){
return exp(-2 * M_PI * t);
};
double check_solution_correctness(const std::vector<std::pair<double, double>> &solution){
double error = 0;
for(size_t i = 0; i < solution.size(); ++i){
const double local_error = std::abs(solution[i].second - exact_solution (solution[i].first));
error += local_error;
}
return error;
}
double check_solution_correctness(const std::vector<std::pair<double, double*>> &solution){
double error = 0;
for(size_t i = 0; i < solution.size(); ++i){
double local_error = 0;
for(size_t j = 0; j < dim; ++j)
local_error += std::abs(solution[i].second[j] - exact_solution (solution[i].first));
error += local_error;
}
return error;
}
double check_solution_correctness(const std::vector<std::pair<double, std::vector<double>>> &solution){
double error = 0;
for(size_t i = 0; i < solution.size(); ++i){
double local_error = 0;
for(size_t j = 0; j < solution[i].second.size(); ++j)
local_error += std::abs(solution[i].second[j] - exact_solution (solution[i].first));
error += local_error;
}
return error;
}
double check_solution_correctness(const std::vector<std::pair<double, std::complex<double>>> &solution){
double error = 0;
for(size_t i = 0; i < solution.size(); ++i){
const double local_error = std::abs(solution[i].second - exact_solution (solution[i].first));
error += local_error;
}
return error;
}
void solve_equation_with_GSL(std::vector<std::pair<double, state_type>> &solution, const simulation_parameters ¶ms){
/* define the type of routine for making steps: */
const gsl_odeiv2_step_type *type_ptr = gsl_odeiv2_step_rkf45;
/*
allocate/initialize the stepper, the control function, and the
evolution function.
*/
gsl_odeiv2_step *step_ptr = gsl_odeiv2_step_alloc (type_ptr, params.dimension);
gsl_odeiv2_control *control_ptr = gsl_odeiv2_control_y_new (params.eps_abs, params.eps_rel);
gsl_odeiv2_evolve *evolve_ptr = gsl_odeiv2_evolve_alloc (params.dimension);
gsl_odeiv2_system my_system; /* structure with the rhs function, etc. */
double mu = 10; /* parameter for the diffeq */
double y[dim]; /* current solution vector */
double t, t_next; /* current and next independent variable */
double tmin, tmax, delta_t; /* range of t and step size for output */
double h = params.h;
tmin = params.tmin;
tmax = params.tmax;
delta_t = params.delta_t;
/* load values into the my_system structure */
my_system.function = gsl_rhs; /* the right-hand-side functions dy[i]/dt */
my_system.jacobian = nullptr; /* the Jacobian df[i]/dy[j] */
my_system.dimension = params.dimension; /* number of diffeq's */
my_system.params = μ /* parameters to pass to rhs and jacobian */
for(size_t i = 0; i < dim; ++i)
y[i] = 1.; /* initial x value */
t = tmin; /* initialize t */
//printf ("%.5e %.5e %.5e\n", t, y[0], exact_solution (t)); /* initial values */
/* step to tmax from tmin */
const int vector_size = (int)((tmax - tmin) / delta_t) + 1;
solution.clear();
solution.resize(vector_size - 1);
int counter = 0;
for (t_next = tmin + delta_t; t_next <= tmax; t_next += delta_t)
{
while (t < t_next) /* evolve from t to t_next */
{
gsl_odeiv2_evolve_apply (evolve_ptr, control_ptr, step_ptr,
&my_system, &t, t_next, &h, y);
}
//printf ("%.5e %.5e %.5e %.5e\n", t, y[0], y[1], exact_solution (t)); /* print at t=t_next */
solution[counter] = std::make_pair(t_next, state_type(y, y + dim));
counter++;
}
/* all done; free up the gsl_odeiv stuff */
gsl_odeiv2_evolve_free (evolve_ptr);
gsl_odeiv2_control_free (control_ptr);
gsl_odeiv2_step_free (step_ptr);
}
void solve_equation_with_Boost(std::vector<std::pair<double, state_type>> &solution, const simulation_parameters ¶ms){
using namespace boost::numeric::odeint;
typedef runge_kutta_fehlberg78<state_type> error_stepper_type;
state_type x_0 = state_type{1.};
typedef controlled_runge_kutta< error_stepper_type > controlled_stepper_type;
controlled_stepper_type controlled_stepper;
std::vector<state_type> x_vec;
std::vector<double> t;
const size_t steps = integrate_adaptive(make_controlled<error_stepper_type>(params.eps_abs, params.eps_rel),
boost_rhs, x_0, params.tmin, params.tmax, params.delta_t, push_back_state_and_time(x_vec, t));
solution.clear();
solution.resize(steps);
for(size_t i = 0; i < steps; ++i)
solution[i] = std::make_pair(t[i], x_vec[i]);
}
void solve_equation_with_Boost_class(std::vector<std::pair<double, state_type>> &solution, const simulation_parameters ¶ms){
using namespace boost::numeric::odeint;
typedef runge_kutta_fehlberg78<state_type> error_stepper_type;
state_type x_0 = state_type{1.};
typedef controlled_runge_kutta< error_stepper_type > controlled_stepper_type;
controlled_stepper_type controlled_stepper;
std::vector<state_type> x_vec;
std::vector<double> t;
boost_calculator local_calculator(dim);
const size_t steps = integrate_adaptive(make_controlled<error_stepper_type>(params.eps_abs, params.eps_rel),
local_calculator, x_0, params.tmin, params.tmax, params.delta_t, push_back_state_and_time(x_vec, t));
solution.clear();
solution.resize(steps);
for(size_t i = 0; i < steps; ++i)
solution[i] = std::make_pair(t[i], x_vec[i]);
}
int main()
{
std::vector<std::pair<double, state_type>> GSL_solution;
std::vector<std::pair<double, state_type>> boost_solution, boost_class_solution;
simulation_parameters local_sim_params;
auto t1 = std::chrono::high_resolution_clock::now();
for(size_t i = 0; i < bench_rounds; ++i)
solve_equation_with_GSL(GSL_solution, local_sim_params);
auto t2 = std::chrono::high_resolution_clock::now();
auto t3 = std::chrono::high_resolution_clock::now();
for(size_t i = 0; i < bench_rounds; ++i)
solve_equation_with_Boost (boost_solution, local_sim_params);
auto t4 = std::chrono::high_resolution_clock::now();
auto t5 = std::chrono::high_resolution_clock::now();
for(size_t i = 0; i < bench_rounds; ++i)
solve_equation_with_Boost_class (boost_class_solution, local_sim_params);
auto t6 = std::chrono::high_resolution_clock::now();
std::cout << "GSL-error: " << check_solution_correctness(GSL_solution)
<< ", solved within " << std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count()
<< " ms" << '\n';
std::cout << "Boost-error: " << check_solution_correctness (boost_solution)
<< ", solved within " << std::chrono::duration_cast<std::chrono::milliseconds>( t4 - t3 ).count()
<< " ms" << '\n';
std::cout << "Boost_class-error: " << check_solution_correctness (boost_class_solution)
<< ", solved within " << std::chrono::duration_cast<std::chrono::milliseconds>( t6 - t5 ).count()
<< " ms" << '\n';
return 0;
}
Initially I started using one dimension, and extended it to several dimensions. My current test results are
GSL-error: 1.40024e-06, solved within 30924 ms
Boost-error: 1.74368e-08, solved within 1879 ms
Boost_class-error: 1.74368e-08, solved within 10482 ms
As far as I know I have to create a separate class if I would like to transfer parameters to my rhs calculation routine, but to compare it to the class-less version, I implemented both versions.
Now, for dim = 1 that code worked fine, but for dim > 1 I experienced segfaults in the rhs-calculation function of the boost class. The way I could fix it was to resize the solution vector each time I call the function, but that slows that function down significantly compared to the class-less function (as seen in the results). Therefore, is there another way of implementing the class-based function without having to resize the vector? And why do the class-less functions always have the correct size for f, but the class-function does not?
Define in the class solving function x_0 like so:
state_type x_0(dim, 1.);
and remove the resize from the class solver's operator()
And the result will look like this:
GSL-error: 1.40024e-06, solved within 31397 ms
Boost-error: 1.74368e-08, solved within 152 ms
Boost_class-error: 1.74368e-06, solved within 1985 ms
Still a lot slower, but that is due to the overhead of the struct creation? Overhead, which could be avoided, if the class was reused.
Hi I am having trouble witht his C++ code, developed with Code Blockers. It implements sense and move of robot( very basic ) , there is vector p of probabilites that wil change ofter I apply the sense and move im my main function.
There is a sense function and a move function below that basically change my vector of probabilities p .
I call them in my main fucntion but it does not seem to work it return 5 nan values.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<float> p (5);
vector<string> world (5);
vector<string> measurements (2);
vector<int> motions (2);
float pHit;
float pMiss;
float pExact;
float pOvershoot;
float pUndershoot;
vector<float> sense(vector<float> p, string Z);
vector<float> move(vector<float> p, int U);
int main(){
vector<float> p = {0.2, 0.2, 0.2, 0.2, 0.2};
vector<string> world = {"green", "red", "red", "green", "green"};
vector<string> measurements = {"red", "green"};
//string measurements = "red";
vector<int> motions = {1,1};
float pHit = 0.6;
float pMiss = 0.2;
float pExact = 0.8;
float p0vershoot = 0.1;
float pUndershoot = 0.1;
vector<float> sense(vector<float> p, string Z);
vector<float> moves(vector<float> p, int U);
for(int i=0; i<measurements.size(); i++){
p = sense(p, measurements[i]);
p = moves(p, motions[i]);
}
for(int i=0; i<p.size(); i++){
cout << p[i] << " ";
}
return 0;
}
vector<float> sense(vector<float> p, string Z){
vector<float> q;
// q.reserve(p.size());
for(int i=0; i<p.size(); i++){
bool hit = (Z == world[i]);
q.push_back(p[i] * (hit * pHit + (1-hit) * pMiss));
}
float s = 0.0;
for(int i=0; i<q.size(); i++){
s += q[i];
}
for(int i=0; i<q.size(); i++){
q[i] /= s;
}
return q;
}
vector<float> moves(vector<float> p, int U){
vector<float> q;
// q.reserve(p.size());
for(int i=0; i<p.size(); i++){
float s = pExact * p[(i-U) % p.size()];
s = s + pOvershoot * p[(i-U-1) % p.size()];
s = s + pUndershoot * p[(i-U+1) % p.size()];
q.push_back(s);
}
return q;
}
Your code wouldn't compile the way you presented it here. First, you are trying to reference local variables defined in main in other functions.Second, you have a bunch of implicit double to float conversions. If these issues are addressed one way or another, your code appears to work (see the code below).
#include <vector>
#include <iostream>
using namespace std;
vector<double> p = { 0.2, 0.2, 0.2, 0.2, 0.2 };
vector<string> world = { "green", "red", "red", "green", "green" };
vector<string> measurements = { "red", "green" };
float pHit = 0.6;
float pMiss = 0.2;
float pExact = 0.8;
float pOvershoot = 0.1;
float pUndershoot = 0.1;
int main() {
//string measurements = "red";
vector<int> motions = { 1,1 };
vector<double> sense(vector<double> p, string Z);
vector<double> moves(vector<double> p, int U);
for (int i = 0; i<measurements.size(); i++) {
p = sense(p, measurements[i]);
p = moves(p, motions[i]);
}
for (int i = 0; i<p.size(); i++) {
cout << p[i] << " ";
}
return 0;
}
vector<double> sense(vector<double> p, string Z) {
vector<double> q;
// q.reserve(p.size());
for (int i = 0; i<p.size(); i++) {
bool hit = (Z == world[i]);
q.push_back(p[i] * (hit * pHit + (1 - hit) * pMiss));
}
float s = 0.0;
for (int i = 0; i<q.size(); i++) {
s += q[i];
}
for (int i = 0; i<q.size(); i++) {
q[i] /= s;
}
return q;
}
vector<double> moves(vector<double> p, int U) {
vector<double> q;
// q.reserve(p.size());
for (int i = 0; i<p.size(); i++) {
float s = pExact * p[(i - U) % p.size()];
s = s + pOvershoot * p[(i - U - 1) % p.size()];
s = s + pUndershoot * p[(i - U + 1) % p.size()];
q.push_back(s);
}
return q;
}
I am new to C++ and I am using the Eigen library. I was wondering if there was a way to sum certain elements in a vector. For example, say I have a vector that is a 100 by 1 and I just want to sum the first 10 elements. Is there a way of doing that using the Eigen library?
What I am trying to do is this: say I have a vector that is 1000 by 1 and I want to take the mean of the first 10 elements, then the next 10 elements, and so on and store that in some vector. Hence I will have a vector of size 100 of the averages. Any thoughts or suggestions are greatly appreciated.
Here is the beginning steps I have in my code. I have a S_temp4vector that is 1000 by 1. Now I intialize a new vector S_A that I want to have as the vector of the means. Here is my messy sloppy code so far: (Note that my question resides in the crudeMonteCarlo function)
#include <iostream>
#include <cmath>
#include <math.h>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>
#include <time.h>
using namespace Eigen;
using namespace std;
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n);
VectorXd time_vector(double min, double max, int n);
VectorXd call_payoff(VectorXd S, double K);
int main(){
int N = 100;
double K = 100;
double r = 0.2;
double S0 = 100;
double sigma = 0.4;
double T = 0.1;
int n = 10;
crudeMonteCarlo(N,K,r,S0,sigma,T,n);
return 0;
}
VectorXd time_vector(double min, double max, int n){
VectorXd m(n + 1);
double delta = (max-min)/n;
for(int i = 0; i <= n; i++){
m(i) = min + i*delta;
}
return m;
}
MatrixXd generateGaussianNoise(int M, int N){
MatrixXd Z(M,N);
static random_device rd;
static mt19937 e2(time(0));
normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
Z(i,j) = dist(e2);
}
}
return Z;
}
VectorXd call_payoff(VectorXd S, double K){
VectorXd C(S.size());
for(int i = 0; i < S.size(); i++){
if(S(i) - K > 0){
C(i) = S(i) - K;
}else{
C(i) = 0.0;
}
}
return C;
}
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n){
// Create time vector
VectorXd tt = time_vector(0.0,T,n);
VectorXd t(n);
double dt = T/n;
for(int i = 0; i < n; i++){
t(i) = tt(i+1);
}
// Generate standard normal Z matrix
//MatrixXd Z = generateGaussianNoise(N,n);
// Generate the log normal stock process N times to get S_A for crude Monte Carlo
MatrixXd SS(N,n+1);
MatrixXd Z = generateGaussianNoise(N,n);
for(int i = 0; i < N; i++){
SS(i,0) = S0;
for(int j = 1; j <= n; j++){
SS(i,j) = SS(i,j-1)*exp((double) (r - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
}
}
// This long bit of code gives me my S_A.....
Map<RowVectorXd> S_temp1(SS.data(), SS.size());
VectorXd S_temp2(S_temp1.size());
for(int i = 0; i < S_temp2.size(); i++){
S_temp2(i) = S_temp1(i);
}
VectorXd S_temp3(S_temp2.size() - N);
int count = 0;
for(int i = N; i < S_temp2.size(); i++){
S_temp3(count) = S_temp2(i);
count++;
}
VectorXd S_temp4(S_temp3.size());
for(int i = 0; i < S_temp4.size(); i++){
S_temp4(i) = S_temp3(i);
}
VectorXd S_A(N);
S_A(0) = (S_temp4(0) + S_temp4(1) + S_temp4(2) + S_temp4(3) + S_temp4(4) + S_temp4(5) + S_temp4(6) + S_temp4(7) + S_temp4(8) + S_temp4(9))/(n);
S_A(1) = (S_temp4(10) + S_temp4(11) + S_temp4(12) + S_temp4(13) + S_temp4(14) + S_temp4(15) + S_temp4(16) + S_temp4(17) + S_temp4(18) + S_temp4(19))/(n);
int count1 = 0;
for(int i = 0; i < S_temp4.size(); i++){
S_A(count1) =
}
// Calculate payoff of Asian option
//VectorXd call_fun = call_payoff(S_A,K);
}
This question includes a lot of code, which makes it hard to understand the question you're trying to ask. Consider including only the code specific to your question.
In any case, you can use Eigen directly to do all of these things quite simply. In Eigen, Vectors are just matrices with 1 column, so all of the reasoning here is directly applicable to what you've written.
const Eigen::Matrix<double, 100, 1> v = Eigen::Matrix<double, 100, 1>::Random();
const int num_rows = 10;
const int num_cols = 1;
const int starting_row = 0;
const int starting_col = 0;
const double sum_of_first_ten = v.block(starting_row, starting_col, num_rows, num_cols).sum();
const double mean_of_first_ten = sum_of_first_ten / num_rows;
In summary: You can use .block to get a block object, .sum() to sum that block, and then conventional division to get the mean.
You can reshape the input using Map and then do all sub-summations at once without any loop:
VectorXd A(1000); // input
Map<MatrixXd> B(A.data(), 10, A.size()/10); // reshaped version, no copy
VectorXd res = B.colwise().mean(); // partial reduction, you can also use .sum(), .minCoeff(), etc.
The Eigen documentation at https://eigen.tuxfamily.org/dox/group__TutorialBlockOperations.html says an Eigen block is a rectangular part of a matrix or array accessed by matrix.block(i,j,p,q) where i and j are the starting values (eg 0 and 0) and p and q are the block size (eg 10 and 1). Presumably you would then iterate i in steps of 10, and use std::accumulate or perhaps an explicit summation to find the mean of matrix.block(i,0,10,1).
I am using the dlib optimization library for C++ specifically the following function:
template <
typename search_strategy_type,
typename stop_strategy_type,
typename funct,
typename funct_der,
typename T
>
double find_max (
search_strategy_type search_strategy,
stop_strategy_type stop_strategy,
const funct& f,
const funct_der& der,
T& x,
double max_f
);
Functions f and der are designed to take a vector of the data parameters being modified to obtain the maximum value of my function. However my function being maximized has four parameters (one is my dataset and the other is fixed by me). However I can't pass these as inputs to my f and der functions because of the format they are supposed to have. How do I get this data into my functions? I am currently trying the below (I hard set variable c but for vector xgrequ I read data from a file each time I process the function.
//Function to be minimized
double mleGPD(const column_vector& p)
{
std::ifstream infile("Xm-EVT.csv");
long double swapRet;
std::string closeStr;
std::vector<double> histRet;
//Read in historical swap data file
if (infile.is_open())
{
while (!infile.eof())
{
infile >> swapRet;
histRet.push_back(swapRet);
}
}
sort(histRet.begin(), histRet.end());
std::vector<double> negRet;
//separate out losses
for (unsigned c = 0; c < histRet.size(); c++)
{
if (histRet[c] < 0)
{
negRet.push_back(histRet[c]);
}
}
std::vector<double> absValRet;
//make all losses positive to fit with EVT convention
for (unsigned s = 0; s < negRet.size(); s++)
{
absValRet.push_back(abs(negRet[s]));
}
std::vector<double> xminusu, xmu, xgrequ;
int count = absValRet.size();
double uPercent = .9;
int uValIndex = ceil((1 - uPercent)*count);
int countAbove = count - uValIndex;
double c = (double)absValRet[uValIndex - 1];
//looking at returns above u
for (unsigned o = 0; o < uValIndex; ++o)
{
xmu.push_back(absValRet[o] - c);
if (xmu[o] >= 0)
{
xgrequ.push_back(absValRet[o]);
xminusu.push_back(xmu[o]);
}
}
double nu = xgrequ.size();
double sum = 0.0;
double a = p(0);
double b = p(1);
for (unsigned h = 0; h < nu; ++h)
{
sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
}
return sum;
}
//Derivative of function to be minimized
const column_vector mleGPDDer(const column_vector& p)
{
std::ifstream infile("Xm-EVT.csv");
long double swapRet;
std::string closeStr;
std::vector<double> histRet;
//Read in historical swap data file
if (infile.is_open())
{
while (!infile.eof())
{
infile >> swapRet;
histRet.push_back(swapRet);
}
}
sort(histRet.begin(), histRet.end());
std::vector<double> negRet;
//separate out losses
for (unsigned c = 0; c < histRet.size(); c++)
{
if (histRet[c] < 0)
{
negRet.push_back(histRet[c]);
}
}
std::vector<double> absValRet;
//make all losses positive to fit with EVT convention
for (unsigned s = 0; s < negRet.size(); s++)
{
absValRet.push_back(abs(negRet[s]));
}
std::vector<double> xminusu, xmu, xgrequ;
int count = absValRet.size();
double uPercent = .9;
int uValIndex = ceil((1 - uPercent)*count);
int countAbove = count - uValIndex;
double c = (double)absValRet[uValIndex - 1];
//looking at returns above u
for (unsigned o = 0; o < uValIndex; ++o)
{
xmu.push_back(absValRet[o] - c);
if (xmu[o] >= 0)
{
xgrequ.push_back(absValRet[o]);
xminusu.push_back(xmu[o]);
}
}
column_vector res(2);
const double a = p(0);
const double b = p(1);
double nu = xgrequ.size();
double sum1 = 0.0;
double sum2 = 0.0;
for (unsigned h = 0; h < nu; ++h)
{
sum1 += ((xgrequ[h]-c)/b)/(1-a*((xgrequ[h]-c)/b));
sum2 += log(1 - a*((xgrequ[h] - c) / b));
}
res(0) = sum1;//df/da
res(1) = sum2;//df/db
return res;
}
Here is what my actual function call looks like:
//Dlib max finding
column_vector start(2);
start = .1, .1; //starting point for a and b
find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), mleGPD, mleGPDDer, start,100);
std::cout << "solution" << start << std::endl;
This kind of API is very common. It's almost always possible to for f and der to any callable, not just static functions. that is, you can pass a custom class object with operator () to it.
For example
struct MyF {
//int m_state;
// or other state variables, such as
std::vector<double> m_histRet;
// (default constructors will do)
double operator()(const column_vector& p) const {
return some_function_of(p, m_state);
}
};
int main(){
. . .
MyF myf{42};
// or
MyF myf{someVectorContainingHistRet};
// then use myf as you would have used mleGPD
}
You need to initiate MyF and MyDer with the same state (std::vector<double> histRet I presume.) Either as copies or (const) references to the same state.
Edit: More full example:
struct MLGDPG_State {
std::vector<double> xgrequ;
// . . . and more you need in f or fder
}
MLGDPG_State makeMLGDPG_State(const std::string& filename){
std::ifstream infile(filename);
std::ifstream infile("Xm-EVT.csv");
long double swapRet;
std::string closeStr;
std::vector<double> histRet;
//Read in historical swap data file
if (infile.is_open())
{
while (!infile.eof())
{
infile >> swapRet;
histRet.push_back(swapRet);
}
}
sort(histRet.begin(), histRet.end());
std::vector<double> negRet;
//separate out losses
for (unsigned c = 0; c < histRet.size(); c++)
{
if (histRet[c] < 0)
{
negRet.push_back(histRet[c]);
}
}
std::vector<double> absValRet;
//make all losses positive to fit with EVT convention
for (unsigned s = 0; s < negRet.size(); s++)
{
absValRet.push_back(abs(negRet[s]));
}
std::vector<double> xminusu, xmu, xgrequ;
int count = absValRet.size();
double uPercent = .9;
int uValIndex = ceil((1 - uPercent)*count);
int countAbove = count - uValIndex;
double c = (double)absValRet[uValIndex - 1];
//looking at returns above u
for (unsigned o = 0; o < uValIndex; ++o)
{
xmu.push_back(absValRet[o] - c);
if (xmu[o] >= 0)
{
xgrequ.push_back(absValRet[o]);
xminusu.push_back(xmu[o]);
}
}
return {std::move(xgrequ)};
// Or just 'return MleGPD(xgrequ)' if you are scared of {} and move
}
//Functor Class, for ion to be minimized
struct MleGPD{
MLGDPG_State state;
double operator()(const column_vector& p) const {
auto mu = state.xgrequ.size();
double sum = 0.0;
double a = p(0);
double b = p(1);
for (unsigned h = 0; h < nu; ++h)
{
sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
}
return sum;
};
Use the same pattern for a struct MleGPD_Derivative.
Usage:
const auto state = makeMLGDPG_State("Xm-EVT.csv");
const auto f = MleGPD{state};
const auto der = MleGPD_Derivative{state};
start = .1, .1; //starting point for a and b
find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), f, der, start,100);
std::cout << "solution" << start << std::endl;
Note, that for simple structs like these, it's often fine to use the default constructors, copy constructor etc. Also note http://en.cppreference.com/w/cpp/language/aggregate_initialization
I'm getting the following errors due to the namespace cpl?
I included Wavepacket.cpp and Vector.hpp below.
obj\Debug\wavepacket.o||In function `Z10initializev':|
wavepacket.cpp|79|undefined reference to `cpl::Vector::Vector(int)'|
wavepacket.cpp|79|undefined reference to `cpl::Vector::operator=(cpl::Vector const&)'|
wavepacket.cpp|80|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|80|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|81|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|81|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|101|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|101|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|102|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|102|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
wavepacket.cpp|103|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|103|undefined reference to `cpl::ComplexVector::operator=(cpl::ComplexVector const&)'|
obj\Debug\wavepacket.o||In function `Z8timeStepv':|
wavepacket.cpp|124|undefined reference to `cpl::solveTridiagonalCyclic(cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&, std::complex<double>, std::complex<double>, cpl::ComplexVector&, cpl::ComplexVector&)'|
wavepacket.cpp|126|undefined reference to `cpl::solveTridiagonal(cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&, cpl::ComplexVector&)'|
obj\Debug\wavepacket.o||In function `_static_initialization_and_destruction_0':|
wavepacket.cpp|22|undefined reference to `cpl::Vector::Vector(int)'|
wavepacket.cpp|71|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|71|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|72|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|72|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
wavepacket.cpp|72|undefined reference to `cpl::ComplexVector::ComplexVector(int)'|
||=== Build finished: 20 errors, 0 warnings ===|
Wavepacket.cpp
#include <cmath>
#include <complex>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <sstream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "Vector.hpp"
const double pi = 4*std::atan(1.0);
double h_bar = 1; // natural units
double mass = 1; // natural units
// The spatial grid
int N = 200; // number of interior grid points
double L = 100; // system extends from x=0 to x=L
double h = L / (N + 1); // grid size
double tau = 1; // time step
cpl::Vector x; // coordinates of grid points
bool periodic = true; // false = oo potential, true = periodic
// The potential V(x)
double V0 = 1.0; // height of potential well
double Vwidth = 10; // width of potential well
double Vcenter = 0.75 * L; // center of potential well
bool gaussian; // false = step potential
double V(double x) {
double halfWidth = std::abs(0.5 * Vwidth);
if (gaussian) {
double dx = (x - Vcenter) / halfWidth;
return V0 * std::exp( - dx * dx / 2);
} else {
if (std::abs(x - Vcenter) <= halfWidth)
return V0;
else
return 0;
}
}
// Inital wave packet
double x0 = L / 4; // location of center
double E = 1; // average energy
double sigma0 = L / 10; // width of wave packet
double Norm_psi; // norm of psi
double k0; // average wavenumber
double velocity; // average velocity
void getInput() {
std::cout << "Time-dependent Schroedinger Equation\n";
std::cout << "Enter size of x region L = ";
std::cin >> L;
std::cout << "Enter number of grid points N = ";
std::cin >> N;
std::cout << "Enter integration time step tau = ";
std::cin >> tau;
std::cout << "Enter width of potential = ";
std::cin >> Vwidth;
std::cout << "Enter height of potential V0 = ";
std::cin >> V0;
std::cout << "Enter width of packet sigma = ";
std::cin >> sigma0;
std::cout << "Enter energy of packet E = ";
std::cin >> E;
}
double t; // time
cpl::ComplexVector psi, chi; // complex wavefunction
cpl::ComplexVector a, b, c; // to represent tridiagonal Q matrix
std::complex<double> alpha, beta; // corner elements of Q
void initialize () {
t = 0;
// reset vectors
x = cpl::Vector(N);
psi = cpl::ComplexVector(N);
chi = cpl::ComplexVector(N);
// reset the lattice
h = L / (N + 1);
for (int j = 0; j < N; j++)
x[j] = (j + 1) * h;
// inititalize the packet
k0 = std::sqrt(2*mass*E - h_bar*h_bar/2/sigma0/sigma0) / h_bar;
velocity = k0 / mass;
Norm_psi = 1 / std::sqrt(sigma0 * std::sqrt(pi));
for (int j = 0; j < N; j++) {
double expFactor = std::exp(-(x[j] - x0) * (x[j] - x0)
/ (2 * sigma0 * sigma0));
psi[j] = std::complex<double>(
Norm_psi * std::cos(k0 * x[j]) * expFactor,
Norm_psi * std::sin(k0 * x[j]) * expFactor);
}
// elements of tridiagonal matrix Q = (1/2)(1 + i tau H / (2 hbar))
a = cpl::ComplexVector(N);
b = cpl::ComplexVector(N);
c = cpl::ComplexVector(N);
for (int j = 0; j < N; j++) {
const std::complex<double> i(0.0, 1.0);
b[j] = 0.5 + i * tau / (4 * h_bar) *
(V(x[j]) + h_bar * h_bar / (mass * h * h));
a[j] = c[j] = - i * tau * h_bar / (8 * mass * h * h);
}
alpha = c[N-1];
beta = a[0];
}
double T = 5; // time to travel length L
double framesPerSec = 50; // animation rate for screen redraws
void timeStep() {
static std::clock_t clockStart;
static bool done;
if (!done) {
double t0 = t;
do {
if (periodic)
solveTridiagonalCyclic(a, b, c, alpha, beta, psi, chi);
else
solveTridiagonal(a, b, c, psi, chi);
for (int j = 0; j < N; j++)
psi[j] = chi[j] - psi[j];
t += tau;
} while (std::abs(velocity * (t - t0)) < L / T / framesPerSec);
done = true;
}
std::clock_t clockNow = std::clock();
double seconds = (clockNow - clockStart) / double(CLOCKS_PER_SEC);
if ( seconds < 1 / framesPerSec ) {
return;
} else {
clockStart = clockNow;
done = false;
}
glutPostRedisplay();
glFlush();
}
void drawText(const std::string& str, double x, double y) {
glRasterPos2d(x, y);
int len = str.find('\0');
for (int i = 0; i < len; i++)
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[i]);
}
bool showRealImaginary; // false = probability only
void display() {
glClear(GL_COLOR_BUFFER_BIT);
if (showRealImaginary) {
glColor3f(0, 0, 1); // real part of psi blue
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
glVertex2d(x[j-1], psi[j-1].real());
glVertex2d(x[j], psi[j].real());
}
glEnd();
glColor3f(0, 1, 0); // imaginary part of psi green
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
glVertex2d(x[j-1], psi[j-1].imag());
glVertex2d(x[j], psi[j].imag());
}
glEnd();
}
glColor3f(1, 0, 0); // probability red
double pOld = psi[0].real() * psi[0].real() +
psi[0].imag() * psi[0].imag();
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
double p = psi[j].real() * psi[j].real() +
psi[j].imag() * psi[j].imag();
glVertex2d(x[j-1], 4 * pOld);
glVertex2d(x[j], 4 * p);
pOld = p;
}
glEnd();
glColor3ub(255, 165, 0); // potential orange
double Vold = V(x[1]);
glBegin(GL_LINES);
for (int j = 1; j < N; j++) {
double Vnew = V(x[j]);
glVertex2d(x[j-1], 0.2 * Vold);
glVertex2d(x[j], 0.2 * Vnew);
Vold = Vnew;
}
glEnd();
glColor3f(0, 0, 0); // text black
std::ostringstream os;
os << (periodic ? "Periodic " : "Infinite Wall ")
<< "Boundary Conditions" << std::ends;
drawText(os.str(), 0.02 * L, 0.28);
os.seekp(0); // beginning of string stream
os << "0" << std::ends;
drawText(os.str(), 0, -0.02);
drawText("0", 0, -0.02);
os.seekp(0);
os << "x = " << L << std::ends;
drawText(os.str(), (1 - 0.1) * L, -0.02);
os.seekp(0);
os << "t = " << t << std::ends;
drawText(os.str(), 0.02 * L, -0.29);
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, L, -0.3, 0.3);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
bool running; // to control animation
void mouse(int button, int state, int x, int y) {
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
if (running) {
glutIdleFunc(NULL);
running = false;
} else {
glutIdleFunc(timeStep);
running = true;
}
}
break;
default:
break;
}
}
void menu(int menuItem) {
switch (menuItem) {
case 1:
gaussian = !gaussian;
break;
case 2:
periodic = !periodic;
break;
case 3:
showRealImaginary = !showRealImaginary;
break;
case 4:
if (running) {
glutIdleFunc(NULL);
running = false;
}
initialize();
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char *argv[]) {
getInput();
initialize();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("Schroedinger Wave Packet Motion");
glClearColor(1.0, 1.0, 1.0, 0.0);
glShadeModel(GL_FLAT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutCreateMenu(menu);
glutAddMenuEntry("Potential: Square/Gaussian", 1);
glutAddMenuEntry("Boundaries: Dirichlet/Periodic", 2);
glutAddMenuEntry("Real & Imag: Show/Hide", 3);
glutAddMenuEntry("Reset", 4);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
}
Vector.hpp
#ifndef CPL_VECTOR_HPP
#define CPL_VECTOR_HPP
#include <complex>
#include <iostream>
namespace cpl {
class Vector {
public:
Vector(int dim = 1);
Vector(const Vector& dv);
~Vector() { delete [] v; }
int dimension() const { return dim; }
void resize(const int);
const double operator[](const int i) const { return v[i]; }
double& operator[](const int i) { return v[i]; }
Vector& operator = (const Vector& dv);
Vector& operator += (const Vector& dv);
Vector& operator -= (const Vector& dv);
Vector& operator *= (double d);
Vector& operator /= (double d);
double abs();
double norm();
double dot(const Vector& dv);
friend std::ostream& operator<<(std::ostream& os, const Vector& dv);
private:
int dim;
double *v;
};
inline Vector operator + (const Vector& dv) {
return dv;
}
extern Vector operator - (const Vector& dv);
extern Vector operator * (const Vector& dv, double d);
extern Vector operator * (double d, const Vector& dv);
extern Vector operator / (const Vector& dv, double d);
extern Vector operator + (const Vector& v1, const Vector& v2);
extern Vector operator - (const Vector& v1, const Vector& v2);
class ComplexVector {
public:
ComplexVector(int dim = 1);
ComplexVector(const ComplexVector& cv);
~ComplexVector() { delete [] v; }
int dimension() const { return dim; }
const std::complex<double> operator[](const int i) const { return v[i]; }
std::complex<double>& operator[](const int i) { return v[i]; }
ComplexVector& operator = (const ComplexVector& cv);
private:
int dim;
std::complex<double> *v;
};
class FFT {
public:
FFT() { N = 0; f = 0; inverse = false; }
void transform(ComplexVector& data);
void inverseTransform(ComplexVector& data);
Vector power(ComplexVector& data);
private:
int N;
ComplexVector *f;
bool inverse;
void bitReverse();
void DanielsonLanczos(int n);
};
extern void solveTridiagonal(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
ComplexVector& r, ComplexVector& u);
extern void solveTridiagonalCyclic(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
std::complex<double> alpha, std::complex<double> beta,
ComplexVector& r, ComplexVector& x);
} /* end namespace cpl */
#endif /* CPL_VECTOR_HPP */
EDIT I didn't want to delete this post incase someone needed it but I forgot to use Vector.cpp which is below.
#include "Vector.hpp"
namespace cpl {
Vector::Vector(int dim) {
v = new double [this->dim = dim];
for (int i = 0; i < dim; i++) v[i] = 0;
}
Vector::Vector(const Vector& dv) {
v = new double [dim = dv.dim];
for (int i = 0; i < dim; i++) v[i] = dv.v[i];
}
void Vector::resize(const int dimension) {
delete [] v;
v = new double [dim = dimension];
for (int i = 0; i < dim; i++) v[i] = 0;
}
Vector& Vector::operator = (const Vector& dv) {
if (this != &dv) {
if (dim != dv.dim) {
delete [] v;
v = new double [dim = dv.dim];
}
for (int i = 0; i < dim; i++) v[i] = dv[i];
}
return *this;
}
Vector& Vector::operator += (const Vector& dv) {
for (int i = 0; i < dim; i++) v[i] += dv[i];
return *this;
}
Vector& Vector::operator -= (const Vector& dv) {
for (int i = 0; i < dim; i++) v[i] -= dv[i];
return *this;
}
Vector& Vector::operator *= (double d) {
for (int i = 0; i < dim; i++) v[i] *= d;
return *this;
}
Vector& Vector::operator /= (double d) {
for (int i = 0; i < dim; i++) v[i] /= d;
return *this;
}
Vector operator - (const Vector& dv) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = -dv[i];
return temp;
}
Vector operator * (const Vector& dv, double d) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = dv[i] * d;
return temp;
}
Vector operator * (double d, const Vector& dv) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = dv[i] * d;
return temp;
}
Vector operator / (const Vector& dv, double d) {
int dim = dv.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = dv[i] / d;
return temp;
}
Vector operator + (const Vector& v1, const Vector& v2) {
int dim = v1.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = v1[i] + v2[i];
return temp;
}
Vector operator - (const Vector& v1, const Vector& v2) {
int dim = v1.dimension();
Vector temp(dim);
for (int i = 0; i < dim; i++) temp[i] = v1[i] - v2[i];
return temp;
}
double Vector::abs() {
return std::sqrt(norm());
}
double Vector::norm() {
double sum = 0;
for (int i = 0; i < dim; i++) sum += v[i] * v[i];
return sum;
}
double Vector::dot(const Vector& dv) {
double sum = 0;
for (int i = 0; i < dim; i++) sum += v[i] * dv[i];
return sum;
}
std::ostream& operator<<(std::ostream& os, const Vector& dv) {
for (int i = 0; i < dv.dim; i++) {
os << dv.v[i];
if (i < dv.dim-1)
os << '\t';
else
os << '\n';
}
return os;
}
// ComplexVector implementation
ComplexVector::ComplexVector(int dim) {
v = new std::complex<double> [this->dim = dim];
for (int i = 0; i < dim; i++) v[i] = 0.0;
}
ComplexVector::ComplexVector(const ComplexVector& cv) {
v = new std::complex<double> [dim = cv.dim];
for (int i = 0; i < dim; i++) v[i] = cv.v[i];
}
ComplexVector& ComplexVector::operator = (const ComplexVector& cv) {
if (this != &cv) {
if (dim != cv.dim) {
delete [] v;
v = new std::complex<double> [dim = cv.dim];
}
for (int i = 0; i < dim; i++) v[i] = cv[i];
}
return *this;
}
// FFT implementation
void FFT::transform(ComplexVector& data) {
N = data.dimension();
f = &data;
bitReverse();
for (int n = 1; n < N; n *= 2)
DanielsonLanczos(n);
for (int i = 0; i < N; ++i)
(*f)[i] /= std::sqrt(double(N));
}
void FFT::inverseTransform(ComplexVector& data) {
inverse = true;
transform(data);
inverse = false;
}
void FFT::bitReverse() {
int j = 1;
for (int i = 1; i < N; ++i) {
if (i < j) {
std::complex<double> temp = (*f)[i-1];
(*f)[i-1] = (*f)[j-1];
(*f)[j-1] = temp;
}
int k = N / 2;
while ( k < j ) {
j -= k;
k /= 2;
}
j += k;
}
}
void FFT::DanielsonLanczos(int n) {
const double pi = 4 * atan(1.0);
std::complex<double> W(0, pi / n);
W = inverse ? std::exp(-W) : std::exp(W);
std::complex<double> W_j(1, 0);
for (int j = 0; j < n; ++j) {
for (int i = j; i < N; i += 2 * n) {
std::complex<double> temp = W_j * (*f)[n+i];
(*f)[n+i] = (*f)[i] - temp;
(*f)[i] += temp;
}
W_j *= W;
}
}
Vector FFT::power(ComplexVector& data) {
Vector P(1 + N / 2);
P[0] = std::norm(data[0]) / double(N);
for (int i = 1; i < N / 2; i++)
P[i] = (std::norm(data[i]) + std::norm(data[N-i])) / double(N);
P[N/2] = std::norm(data[N/2]) / double(N);
return P;
}
// Solving tridiagonal complex matrices
void solveTridiagonal(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
ComplexVector& r, ComplexVector& u)
{
int n = a.dimension();
ComplexVector gamma(n);
std::complex<double> beta = b[0];
u[0] = r[0] / beta;
for (int j = 1; j < n; j++) {
gamma[j] = c[j-1] / beta;
beta = b[j] - a[j] * gamma[j];
u[j] = (r[j] - a[j] * u[j-1]) / beta;
}
for (int j = n - 2; j >= 0; j--)
u[j] -= gamma[j+1] * u[j+1];
}
void solveTridiagonalCyclic(
ComplexVector& a, ComplexVector& b, ComplexVector& c,
std::complex<double> alpha, std::complex<double> beta,
ComplexVector& r, ComplexVector& x)
{
int n = a.dimension();
ComplexVector bb(n), u(n), z(n);
std::complex<double> gamma = -b[0];
bb[0] = b[0] - gamma;
bb[n-1] = b[n-1] - alpha * beta / gamma;
for (int i = 1; i < n-1; i++)
bb[i] = b[i];
solveTridiagonal(a, bb, c, r, x);
u[0] = gamma;
u[n-1] = alpha;
for (int i = 1; i < n-1; i++)
u[i] = 0.0;
solveTridiagonal(a, bb, c, u, z);
std::complex<double> fact = x[0] + beta * x[n-1] / gamma;
fact /= 1.0 + z[0] + beta * z[n-1] / gamma;
for (int i = 0; i < n; i++)
x[i] -= fact * z[i];
}
} /* end namespace cpl */
it's probably your build script that's not configured correctly. Your code compiled for me when I used the following commands:
g++ -c Vector.cpp -o Vector.o
g++ -c Wavepacket.cpp -o Wavepacket.o
g++ Vector.o Wavepacket.o -lGL -lGLU -lglut -o app