For my assignment I have to implement an algorithm for the Bernstein polynomial defined on the interval [0,1].
My experiment needs to include the following function: f(x) = |ax|, for sake of simplicity in my code I let a = 1. When implementing the algorithm I used this Matlab code from our book (first picture) and the way the professors defines in his notes (second picture):matlab code professors defines in his notes
My output has all the same numbers, I think the problem is I am not sure what value k needs to be from the formula. Anyway here is my code:
#include <iostream>
#include <math.h>
using namespace std;
int combinations(int n, int k);
int fact(int n);
// Bernstein polynomial single precision
float Bernstein(float x[], float f[], int k, int n);
// Bernstein polynomial double precision
//float Bernstein(double x[], double k, int n);
//-------------------------------------------------------------
int main() {
int n,k;
cout << "Enter the degree: " << endl;
cin >> n;
cout << "Enter the k parameter: " << endl;
cin >> k;
float x[n];
double x_0[n];
// stepsize for interval [0,1]
double h = (1.0 - 0)/10.0;
for(int i = 0; i < n; i++){
x[i] = 0 + i*h;
x_0[i] = 0 + i*h;
}
// Compute the f(x_i) = y_i values single precision
float f_0[n], f_1[n], f_2[n];
float alpha = 1.0;
for(int i = 0; i < n; i++){
f_0[i] = fabs(alpha*x[i]);
f_1[i] = fabs(alpha*x[i]) + x[i]/2 - pow(x[i],2);
f_2[i] = 1/(1 + alpha*pow(x[i],2));
}
// Compute the f(x_i) = y_i values double precision
double alpha1 = 1.0;
double f0[n], f1[n], f2[n];
for(int i = 0; i < n; i++){
f0[i] = fabs(alpha1*x_0[i]);
f1[i] = fabs(alpha1*x_0[i]) + x_0[i]/2 - pow(x_0[i],2);
f2[i] = 1/(1 + alpha1*pow(x_0[i],2));
}
for(int i = 0; i < n; i++){
cout << Bernstein(x,f_0,k,n) << endl;
}
return 0;
}
//----------------------------------------------------------
float Bernstein(float x[], float f[], int k, int n){
int C;
float B;
if(k == 0){
C = 1;
}else{
C = combinations(n,k);
}
int t = n - k;
for(int i = 0; i < n; i++){
B = C*pow(x[i],k)*pow((1 - x[i]),t)*f[i];
}
return B;
}
int combinations(int n, int k){
return fact(n) / (fact(k) * fact(n - k));
}
int fact(int n){
int result = 1;
for (int i =1; i <= n; i++){
result = result*i;
}
return result;
}
Question:
Why does my output have all the same numbers, and what could be the problem?
bernstein(f,n,t) with a function handle f returns the nth-order Bernstein polynomial symsum(nchoosek(n,k)*t^k*(1-t)^(n-k)*f(k/n),k,0,n), evaluated at the point t. This polynomial approximates the function f over the interval [0,1].
Example:
bernstein(g,n,t) with a symbolic expression or function g returns the nth-order Bernstein polynomial, evaluated at the point t. This syntax regards g as a univariate function of the variable determined by symvar(g,1).
If any argument is symbolic, bernstein converts all arguments except a function handle to symbolic, and converts a function handle's results to symbolic.
I execute the program and how you say the output have the sames results. Did you make some changes at this program after your post? I am interesting on it, because i have a homework at home about bernstein polynomial.
Related
My implementation of the Durand-Kerner-Method (https://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method) does not seem to work. I believe (see following code) that I am not calculating new approximation correctly in the algorithm part itself. I cannot seem to be able to fix the problem. Very grateful for any advice.
#include <complex>
#include <cmath>
#include <vector>
#include <iostream>
#include "DurandKernerWeierstrass.h"
using namespace std;
using Complex = complex<double>;
using vec = vector<Complex>;
using Matrix = vector<vector<Complex>>;
//PRE: Recieves input value of polynomial, degree and coefficients
//POST: Outputs y(x) value
Complex Polynomial(vec Z, int n, Complex x) {
Complex y = pow(x, n);
for (int i = 0; i < n; i++){
y += Z[i] * pow(x, (n - i - 1));
}
return y;
}
/*PRE: Takes a test value, degree of polynomial, vector of coefficients and the desired
precision of polynomial roots to calculate the roots*/
//POST: Outputs the roots of Polynomial
Matrix roots(vec Z, int n, int iterations, const double precision) {
Complex z = Complex(0.4, 0.9);
Matrix P(iterations, vec(n, 0));
Complex w;
//Creating Matrix with initial starting values
for (int i = 0; i < n; i++) {
P[0][i] = pow(z, i);
}
//Durand Kerner Algorithm
for (int col = 0; col < iterations; col++) {
*//I believe this is the point where everything is going wrong*
for (int row = 0; row < n; row++) {
Complex g = Polynomial(Z, n, P[col][row]);
for (int k = 0; k < n; k++) {
if (k != row) {
g = g / (P[col][row] - P[col][k]);
}
}
P[col][row] -= g;
}
return P;
}
}
The following Code is the code I am using to test the function:
int main() {
//Initializing section
vec A = {1, -3, 3,-5 };
int n = 3;
int iterations = 10;
const double precision = 1.0e-10;
Matrix p = roots(A, n, iterations,precision);
for (int i = 0; i < iterations; i++) {
for (int j = 0; j < n; j++) {
cout << "p[" << i << "][" << j << "] = " << p[i][j] << " ";
}
cout << endl;
}
return 0;
}
Important to note the Durand-Kerner-Algorithm is connected to a header file which is not included in this code.
Your problem is that you do not transcribe the new values into the next data record with index col+1. Thus in the next loop you start again with a data set of zero entries. Change to
P[col+1][row] = P[col][row] - g;
If you want to use the new improved approximation immediately for all following approximations, then use
P[col+1][row] = (P[col][row] -= g);
Then the data sets all contain the next approximations, especially the first one will no longer contain the initially set powers.
I wrote a program for finding combination(n Choose r = nCr) using for loop/iterations, wanted to know how to do the same using recursion.
Code is as follows:
#include<iostream>
using namespace std;
int main(){
int n,r;
float num = 1,denum = 1,comb = 1;
cout<<"Enter the values of n and r in nCr \n";
cin>>n>>r;
for (int i = 1; i <= r; i++)
{
num *= (n-r+i);
}
for (int i = 1; i <= r; i++)
{
denum *= (i);
}
comb = num/denum;
cout<<"The number of combinations is "<<comb<<"\n";
}
The following code that I've written helps in finding nCr through recursion:
#include<iostream>
using namespace std;
float comb(int n,int r){
if(r!=0)
{
return (n-r+1)*comb(n,r-1)/r;
}
else
{
return 1;
}
}
int main(){
int n,r;
float com;
cout<<"Enter the values of n and r in nCr \n";
cin>>n>>r;
if(n-r>=r)
{
com = comb(n,r);
}
else
{
com = comb(n,n-r);
}
cout<<"The number of combinations is "<<com<<"\n";
}
Had done this program recently, upon calling the com function in main(), the function is calling itself(i.e recurses) until r value becomes 0 after which it goes to the base statement i.e return 1 if r equals 0
If you just need a code, here it is
int findNumerator(int num, int i, int r) {
return num * (i != r ? findNumerator(num, i+1, r) : 1);
}
int findDenominator(int denum, int i, int r) {
return denum * (i != r ? findDenominator(denum, i+1, r) : 1);
}
int main(){
int n,r;
float num = 1,denum = 1,comb = 1;
cout<<"Enter the values of n and r in nCr \n";
cin>>n>>r;
comb = findNumerator(num, 1, r) / findDenominator(denum, 1, r);
cout<<"The number of combinations is "<<comb<<"\n";
}
I am trying to solve the generalized eigenvalue problem for the hydrogen atom by using LAPACKE_dsygvd. For the parameters of the generator functions, I use an interval that starts at 0.01 and takes N steps of 0.01. What I change is the value of N. Everythings fine for N = 14 and below, where I get the answers from the analytical solution. However, when I choose N = 15 and above, I get an error and info is returned with a value > N. After reading the documentation from LAPACK, it says the following:
N: if INFO = N + i, for 1 <= i <= N, then the leading
minor of order i of B is not positive definite.
The factorization of B could not be completed and
no eigenvalues or eigenvectors were computed.
But I have checked my matrix B and it is positive definite. I don't know what is wrong.
Below I show my scripts
#include <cmath>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "library.h"
#include "mkl.h"
using namespace std;
double Superposition(const double ai, const double aj, const int m);
double Hamiltonian(const double ai, const double aj, const int m);
void print_matrix(double *A, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%.7f ", A[i*n + j]);
}
cout << "\n";
}
}
void print_vector(double *vec, int n) {
for (int i = 0; i < n; i++) {
cout << vec[i] << " ";
}
cout << "\n";
}
double* interval(double min, double step) {
double *result;
result = (double *)mkl_malloc( N*sizeof( double ), 64 );
for (int i = 0; i < N; i++) {
result[i] = min + i*step;
}
return result;
}
int main() {
cout << Ry << "\n";
double *S, *H, *I, *eigenvalues;
double alpha, beta;
int i, j, info;
char* uplo = "U"; char* jobz = "V";
I = interval(0.01, 0.01);
alpha = 1.0; beta = 0.0;
S = (double *)mkl_malloc( N*N*sizeof( double ), 64 );
H = (double *)mkl_malloc( N*N*sizeof( double ), 64 );
eigenvalues = (double *)mkl_malloc( N*sizeof( double ), 64 );
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
int index = i*N + j;
if (j < i) {
S[index] = 0.0;
H[index] = 0.0;
}
else {
S[index] = Superposition(I[i], I[j], m);
H[index] = Hamiltonian(I[i], I[j], m);
}
}
}
print_matrix(S, N); cout << "\n";
print_matrix(H, N); cout << "\n" << "\n";
info = LAPACKE_dsygv(LAPACK_ROW_MAJOR, 1, *jobz, *uplo, N,
H, N, S, N, eigenvalues);
//print_matrix(H, N); cout << "\n";
//for (i = 0; i < N; i++) {
// eigenvalues[i] /= Ry;
//}
cout << info << "\n" << "\n";
print_matrix(H, N); cout << "\n";
print_vector(eigenvalues, N);
mkl_free(S);
mkl_free(H);
mkl_free(I);
mkl_free(eigenvalues);
}
*Edit: I used dsygvd as included in MKL, and the same error doesn't occur. However, I get very different results for both functions using the same inputs.
Background Information:
Here is an outline of the algorithm known as forward Monte Carlo for pricing American options which is from the paper, "A Forward Monte Carlo Method for American Options Pricing" by Daniel Wei-Chung Miao and Yung-Hsin Lee.
Question:
My program works correctly when the time steps N = 100 or anything less and when M = 100 or anything less. But when I increase N or M to say 1000 then my program breaks and does not run and I am not sure why.
Here is my code:
#include <iostream>
#include <cmath>
#include <math.h>
#include <limits>
#include <algorithm>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>
#include <vector>
#include <time.h>
using namespace Eigen;
using namespace std;
void FM(double T, double r, double q, double sigma, double S0, double K, int M, int N);
MatrixXd generateGaussianNoise(int M, int N); // Generates Normally distributed random numbers
double Black_Scholes(double T, double K, double S0, double r, double sigma);
double phi(long double x);
VectorXd time_vector(double min, double max, int N);
MatrixXd call_payoff(MatrixXd S, double K);
int main(){
double r = 0.03; // Riskless interest rate
double q = 0.0; // Divident yield
double sigma = 0.15; // Volatility of stock
int T = 1; // Time (expiry)
int N = 100; // Number of time steps
double K = 100; // Strike price
double S0 = 102; // Initial stock price
int M = 1000; // Number of paths // Current issue
FM(T,r,q,sigma,S0,K,M,N);
return 0;
}
MatrixXd generateGaussianNoise(int M, int N){
MatrixXd Z(N,M);
random_device rd;
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;
}
double phi(double x){
return 0.5 * erfc(-x * M_SQRT1_2);
}
double Black_Scholes(double T, double K, double S0, double r, double sigma){
double d_1 = (log(S0/K) + (r+sigma*sigma/2.)*(T))/(sigma*sqrt(T));
double d_2 = (log(S0/K) + (r-sigma*sigma/2.)*(T))/(sigma*sqrt(T));
double C = S0*phi(d_1) - phi(d_2)*K*exp(-r*T);
return C;
}
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 call_payoff(MatrixXd S, double K){
MatrixXd result(S.rows(),S.cols());
for(int i = 0; i < S.rows(); i++){
for(int j = 0; j < S.cols(); j++){
if(S(i,j) - K > 0){
result(i,j) = S(i,j) - K;
}else{
result(i,j) = 0.0;
}
}
}
return result;
}
void FM(double T, double r, double q, double sigma, double S0, double K, int M, int N){
MatrixXd Z = generateGaussianNoise(M,N);
double dt = T/N;
VectorXd t = time_vector(0.0,T,N);
// Generate M paths of stock prices
MatrixXd S(M,N+1);
for(int i = 0; i < M; i++){
S(i,0) = S0;
for(int j = 1; j <= N; j++){
S(i,j) = S(i,j-1)*exp((double) (r - q - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
}
}
//
// If path i is "alive" at time index j - 1 < N, generate the price for time index j, denoted as S = S_ij
// Case for call option:
// If j = N, the option is expired with value V = exp(-rT)(S-K)^+ and path i is finished
// If j < N, calculate S_c = f_C(S)
// If S > S_c, the option is exercised with value V_i = exp(-rT)(S-K)^+ and path i is stopped. Otherwise,
// the option is held and path continues to live to the next step j+1
//
// Case for put option:
// If j = N, the option is expired with value V = exp(-rT)(K-S)^+ and path i is finished
// If j < N, calculate S_p = f_p(S)
// if S < S_p, the option is exercised with value V_i and path i is stopped. Otherwise,
// the option is held and path continues to live to the next step j+1.
// Compute S_c parameters and S_p
double m = 2*r/(pow(sigma,2.0));
double n = 2*(r-q)/(pow(sigma,2.0));
VectorXd k(t.size());
for(int i = 0; i < k.size(); i++){
k(i) = 1.0 - exp((double) -r*(double)(T - t(i))); // Note the t vector (not sure if this is correct)
}
VectorXd Q_2(k.size());
VectorXd Q_1(k.size());
for(int i = 0; i < Q_2.size(); i++){
Q_1(i) = (-1*(n-1) + sqrt((double)(n-1)*(n-1) + (double)4*m/(double)(k(i))))/2.0; // Q_1 < 0
Q_2(i) = (-1*(n-1) + sqrt((double)(n-1)*(n-1) + (double)4*m/(double)(k(i))))/2.0; // Q_2 > 0
}
double d_1 = (log(S0/K) + (r+sigma*sigma/2.)*(T))/(sigma*sqrt(T));
double C_e = Black_Scholes(T, K, S0, r, sigma); // C_e(S) is the European call option price calculated by Black-Scholes
double Delta = exp(-q*T)*phi(d_1);
MatrixXd V(M,N+1);
VectorXd S_c(Q_2.size());
MatrixXd call_fun = call_payoff(S,K);
for(int j = 0; j < N + 1; j++){
for(int i = 0; i < M; i++){
if(j == N){
V(i,j) = exp(-r*T)*call_fun(i,j); //////////////
//cout << "The option is expired with value " << V(i) << " and path " << i << " is finished" << endl;
}
else if(j < N){
S_c(j) = Q_2(j)*(C_e + K)/(Q_2(j) - (1 - Delta));
}
else if (S(i,j) > S_c(j)){
V(i,j) = exp(-r*T)*call_fun(i,j); ///////////////
//cout << "The option is expired with value " << V(i) << " and path " << i << " is finished" << endl;
}
}
}
double Value = 0.0;
for(int i = 0; i < V.rows(); i++){
for(int j = 0; j < V.cols(); j++){
Value += V(i,j);
}
}
Value = 1.0/M * Value;
cout << C_e << endl;
cout << endl;
cout << Value << endl;
}
I am pretty new with C++ so I am not sure how to debug my program when this sort of problem arises. This has happened to me to another algorithm I wrote but when I restarted my computer then it worked fine. Any suggestions are greatly appreciated.
From what the user Incomputable asked I believe this is crashing because of low memory, here are the specifications of my computer:
Update:
Taking the advice from user Daniel Jour, I changed the FM function to void. Following the same sample where I set M = 1000 and leave N = 100 then I get this crash message:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Assertion failed!
Program: C:\Users\Morgan Weiss\workspace\Forward_Monte_Carlo\Debug\Forward_Monte_Carlo.exe
File: c:\mingw\include\c++\6.2.0\eigen\src/Core/DenseCoeffsBase.h, Line 365
Expression: row >= 0 && row < rows() && col >= 0 && col < cols()
Update 2:
I set N = 1000 and M = 1000 and it ran just fine with no issue, so I am not sure why if I set N not equal to M the program will crash... Any ideas?
Looking onto your code the following seems to be quite strange:
MatrixXd call_payoff(MatrixXd S, double K){
MatrixXd result(S.rows(),S.cols()); <-- result size is exact the same as input size
....
}
Then:
VectorXd S_c(Q_2.size()); <---- Vector (one of the dimensions is 1)
MatrixXd call_fun = call_payoff(S,K); <--- Matrix 1xN (or Nx1, I am not sure)
And then:
for(int j = 0; j < N + 1; j++){
for(int i = 0; i < M; i++){
...
V(i,j) = exp(-r*T)*call_fun(i,j); <---- i and j may be significantly bigger than 1
...
}
}
How can I write an "X to the power of k" procedure in C++? (k is a positive integer)
I did the same thing in python, and it was a breeze, but in C++, I don't even know where to begin.
How can I write an "X to the power of k" procedure in C++? (k is a positive integer)
Write a short loop in a function like
int pow(int X, int k) {
int result = 1;
for(int i = 0; i < k; ++i) result *= X;
return result;
}
It's easy to express this in a lambda as well:
auto pow = [] (int X, int k) {
int result = 1;
for(int i = 0; i < k; ++i) result *= X;
return result;
};
cout << pow(5,3);
See a working sample please.
Ummm, maby try this:
#include <iostream>
#include<cmath> //adds math functions: power, square root etc.
using namespace std;
int main(){
int x;
int k;
cin >> x;
cin >> k;
x = pow(x, k);
cout << "\nX to the power of k: " << x << endl << endl;
return 0;
}