Numerical Integration with Trapezoidal rule c++ - c++

I'm attempting to implement a Trapezoidal rule that utilizes previous function evaluations in order to avoid redundant computation. Two things: a) computed results are not converging and I'm a little unsure of why. I'll post of the mathematics behind why I think that the algorithm should yield convergence if it's wanted, and b) the do while loop is terminating at n=8 and I've been unable to figure that one out as well; it should be running until n>128? (n is the number of subintervals) My code is below. Thanks in advance!
void NestedTrap(int n) //Trapezoidal with reuse of function evaluations
{
double a,b; //interval end points
double x[n+1]; //equally spaced nodes
double c[n]; //midpoints
double T; //Initial integral evaluation
double T2; //Evaluation with reuse of previous function evaluations
double h, h2; //step sizes for T and T2
double temp1, temp2;
std::cout <<"Enter interval end points (lesser first; enter 999 for pi & 999.2 for pi/2 & 999.4 for pi/4): ";
std::cin >> a >> b;
if (b == 999)
{
b = M_PI;
}
if (a == 999)
{
a = M_PI;
}
if (b == 999.4)
{
b = M_PI/4;
}
if (a == 999.4)
{
a = M_PI/4;
}
if (b == 999.2)
{
b = M_PI/2;
}
if (a == 999.2)
{
a = M_PI/2;
}
h = (b-a)/n;
T = 0;
temp1 = 0;
temp2 = 0;
for (int i=0; i<=n; i++)
{
x[i] = 0;
}
for (int i=0; i<n; i++)
{
x[i+1] = x[i] + h;
}
for (int i=1; i<n; i++)
{
temp1 += I1(x[i]);
}
T = (h/2)*exp(x[0]) + (h/2)*exp(x[n]) + (h*temp1);
std::cout << "T_" << n <<": " << T << std::endl;
do
{
temp2 = 0;
n = 2*n;
h2 = (b-a)/(n);
for (int i=0; i<n; i++)
{
c[i] = 0;
}
for (int i=1; i<=n; i++)
{
c[i] = a + h2*(i-0.5);
//std::cout << c[i] << std::endl;
}
for (int i=0; i<n; i++)
{
temp2 += exp(c[i]);
}
T2 = (T/2) + h2*temp2;
std::cout << "T_" << n <<": " << T2 << std::endl;
T = T2;
} while (n <= 128);
}

You create arrays of size n here
double x[n+1]; //equally spaced nodes
double c[n]; //midpoints
(note that this is not valid c++)
then you increase n here:
n = 2*n;
then you write past the end of your array here:
for (int i=0; i<n; i++)
{
c[i] = 0;
}
which causes undefined behaviour (probably overwrites some other variables)

Related

Array elements changing values if I comment out cout statement. Is this memory leak related?

I'm working on a KNN algorithm with 2D arrays. It worked great when I first had the nodes be simple X and Y coordinates, but when I changed it to 2D arrays and reworked some things, I run into a funny issue.
#include <iostream>
#include <math.h>
using namespace std;
//A node
struct Node
{
int groupValue;
int col = 16; //We only have to update these to reflect the bitmap dimensions
int row = 16;
int bitmap[16][16];
float distance = -1;
//distance is the distance this node is from another
//Overloading this operator to make swapping them with insertion sort easier
Node& operator =(const Node& n)
{
for(int a = 0; a < row; a++)
{
for(int b = 0; b < col; b++)
{
bitmap[a][b] = n.bitmap[a][b];
}
}
distance = n.distance;
groupValue = n.groupValue;
return *this;
}
};
void printNode(Node n)
{
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
cout << n.bitmap[a][b] << ".";
cout << endl;
}
}
struct Group
{
int frequency = 0;
int id;
};
void insertionSort(Node arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = arr[i].distance;
j = i - 1;
while (j >= 0 && arr[j].distance > key)
{
Node temp = arr[j+1];
arr[j + 1] = arr[j];
arr[j] = temp;
j = j - 1;
}
arr[j + 1].distance = key;
}
}
//Takes two bitmaps and find the distance between each pixel
//using the formula d=sqrt(sum((pixel_1-pixel_2)^2))
float bitmapDistance(Node n1, Node n2)
{
Node differences; //Node's bitmap data will be the differences
//squared of each pixel from n1 and n2.
float diff;
for(int a = 0; a < n1.row; a++)
{
for(int b = 0; b < n1.col; b++)
{
diff = n1.bitmap[a][b] - n2.bitmap[a][b];
differences.bitmap[a][b] = diff * diff; //Squared difference
}
}
//Now we need to sum up the squared differences that we stored earlier
float sum;
for(int a = 0; a < n1.row; a++)
{
for(int b = 0; b < n1.col; b++)
{
sum += differences.bitmap[a][b];
}
}
//Now just take the square root of the sum and return it
if(sum < 0.01) //To fix some weird rounding issues I added this. 0.01 is arbitrary.
return 0;
return sqrt(sum);
}
/*
*Classify the node using KNN algorithm
*Multiple groups can be used, and we count how many neighbors
*belong to each group.
*n is the total amount of nodes
*k is the number of nearby neighbors
*/
int classify(Node arr[], int n, int k, Node node)
{
//Two switches for sampling, recorded as binary (0-3)
Group g0;
g0.id = 0;
Group g1;
g1.id = 1;
Group g2;
g2.id = 2;
Group g3;
g3.id = 3;
Group groupFrequency[4] = {g0, g1, g2, g3};
//For each neighbor of the given node (node) we use the distance formula
//and set it's distance member variable to this measurement
for(int a = 0; a < n; a++)
{
arr[a].distance = bitmapDistance(node, arr[a]);
//cout << arr[a].distance << ","; //<===============PROBLEM AREA===============
}
cout << endl << "----------" << endl;
insertionSort(arr, n-1);
for(int a = 0; a < n; a++)
cout << arr[a].distance << ",";
cout << endl << "----------" << endl;
//Look at all the nearest neighbors and see which group they belong to
//Increase a counter for each group the neighbor belongs to
for(int i = 0; i < k; i++)
{
if(arr[i].groupValue == 0)
groupFrequency[0].frequency++;
else if(arr[i].groupValue == 1)
groupFrequency[1].frequency++;
else if(arr[i].groupValue == 2)
groupFrequency[2].frequency++;
else if(arr[i].groupValue == 3)
groupFrequency[3].frequency++;
}
cout << "Neighboring group frequencies:" << endl;
cout << "Group Zero: " << groupFrequency[0].frequency << endl;
cout << "Group One: " << groupFrequency[1].frequency << endl;
cout << "Group Two: " << groupFrequency[2].frequency << endl;
cout << "Group Three: " << groupFrequency[3].frequency << endl;
cout << "-------------------------------------------------" << endl;
//Now we just need to look at the most common frequency and classify our node
int highestFrequency = 0;
int groupNumber = -1; //If -1 is returned, something went wrong.
for(int a = 0; a < 4; a++)
{
if(groupFrequency[a].frequency >= highestFrequency)
{
highestFrequency = groupFrequency[a].frequency;
groupNumber = groupFrequency[a].id;
}
}
return groupNumber;
}
//This stuff is just setup for testing purposes. Could this be the issue's origin?
int main()
{
Node nodeArray[200];
for(int c = 0; c < 100; c++)
{
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
{
nodeArray[c].groupValue = 0;
nodeArray[c].bitmap[a][b] = rand()%10;
}
}
}
for(int c = 100; c < 200; c++)
{
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
{
nodeArray[c].groupValue = 1;
nodeArray[c].bitmap[a][b] = 50;//rand()%10+50;
}
}
}
Node testNode;
for(int a = 0; a < 16; a++)
{
for(int b = 0; b < 16; b++)
{
testNode.bitmap[a][b] = 50;//rand()%10+50;
}
}
int num = classify(nodeArray, 200, 189, testNode);
cout << "Test node has a group classification of: " << num << endl << endl;
printNode(testNode);
cout << endl << "last node in array:" << endl;
printNode(nodeArray[199]);
cout << endl << bitmapDistance(testNode, nodeArray[199]) << endl << "first node in array:" << endl;
printNode(nodeArray[0]);
cout << bitmapDistance(testNode, nodeArray[0]);
}
The problem specifically is on line 124, in the classify() function in the for loop
for(int a = 0; a < n; a++)
{
arr[a].distance = bitmapDistance(node, arr[a]);
//cout << arr[a].distance << ","; //<====PROBLEM AREA
}
This loop is responsible for calculating the distance each node is from the sample/test node. The "arr" array is then sorted a couple of lines later via insertion sort.
If I have the for loop print out the distance values, everything works perfectly fine. I can see that all the data is properly there.
However, if I comment it out, and only print the sorted data, everything is wrong (the data does not mess up if I comment out the print statements for the sorted data, strangely enough. It's just this one line that breaks everything).
I have attached images depicting the differences between the commented line (wrong) and the uncommented line (correct) running to better show what issues I'm dealing with.
Basically, the data will lose decimal precision, have seemingly random values, and any zero value will be non-existent if I comment out this specific line.
(I know the K value should be low, but I'm using high numbers for testing right now)
Some of the output when I don't comment out the line
Some of the output when I do comment out the line
As you can see, when I comment out the line, all the sorted distance values become garbage.
What can I do to fix this?

Cannot get jacobi converted from gauss seidel in C++

I have coded up a gauss seidel method that works just fine but i cannot seem to figure out how to convert that to jacobi... I know it should be easy so i must be missing something simple. For the assignment i had to make my own vector and matrix classes so that is why Vector is capital and called differently. Here is my working gauss seidel code:
else if (mode == 3) {
Vector temp;
temp.allocateData(b.numElems());
Vector old = temp;
Vector sum;
double f = 50;
int y = 4;
double tol = 1e-12;
double error = 10;
int max = 999999;
int count = 0;
while ( error > tol && max > count) {
for (int i = 0; i < row_; i++) {
temp.setVal(i, b.getVal(i) / M[i][i]);
for (int j = 0; j < col_; j++) {
if (j == i) {
continue;
}
temp.setVal(i, temp.getVal(i) - ((M[i][j] / M[i][i]) * temp.getVal(j)));
old.setVal(j, temp.getVal(i));
}
cout<<"x"<< i + 1 << "="<< temp.getVal(i) <<" \n";
error = abs(temp.getVal(i)-old.getVal(i))/abs(temp.getVal(i));
old = temp;
}
cout << "\n";
count++;
}
}
and here is my attempt at jacobi:
else if (mode == 2) {
Vector temp;
temp.allocateData(b.numElems());
Vector old = temp;
Vector sum;
double f = 50;
int y = 4;
double tol = 1e-12;
double error = 10;
int max = 999999;
int count = 0;
while ( error > tol && max > count) {
old.allocateData(b.numElems());
for (int i = 0; i < row_; i++) {
old.setVal(i, temp.getVal(i));
temp.setVal(i, b.getVal(i) / M[i][i]);
for (int j = 0; j < col_; j++) {
if (j == i) {
continue;
}
temp.setVal(i, temp.getVal(i) - ((M[i][j] / M[i][i]) * old.getVal(j)));
}
cout<<"x"<< i + 1 << "="<< temp.getVal(i) <<" \n";
error = abs(temp.getVal(i)-old.getVal(i))/abs(temp.getVal(i));
}
cout << "\n";
count++;
}
}
thanks everyone ahead of time for the help!!!

Showing garbage values when adding two matrix using operator overloading

Please help me as I am new to programming and I have made this program and it looks fine to me but I am getting garbage values instead of sum of two matrix.I have applied the concept of operator overloading to find the sum of two matrices but I am getting garbage values again and again?Please help me that where is the problem?Thanks.Any help is completely appreciated
#include<iostream>
#include<string>
using namespace std;
class Matrix {
private:
int matrix[2][2];
public:
Matrix operator + (Matrix Sum)
{
Matrix sum[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
sum[i][j].matrix[i][j] = matrix[i][j] + Sum.matrix[i][j];
return(sum[i][j]);
}
}
}
void setMatrix(int m[][2])
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
matrix[i][j] = m[i][j];
}
}
}
void Display()
{
cout << "\n\nThe matrix finally equals: ";
for (int i = 0; i < 2; i++)
{
cout << " ";
for (int j = 0; j < 2; j++)
{
cout<<matrix[i][j];
if (j == 2 - 1)
cout << endl;
}
}
}
};
int main()
{
Matrix m1, m2,sum;
const int size=2;
int matrix1[size][size];
int matrix2[size][size];
cout << "Enter the values of matrix 1 (2 X 2)\n\n";
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cin >> matrix1[i][j];
}
}
cout << "Enter the values of matrix 2 (2 X 2)\n\n";
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cin >> matrix2[i][j];
}
}
cout <<"\n\nSetting the values now\n\n";
m1.setMatrix(matrix1);
m2.setMatrix(matrix2);
sum = m1 + m2;
cout << "\n\nMatrix 1 (2 X 2) is : ";
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
cout << matrix1[i][j] << " ";
if (j == size - 1)
cout << endl;
}
}
cout << "\n\nMatrix 2 (2 X 2) is : ";
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
cout << matrix2[i][j] << " ";
if (j == size - 1)
cout << endl;
}
}
cout << "\n\nSum of two matrices is equal to (2 X 2) is : ";
sum.Display();
return 0;
}
Let's take a close look at you operator+, there are two major errors:
Matrix sum[2][2]; is an array of matrices, but you want to return only a single Matrix, not multiple. Also the name is bad, because you already have a parameter with a similiar name. And yes, C++ is case sensitive, but such similiar names are problematic for human readers ;).
Look where the return is. It will return during the first iteration, e.g.
sum[i][j].matrix[i][j] = matrix[i][j] + Sum.matrix[i][j];
will be called just once, with i and j being zero. Thus it sets only one entry and returns immediately afterwards (leaving the other 3 values uninitialized). That's where the garbage values come from, technically it's undefined behaviour.
Here is what the function should look like, but please don't just copy-paste, but take some time to understand it.
Matrix operator + (Matrix rhs) // One of the two names needed to change.
{
Matrix sum; //only one value with a proper name
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
// better be explicit and use this, imo
sum.matrix[i][j] = this->matrix[i][j] + rhs.matrix[i][j];
}
}
return sum; // return only after all the calculations.
}

Is this test tautological?

Given some
double x;
what is the difference between
if((x>0 || (x<=0)))
and if(true)? Is there any difference? I think they are equivalent, but it seems it's not the case? Anybody knows why?
Ok, I am new to cpp and I am sorry for this question. But I truly need to solve this problem
double sigmaX = 0.1;
double sigmaY = 0.1;
SimPFilter::SimPFilter() {
totalParticles = 100;
nFilters = 2;
gsl_rng_env_setup();
rng = gsl_rng_alloc(gsl_rng_mt19937);
gsl_rng_set(rng, time(NULL));
}
SimPFilter::~SimPFilter() {
}
void SimPFilter::initParticles(double initX, gsl_rng* rng){
for (int i=0; i < totalParticles; i++) {
particles[i].xp = particles[i].x = 0.5 + gsl_ran_gaussian(rng, sigmaX*sigmaX);
if(i > totalParticles/2)
particles[i].xp = particles[i].x = -0.5 + gsl_ran_gaussian(rng, sigmaX*sigmaX);
particles[i].wNormalized = 1/(totalParticles/nFilters);
int j = (int)i/(totalParticles/nFilters);
particles[i].id = j;
filters[j].nParticles = (totalParticles/nFilters);
particles[i].w = particles[i].wp = particles[i].wNormalized = 1/totalParticles;
}
for(int i =0; i<nFilters; i++){
filters[i].weight = filters[i].weightPrev = 1.0/nFilters;
}
}
void SimPFilter::transition(gsl_rng* rng){
for (int i=0; i < totalParticles; i++) {
double temp = particles[i].x;
particles[i].xp = temp;
particles[i].x += gsl_ran_gaussian(rng, sigmaX*sigmaX); //the centre of each region
}
}
double SimPFilter::measure_prob(particle *p, double obser_y, gsl_rng* rng){
double x = p->x;
//cout << "x value is " << x << endl;
double prob = gsl_ran_gaussian_pdf (obser_y - (x*x), sigmaY);
//cout << "probability " << prob << endl;
std::cout << std::boolalpha;
//cout << (x>0 || (x<=0)) << endl;
if(true){
//cout << "probability2 " << prob << endl;
return prob;
}
return prob;
}
void SimPFilter::updateWeight(double obser_y, gsl_rng* rng){
for (int i=0; i < totalParticles; i++) {
double temp = particles[i].w;
particles[i].wp = particles[i].w;
particles[i].w = measure_prob(&particles[i], obser_y, rng);
}
//normalized particle weight
double eachFilterSum[nFilters];
for(int i=0; i < totalParticles; i++){
int id = particles[i].id;
eachFilterSum[id] += particles[i].w;
}
for(int i=0; i < totalParticles; i++){
particles[i].wNormalized = particles[i].w / eachFilterSum[particles[i].id];
}
//update each filter's weight
double eachFilterW[nFilters];
for(int i=0; i< totalParticles; i++){
//cout << "prticle i's weight1 "<<particles[i].w << endl;
int id = particles[i].id;
eachFilterW[id] += particles[i].wNormalized;
}
double sigmaweight =0; // simga pi n t-1 * wnt
for(int j=0; j<nFilters; j++){
sigmaweight += filters[j].weightPrev * eachFilterW[j];
}
for(int j=0; j<nFilters; j++){
double temp = filters[j].weight;
filters[j].weight = filters[j].weightPrev * eachFilterW[j] / sigmaweight;
filters[j].weightPrev = temp;
}
}
void SimPFilter::resample(gsl_rng* rng){
particle * newParticles;
newParticles = (particle*) malloc(totalParticles * sizeof(particle));
int index =(int)gsl_rng_uniform (rng)* totalParticles;
double beta = 0.0;
double maxWeight =0;
for (int i=0; i < totalParticles; i++) {
maxWeight = max(maxWeight, particles[i].wNormalized* filters[particles[i].id].weight);
}
for(int j=0; j < totalParticles; j++){
beta += (rng, 0, 2*maxWeight);
while(beta > particles[index].wNormalized * (filters[particles[index].id].weight)){
beta -= particles[index].wNormalized * (filters[particles[index].id].weight);
index = (index+1) % totalParticles;
}
newParticles[j] = particles[index];
}
for(int i=0; i<totalParticles; i++){
particles[i] = newParticles[i];
particles[i].w = particles[i].wNormalized = particles[i].wp =1/filters[particles[i].id].nParticles;
}
//update each filter particles number
vector<int> countP;
for(int i=0; i<nFilters; i++){
countP.push_back(0);
}
for(int i=0; i< totalParticles; i++){
countP.at(particles[i].id)++;
}
for(int i=0; i< nFilters; i++){
filters[i].nParticles = countP.at(i);
}
for(int i=0; i< nFilters;i++)
cout << "n particle value is " << filters[i].nParticles << endl;
free(newParticles);
}
`
in the measure_prob function, I find out, if(true) or if(x>=0 || x<0) give different result. When if(true) it could track two objects, but when I use if(x>=0 || x<0) it will converge to one object quickly. I am really confused...
Example :
double x = log2(-1); // Evaluates to NAN
if (x>0 || (x<=0)) {
printf("True\n");
}
else {
printf("False\n");
}
OUTPUT
False
Hence they are not equivalent. NAN stands for Not A Number so it is neither greater than 0 nor is it equal to or less than zero cause it is not a number.

New set of values for testcases using srand() in c++

I am trying to create some test cases for my 'minimum dot product' problem. I want 10 test cases , each generating different set of values for both vector a and b.
The Problem is that even after using srand( time( NULL ) ) though a new input is generated every time I compile and run the code but that same input is used for all the 10 test cases.
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using std::vector;
void sort_asc(vector<int> &manav, int sizes)
{
int temp = 0;
for (int i = 0; i<sizes; i++)
{
for (int j = i + 1; j<sizes; j++)
{
if (manav[i] > manav[j])
{
temp = manav[i];
manav[i] = manav[j];
manav[j] = temp;
}
}
}
std::cout << "b in asc order : ";
for (int i = 0; i<sizes; i++)
{
std::cout << manav[i] << " ";
}
std::cout << std::endl;
}
void sort_desc(vector<int> &manav, int sizes)
{
int temp = 0;
for (int i = 0; i<sizes; i++)
{
for (int j = i + 1; j<sizes; j++)
{
if (manav[i] < manav[j])
{
temp = manav[i];
manav[i] = manav[j];
manav[j] = temp;
}
}
}
std::cout << "a in desc : ";
for (int i = 0; i<sizes; i++)
{
std::cout << manav[i] << " ";
}
std::cout << std::endl;
}
long long min_dot_product(vector<int> a, vector<int> b, int sizes) {
long long result = 0;
sort_desc(a, sizes);
sort_asc(b, sizes);
for (size_t i = 0; i < sizes; i++) {
result += a[i] * b[i];
}
return result;
}
int main() {
srand(time(NULL));
/*
std::cin >> n;
vector<int> a(n), b(n);
for (size_t i = 0; i < n; i++) {
std::cin >> a[i];
}
for (size_t i = 0; i < n; i++) {
std::cin >> b[i];
}
*/
//================================================================ TESTING =========================================================================
int z = 0;
int n = (rand() % 10) + 1; // generating the size of the vectors [1-10]
std::cout << "n = " << n << "\n";
vector<int> a;
vector<int> b;
while (z != 10) {
for (int i = 0; i < n; ++i)
{
int p = (rand() % 10) - 5;
a.push_back(p); // input values [-5,4] in 'a'
}
std::cout << "Unsorted Vector a = ";
for (int i = 0; i<n; i++)
{
std::cout << a[i] << " ";
}
std::cout << std::endl;
for (int i = 0; i < n; ++i)
{
int q = (rand() % 10) - 5;
b.push_back(q); // inputing values [-5,4] in 'b'
}
std::cout << "Unsorted Vector b = ";
for (int i = 0; i<n; i++)
{
std::cout << b[i] << " ";
}
std::cout << std::endl;
std::cout << "min_dot_product = " << min_dot_product(a, b, n) << std::endl;
z++;
}
return 0;
}
I somehow want to generate a different set of values for vector a and b for all of the 10 test cases every time I run the code.
I have tried srand(i) within the respective for loops before pushing the value in vectors but its not working for me, also reusing srand( time( NULL ) ) within the for loops is not gonna help either. Is there some other simple way I can achieve this?
The problem is you never clear out the vector on each iteration. Since you don't all of the new random numbers you generate are being added to the end of the vector and you ignore them since n never changes.
What you need to do is add
a.clear();
b.clear();
to the end of the while loop. This will clear out the vectors and then when you start the next iteration the new random numbers will get added into the part of the vector you use in your functions.
You could also set the vector the proper size and then use [] to access the elements. This way you would just overwrite the previous values and you would not have to call clear()
vector<int> a(n);
vector<int> b(n);
//...
for (int i = 0; i < n; ++i)
{
a[i] = (rand() % 10) - 5;
b[i] = (rand() % 10) - 5;
}
I put both assignments in the same for loop to save space. You can do this in two separate loops but it is not needed.