Random Number Generator - Histogram Construction (Poisson Distribution and Counting Variables) - c++

This Problem Has Now Been Resolved - Revised Code is Shown Below
I have a problem here which I'm sure will only require a small amount of tweaking the code but I do not seem to have been able to correct the program.
So, basically what I want to do is write a C++ program to construct a histogram with nbin = 20 (number of bins), for the number of counts of a Geiger counter in 10000 intervals of a time interval dt (delta t) = 1s; assuming an average count rate of 5 s^(-1). In order to determine the number of counts in some time interval deltat I use a while statement of the form shown below:
while((t-=tau*log(zscale*double(iran=IM*iran+IC)))<deltat)count++;
As a bit of background to this problem I should mention that the total number of counts is given by n*mu, which is proportional to the total counting time T = n*deltat. Obviously, in this problem n has been chosen to be 10000 and deltat is 1s; giving T = 10000s.
The issue I am having is that the output of my code (which will be shown below) simply gives 10000 "hits" for the element 0 (corresponding to 0 counts in the time deltat) and then, of course, 0 "hits" for every other element of the hist[] array subsequently. Whereas, the output which I am expecting is a Poisson Distribution with the peak "hits" at 5 counts (per second).
Thank you in advance for any help you can offer, and I apologise for my poor explanation of the problem at hand! My code is shown below:
#include <iostream> // Pre-processor directives to include
#include <ctime> //... input/output, time,
#include <fstream> //... file streaming and
#include <cmath> //... mathematical function headers
using namespace std;
int main(void) {
const unsigned IM = 1664525; // Integer constants for
const unsigned IC = 1013904223; //... the RNG algorithm
const double zscale = 1.0/0xFFFFFFFF; // Scaling factor for random double between 0 and 1
const double lambda = 5; // Count rate = 5s^-1
const double tau = 1/lambda; // Average time tau is inverse of count rate
const int deltat = 1; // Time intervals of 1s
const int nbin = 20; // Number of bins in histogram
const int nsteps = 1E4;
clock_t start, end;
int count(0);
double t = 0; // Time variable declaration
unsigned iran = time(0); // Seeds the random-number generator from the system time
int hist[nbin]; // Declare array of size nbin for histogram
// Create output stream and open output file
ofstream rout;
rout.open("geigercounterdata.txt");
// Initialise the hist[] array, each element is given the value of zero
for ( int i = 0 ; i < nbin ; i++ )
hist[i] = 0;
start = clock();
// Construction of histogram using RNG process
for ( int i = 1 ; i <= nsteps ; i++ ) {
t = 0;
count = 0;
while((t -= tau*log(zscale*double(iran=IM*iran+IC))) < deltat)
count++; // Increase count variable by 1
hist[count]++; // Increase element "count" of hist array by 1
}
// Print histogram to console window and save to output file
for ( int i = 0 ; i < nbin ; i++ ) {
cout << i << "\t" << hist[i] << endl;
rout << i << "\t" << hist[i] << endl;
}
end = clock();
cout << "\nTime taken for process completion = "
<< (end - start)/double(CLOCKS_PER_SEC)
<< " seconds.\n";
rout.close();
return 1;
} // End of main() routine

I do not entirely follow you on the mathematics of your while loop; however the problem is indeed in the condition of the while loop. I broke your while loop down as follows:
count--;
do
{
iran=IM * iran + IC; //Time generated pseudo-random
double mulTmp = zscale*iran; //Pseudo-random double 0 to 1
double logTmp = log(mulTmp); //Always negative (see graph of ln(x))
t -= tau*logTmp; //Always more than 10^4 as we substract negative
count++;
} while(t < deltat);
From the code it is apparent that you will always end up with count = 0 when t > 1 and run-time error when t < 1 as you will be corrupting your heap.
Unfortunately, I do not entirely follow you on mathematics behind your calculation and I don't understand why Poisson distribution shall to be expected. With the issue mentioned above, you should either go ahead and solve your problem (and then share your answer for the community) or provide me with more mathematical background and references and I will edit my answer with corrected code. If you decide for the earlier, keep in mind that Poisson distribution's domain is [0, infinity[ so you will need to check whether the vale of count is smaller than 20 (or your nbin for that matter).

Related

C++ Header file not creating random number

My first attempt at creating a header file. The solution is nonsense and nothing more than practice. It receives two numbers from the main file and is supposed to return a random entry from the vector. When I call it from a loop in the main file, it increments by 3 instead of randomly. (Diagnosed by returning the value of getEntry.) The Randomizer code works correctly if I pull it out of the header file and run it directly as a program.
int RandomNumber::Randomizer(int a, int b){
std::vector < int > vecArray{};
int range = (b - a) + 1;
time_t nTime;
srand((unsigned)time(&nTime));
for (int i = a-1; i < b+1; i++) {
vecArray.push_back(i);
}
int getEntry = rand() % range + 1;
int returnValue = vecArray[getEntry];
vecArray.clear();
return returnValue;
}
From what I read, header files should generally not contain function and variable definitions. I suspect Rand, being a function, is the source of the problem.
How, if possible, can I get my header file to create random numbers?
void random(){
double rangeMin = 1;
double rangeMax = 10;
size_t numSamples = 10;
thread_local std::mt19937 mt(std::random_device{}());
std::uniform_real_distribution<double> dist(rangeMin, rangeMax);
for (size_t i = 1; i <= numSamples; ++i) {
std::cout << dist(mt) << std::endl;
}
}
This method will give you the opportunity to generate random numbers, between two numbers this method you have to include random
There are many cases where you will optate to engender a desultory number. There are genuinely two functions you will require to ken about arbitrary number generation. The first is rand(), this function will only return a pseudo desultory number. The way to fine-tune this is to first call the srand() function.
Here is an example:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
int i,j;
srand( (unsigned)time( NULL ) );
for( i = 0; i < 10; i++ ) {
j = rand();
cout <<" Random Number : " << j << endl;
}
return 0;
}
Using srand( (unsigned)time( NULL ) ); Instead of using your own value use NULL for the default setting.
You can also go here for more info.
I hope I answered your question! Have a nice day!
Ted Lyngmo gave me the idea that fixed the problem. Using random appears to work correctly in a header file.
I removed/changed the following:
time_t nTime;
srand((unsigned)time(&nTime));
int getEntry = rand() % range + 1;
and replaced them with:
std::random_device rd;
std::mt19937 gen(rd());
int getEntry = gen() % range + 1;
Issue resolved. Thank you everybody for your suggestions and comments!
As an experiment, I remove the vector and focus on the randomizer `srand(T)`, where `T` is the system time `volatile time_t T = time(NULL)`. We then found that system is NOT changed during the program running (execution simply too fast).
The function `rand()` generates a pesudo-random integer using confluent rnadom generator, basically multiply the seed by another larger unsigned integer and truncated to the finite bits of `seed`. The randomizer `srand(T)` is used to initialize the seed using system time, or any number `srand(12345);` . A seed gives a fixed sequence of random number. Without calling `srand(T)`, the seed is determined by the system initial memory gabage. The seed is then changed in every generating `rand()`.
In your code, you issue randomizer `srand(T)` reset the seed to the system time in every run. But the system time didn't changed, Thus, you are reseting the `seed` to a same number.
Run this test.
#include <cstdlib>
#include <iostream>
#include <ctime>
int Randomizer(int a, int b){
volatile time_t T = time(NULL);
std::cout << "time = " << T << std::endl;
srand(T);
std::cout << "rand() = " << rand() << std::endl;
return rand();
}
int main()
{
int n1 = 1, n2 = 8;
for(int i=0; i<5; ++i)
{
std::cout << Randomizer(n1, n2) << std::endl;
}
}
The seed is reset to the system time, which is not change during execution. Thus It renders the same random number.
$ ./a.exe
time = 1608049336
rand() = 9468
15874
time = 1608049336
rand() = 9468
15874
time = 1608049336
rand() = 9468
15874
time = 1608049336
rand() = 9468
15874
time = 1608049336
rand() = 9468
15874
In order to see the change of system time, we add a pause in the main():
int main()
{
int n1 = 1, n2 = 8;
for(int i=0; i<5; ++i)
{
std::cout << Randomizer(n1, n2) << std::endl;
system("pause");
}
}
We can observe the system time moving on...
$ ./a.exe
time = 1608050805
rand() = 14265
11107
Press any key to continue . . .
time = 1608050809
rand() = 14279
21332
Press any key to continue . . .
time = 1608050815
rand() = 14298
20287
Press any key to continue . . .
Because system time is not much different, the first generation of confluent sequence rand() is also rather closed, but the continue sequence of numbers will be "seemingly" random. The principle for confluent random generator is that once after set the seed don't change it. Until you are working for another series of random set. Therefore, put the srand(T) funtcion just once in the main() or somewhere that executed only once.
int main()
{
srand(time(NULL)); // >>>> just for this once <<<<
int n1 = 1, n2 = 8;
for(int i=0; i<5; ++i)
{
std::cout << Randomizer(n1, n2) << std::endl;
}
}

Why is my C++ code so much slower than R?

I have written the following codes in R and C++ which perform the same algorithm:
a) To simulate the random variable X 500 times. (X has value 0.9 with prob 0.5 and 1.1 with prob 0.5)
b) Multiply these 500 simulated values together to get a value. Save that value in a container
c) Repeat 10000000 times such that the container has 10000000 values
R:
ptm <- proc.time()
steps <- 500
MCsize <- 10000000
a <- rbinom(MCsize,steps,0.5)
b <- rep(500,times=MCsize) - a
result <- rep(1.1,times=MCsize)^a*rep(0.9,times=MCsize)^b
proc.time()-ptm
C++
#include <numeric>
#include <vector>
#include <iostream>
#include <random>
#include <thread>
#include <mutex>
#include <cmath>
#include <algorithm>
#include <chrono>
const size_t MCsize = 10000000;
std::mutex mutex1;
std::mutex mutex2;
unsigned seed_;
std::vector<double> cache;
void generatereturns(size_t steps, int RUNS){
mutex2.lock();
// setting seed
try{
std::mt19937 tmpgenerator(seed_);
seed_ = tmpgenerator();
std::cout << "SEED : " << seed_ << std::endl;
}catch(int exception){
mutex2.unlock();
}
mutex2.unlock();
// Creating generator
std::binomial_distribution<int> distribution(steps,0.5);
std::mt19937 generator(seed_);
for(int i = 0; i!= RUNS; ++i){
double power;
double returns;
power = distribution(generator);
returns = pow(0.9,power) * pow(1.1,(double)steps - power);
std::lock_guard<std::mutex> guard(mutex1);
cache.push_back(returns);
}
}
int main(){
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
size_t steps = 500;
seed_ = 777;
unsigned concurentThreadsSupported = std::max(std::thread::hardware_concurrency(),(unsigned)1);
int remainder = MCsize % concurentThreadsSupported;
std::vector<std::thread> threads;
// starting sub-thread simulations
if(concurentThreadsSupported != 1){
for(int i = 0 ; i != concurentThreadsSupported - 1; ++i){
if(remainder != 0){
threads.push_back(std::thread(generatereturns,steps,MCsize / concurentThreadsSupported + 1));
remainder--;
}else{
threads.push_back(std::thread(generatereturns,steps,MCsize / concurentThreadsSupported));
}
}
}
//starting main thread simulation
if(remainder != 0){
generatereturns(steps, MCsize / concurentThreadsSupported + 1);
remainder--;
}else{
generatereturns(steps, MCsize / concurentThreadsSupported);
}
for (auto& th : threads) th.join();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now() ;
typedef std::chrono::duration<int,std::milli> millisecs_t ;
millisecs_t duration( std::chrono::duration_cast<millisecs_t>(end-start) ) ;
std::cout << "Time elapsed : " << duration.count() << " milliseconds.\n" ;
return 0;
}
I can't understand why my R code is so much faster than my C++ code (3.29s vs 12s) even though I have used four threads in the C++ code? Can anyone enlighten me please? How should I improve my C++ code to make it run faster?
EDIT:
Thanks for all the advice! I reserved capacity for my vectors and reduced the amount of locking in my code. The crucial update in the generatereturns() function is :
std::vector<double> cache(MCsize);
std::vector<double>::iterator currit = cache.begin();
//.....
// Creating generator
std::binomial_distribution<int> distribution(steps,0.5);
std::mt19937 generator(seed_);
std::vector<double> tmpvec(RUNS);
for(int i = 0; i!= RUNS; ++i){
double power;
double returns;
power = distribution(generator);
returns = pow(0.9,power) * pow(1.1,(double)steps - power);
tmpvec[i] = returns;
}
std::lock_guard<std::mutex> guard(mutex1);
std::move(tmpvec.begin(),tmpvec.end(),currit);
currit += RUNS;
Instead of locking every time, I created a temporary vector and then used std::move to shift the elements in that tempvec into cache. Now the elapsed time has reduced to 1.9seconds.
First of all, are you running it in release mode?
Switching from debug to release reduced the running time from ~15s to ~4.5s on my laptop (windows 7, i5 3210M).
Also, reducing the number of threads to 2 instead of 4 in my case (I just have 2 cores but with hyperthreading) further reduced the running time to ~2.4s.
Changing the variable power to int (as jimifiki also suggested) also offered a slight boost, reducing the time to ~2.3s.
I really enjoyed your question and I tried the code at home. I tried to change the random number generator, my implementation of std::binomial_distribution requires on average about 9.6 calls of generator().
I know the question is more about comparing R with C++ performances, but since you ask "How should I improve my C++ code to make it run faster?" I insist with pow optimization. You can easily avoid one half of the call by precomputing either 0.9^steps or 1.1^steps before the for loop. This makes your code run a bit faster:
double power1 = pow(0.9,steps);
double ratio = 1.1/0.9;
for(int i = 0; i!= RUNS; ++i){
...
returns = myF1 * pow(myF2, (double)power);
Analogously you can improve the R code:
...
ratio <-1.1/0.9
pow1 = 0.9^steps
result <- rep(ratio,times=MCsize)^rep(pow1,times=MCsize)
...
Probably doesn't help you that much, but
start by using pow(double,int) when your exponent is an int.
int power;
returns = pow(0.9,power) * pow(1.1,(int)steps - power);
Can you see any improvement?

Sieve of Eratosthenes algorithm not working for large limits

I have programmed a sieve of Eratosthenes algorithm in C++, and it works fine for smaller numbers that I have tested it with. However, when I use large numbers, i.e. 2 000 000 as the upper limit, the program begins giving wrong answers. Can anyone clarify why?
Your help is appreciated.
#include <iostream>
#include <time.h>
using namespace std;
int main() {
clock_t a, b;
a = clock();
int n = 0, k = 2000000; // n = Sum of primes, k = Upper limit
bool r[k - 2]; // r = All numbers below k and above 1 (if true, it has been marked as a non-prime)
for(int i = 0; i < k - 2; i++) // Check all numbers
if(!r[i]) { // If it hasn't been marked as a non-prime yet ...
n += i + 2; // Add the prime to the total sum (+2 because of the shift - index 0 is 2, index 1 is 3, etc.)
for(int j = 2 * i + 2; j < k - 2; j += i + 2) // Go through all multiples of the prime under the limit
r[j] = true; // Mark the multiple as a non-prime
}
b = clock();
cout << "Final Result: " << n << endl;
cout << b - a << "ms runtime achieved." << endl;
return 0;
}
EDIT: I just did some debugging and found that it works with the limit at around 400. At 500, however, it is off - it should be 21536, but is 21499
EDIT 2: Ah, I found two errors and those seem to have fixed the problem.
The first was found by others who answered, and is that n is overflowing - upon being made a long long data type, it has begun working.
The second, rather facepalm-worthy mistake, was that the booleans in r had to be initialized. After running loop before checking for primes to make all of them false, the right answer is gotten. Does anyone know why this occured?
You simply get an integer overflow. The C++ type int is has a limited range (on a 32 bit System usually from -(2^32) / 2 to 2^32 / 2 - 1, that is the usual maximum is 2147483647 (The specific maximum on your setup can be found out by #including the <limits> header and evaluating std::numeric_limits<int>::max(). Even when k is smaller than the maximum, your code will sooner or later cause an overflow in the expressions n += i + 2 or int j = 2 * i + 2.
You will have to choose a better (read: more appropriate) type like unsigned which does not support negative numbers and can thus can represent numbers twice as large as int. You can also try unsigned long or even unsigned long long.
Also note that variable length arrays (VLAs; that's what bool r[k - 2] is) are not standard C++. You might want to use std::vector instead. You also did not initialize the array to false (std::vector would do this automatically), which could also be the problem, especially if you say that it does not work even at k=500.
In C++, you should also use <ctime> instead of <time.h> (then clock_t and andclock()are defined in thestdnamespace, but since you areusing namespace std`, this won't make a difference for you), but this is more or less a matter of style.
I found a working example in my "code archive". Although it is not based on yours, you might find it useful:
#include <vector>
#include <iostream>
int main()
{
typedef std::vector<bool> marked_t;
typedef marked_t::size_type number_t; // The type used for indexing marked_t.
const number_t max = 500;
static const number_t iDif = 2; // Account for the numbers 1 and 2.
marked_t marked(max - iDif);
number_t i = iDif;
while (i*i <= max) {
while (marked[i - iDif] == true)
++i;
for (number_t fac = iDif; i * fac < max; ++fac)
marked[i * fac - iDif] = true;
++i;
}
for (marked_t::size_type i = 0; i < marked.size(); ++i) {
if (!marked[i])
std::cout << i + iDif << ',';
}
}

Not Finding Times of Prime Generation / Limited Generation

This program is a c++ program that finds primes using the sieve of eratosthenes to calculate primes. It is then supposed to store the time it takes to do this, and reperform the calculation 100 times, storing the times each time. There are two things that I need help with in this program:
Firstly, I can only test numbers up to 480million I would like to get higher than that.
Secondly, when i time the program it only gets the first timing and then prints zeros as the time. This is not correct and I don't know what the problem with the clock is. -Thanks for the help
Here is my code.
#include <iostream>
#include <ctime>
using namespace std;
int main ()
{
int long MAX_NUM = 1000000;
int long MAX_NUM_ARRAY = MAX_NUM+1;
int long sieve_prime = 2;
int time_store = 0;
while (time_store<=100)
{
int long sieve_prime_constant = 0;
int *Num_Array = new int[MAX_NUM_ARRAY];
std::fill_n(Num_Array, MAX_NUM_ARRAY, 3);
Num_Array [0] = 1;
Num_Array [1] = 1;
clock_t time1,time2;
time1 = clock();
while (sieve_prime_constant <= MAX_NUM_ARRAY)
{
if (Num_Array [sieve_prime_constant] == 1)
{
sieve_prime_constant++;
}
else
{
Num_Array [sieve_prime_constant] = 0;
sieve_prime=sieve_prime_constant;
while (sieve_prime<=MAX_NUM_ARRAY - sieve_prime_constant)
{
sieve_prime = sieve_prime + sieve_prime_constant;
Num_Array [sieve_prime] = 1;
}
if (sieve_prime_constant <= MAX_NUM_ARRAY)
{
sieve_prime_constant++;
sieve_prime = sieve_prime_constant;
}
}
}
time2 = clock();
delete[] Num_Array;
cout << "It took " << (float(time2 - time1)/(CLOCKS_PER_SEC)) << " seconds to execute this loop." << endl;
cout << "This loop has already been executed " << time_store << " times." << endl;
float Time_Array[100];
Time_Array[time_store] = (float(time2 - time1)/(CLOCKS_PER_SEC));
time_store++;
}
return 0;
}
I think the problem is that you don't reset the starting prime:
int long sieve_prime = 2;
Currently that is outside your loop. On second thoughts... That's not the problem. Has this code been edited to incorporate the suggestions in Mats Petersson's answer? I just corrected the bad indentation.
Anyway, for the other part of your question, I suggest you use char instead of int for Num_Array. There is no use using int to store a boolean. By using char you should be able to store about 4 times as many values in the same amount of memory (assuming your int is 32-bit, which it probably is).
That means you could handle numbers up to almost 2 billion. Since you are using signed long as your type instead of unsigned long, that is approaching the numeric limits for your calculation anyway.
If you want to use even less memory, you could use std::bitset, but be aware that performance could be significantly impaired.
By the way, you should declare your timing array at the top of main:
float Time_Array[100];
Putting it inside the loop just before it is used is a bit whack.
Oh, and just in case you're interested, here is my own implementation of the sieve which, personally, I find easier to read than yours....
std::vector<char> isPrime( N, 1 );
for( int i = 2; i < N; i++ )
{
if( !isPrime[i] ) continue;
for( int x = i*2; x < N; x+=i ) isPrime[x] = 0;
}
This section of code is supposed to go inside your loop:
int *Num_Array = new int[MAX_NUM_ARRAY];
std::fill_n(Num_Array, MAX_NUM_ARRAY, 3);
Num_Array [0] = 1;
Num_Array [1] = 1;
Edit: and this one needs be in the loop too:
int long sieve_prime_constant = 0;
When I run this on my machine, it takes 0.2s per loop. If I add two zeros to the MAX_NUM_ARRAY, it takes 4.6 seconds per iteration (up to the 20th loop, I got bored waiting longer than 1.5 minute)
Agree with the earlier comments. If you really want to juice things up you don't store an array of all possible values (as int, or char), but only keep the primes. Then you test each subsequent number for divisibility through all primes found so far. Now you are only limited by the number of primes you can store. Of course, that's not really the algorithm you wanted to implement any more... but since it would be using integer division, it's quite fast. Something like this:
int myPrimes[MAX_PRIME];
int pCount, ii, jj;
ii = 3;
myPrimes[0]=2;
for(pCount=1; pCount<MAX_PRIME; pCount++) {
for(jj = 1; jj<pCount; jj++) {
if (ii%myPrimes[jj]==0) {
// not a prime
ii+=2; // never test even numbers...
jj = 1; // start loop again
}
}
myPrimes[pCount]=ii;
}
Not really what you were asking for, but maybe it is useful.

Numerical solution to differential equations in C++, path to take?

Edit
I am now using odeint. It is fairly simple to use and less memory hungry than my brute force algorithm implementation.
Check my questions here-->http://stackoverflow.com/questions/12060111/using-odeint-function-definition
and here-->http://stackoverflow.com/questions/12150160/odeint-streaming-observer-and-related-questions
I am trying to implement a numerical method (Explicit Euler) to solve a set of three coupled differential equations. I have worked with C before, but that was a very long time ago (effectively forgotten everything). I have a pretty good idea on what I want my program to do and also have a rough algorithm.
I am interested in using C++ for this task (picked up Stroustroup's Programming: Principles and Practice using C++). My question is, should I go with arrays or vectors? Vectors seem easier to handle, but I was unable to find how you can make a function return a vector? Is it possible for a function to return more than one vector? At this point, I am familiarizing myself with the C++ syntax.
I basically need my function to return many arrays. I realize that it is not possible in C++, so I can also work with some nested structure such as {{arr1},{arr2},{arr3}..}. Please bear with me as I am a noob and come from programming in Mathematica.
Thanks!
If you want to use C++ for integrating ordinary differential equations and you don't want to reinvent the wheel use odeint. This lib is on its way of becoming the de facto standard for solving ODEs in C++. The code is very flexible and highly optimized and can compete with any handcrafted C-code (and Fortran anyway).
Commenting on you question on returning vectors or arrays: Functions can return vectors and arrays if the are wrapped in a class (like std::array). But this is not recommended, since you make many unnecessary copies (incl. calling the constructors and destructors every time).
I assume you want to put your function equation into a c++ function and let it return the resulting vector. For this task it's much better if you pass a reference to a vector to the function and let the function fill this vector. This is also the way how odeint has implemented this.
This link might help you, but for ordinary differential equations :
http://www.codeproject.com/KB/recipes/odeint.aspx
To make the program do what you wan you could take a look at this code, It may be get you started.
I found it very useful, and tested it against mathematica solution, and it is ok.
for more information go here
/*
A simple code for option valuation using the explicit forward Euler method
for the class Derivative Securities, fall 2010
http://www.math.nyu.edu/faculty/goodman/teaching/DerivSec10/index.html
Written for this purpose by Jonathan Goodman, instructor.
Assignment 8
*/
#include <iostream>
#include <fstream>
#include <math.h>
#define NSPOTS 100 /* The number of spot prices computed */
/* A program to compute a simple binomial tree price for a European style put option */
using namespace std;
// The pricer, main is at the bottom of the file
void FE( // Solve a pricing PDE using the forward Euler method
double T, double sigma, double r, double K, // The standard option parameters
double Smin, double Smax, // The min and max prices to return
int nPrices, // The number of prices to compute between Smin and Smax,
// Determines the accuracy and the cost of the computation
double prices[], // An array of option prices to be returned.
double intrinsic[], // The intrinsic value at the same prices
double spots[], // The corresponding spot prices, computed here for convenience.
// Both arrays must be allocated in the calling procedure
double *SEarly ) { // The early exercise boundary
// Setup for the computation, compute computational parameters and allocate the memory
double xMin = log(Smin); // Work in the log variable
double xMax = log(Smax);
double dx = ( xMax - xMin )/ ( (double( nPrices - 1 ) ) ); // The number of gaps is one less than the number of prices
double CFL = .8; // The time step ratio
double dt = CFL*dx*dx/sigma; // The forward Euler time step size, to be adjusted slightly
int nTimeSteps = (int) (T/dt); // The number of time steps, rounded down to the nearest integer
nTimeSteps++; // Now rounded up
dt = T / ( (double) nTimeSteps ); // Adjust the time step to land precisely at T in n steps.
int nx = nPrices + 2*nTimeSteps; // The number of prices at the final time, growing by 2 ...
// ... each time step
xMin = xMin - nTimeSteps*dx; // The x values now start here
double *fOld; // The values of the pricing function at the old time
fOld = new double [nx]; // Allocated using old style C++ for simplicity
double *fNew; // The values of the pricing function at the new time
fNew = new double [nx];
double *V; // The intrinsic value = the final condition
V = new double [nx];
// Get the final conditions and the early exercise values
double x; // The log variable
double S; // A stock price = exp(x)
int j;
for ( j = 0; j < nx; j++ ) {
x = xMin + j*dx;
S = exp(x);
if ( S < K ) V[j] = K-S; // A put struck at K
else V[j] = 0;
fOld[j] = V[j]; // The final condition is the intrinsic value
}
// The time stepping loop
double alpha, beta, gamma; // The coefficients in the finite difference formula
alpha = beta = gamma = .333333333333; // XXXXXXXXXXXXXXXXXXXXXXXXXXX
int jMin = 1; // The smallest and largest j ...
int jMax = nx - 1; // ... for which f is updated. Skip 1 on each end the first time.
int jEarly ; // The last index of early exercise
for ( int k = nTimeSteps; k > 0; k-- ) { // This is, after all, a backward equation
jEarly = 0; // re-initialize the early exercise pointer
for ( j = jMin; j < jMax; j++ ) { // Compute the new values
x = xMin + j*dx; // In case the coefficients depend on S
S = exp(x);
fNew[j] = alpha*fOld[j-1] + beta*fOld[j] + gamma*fOld[j+1]; // Compute the continuation value
if ( fNew[j] < V[j] ) {
fNew[j] = V[j]; // Take the max with the intrinsic value
jEarly = j; // and record the largest early exercise index
}
}
for ( j = jMin; j < jMax; j++ ) // Copy the new values back into the old array
fOld[j] = fNew[j];
jMin++; // Move the boundaries in by one
jMax--;
}
// Copy the computed solution into the desired place
jMin--; // The last decrement and increment were mistakes
jMax++;
int i = 0; // The index into the output array
for ( j = jMin; j < jMax; j++ ) { // Now the range of j should match the output array
x = xMin + j*dx;
S = exp(x);
prices[i] = fOld[j];
intrinsic[i] = V[j];
spots[i++] = S; // Increment i after all copy operations
}
double xEarly = xMin + jEarly*dx;
*SEarly = exp(xEarly); // Pass back the computed early exercise boundary
delete fNew; // Be a good citizen and free the memory when you're done.
delete fOld;
delete V;
return;
}
int main() {
cout << "Hello " << endl;
ofstream csvFile; // The file for output, will be csv format for Excel.
csvFile.open ("PutPrice.csv");
double sigma = .3;
double r = .003;
double T = .5;
double K = 100;
double Smin = 60;
double Smax = 180;
double prices[NSPOTS];
double intrinsic[NSPOTS];
double spots[ NSPOTS];
double SEarly;
FE( T, sigma, r, K, Smin, Smax, NSPOTS, prices, intrinsic, spots, &SEarly );
for ( int j = 0; j < NSPOTS; j++ ) { // Write out the spot prices for plotting
csvFile << spots[j];
if ( j < (NSPOTS - 1) ) csvFile << ", "; // Don't put a comma after the last value
}
csvFile << endl;
for ( int j = 0; j < NSPOTS; j++ ) { // Write out the intrinsic prices for plotting
csvFile << intrinsic[j];
if ( j < (NSPOTS - 1) ) csvFile << ", "; // Don't put a comma after the last value
}
csvFile << endl;
for ( int j = 0; j < NSPOTS; j++ ) { // Write out the computed option prices
csvFile << prices[j];
if ( j < (NSPOTS - 1) ) csvFile << ", ";
}
csvFile << endl;
csvFile << "Critical price," << SEarly << endl;
csvFile << "T ," << T << endl;
csvFile << "r ," << r << endl;
csvFile << "sigma ," << sigma << endl;
csvFile << "strike ," << K << endl;
return 0 ;
}