Finding the roots of a nonlinear equation using C++ - c++

What method would I use to find the roots of f(x) = 5x(e^-mod(x))cos(x) + 1 ? I have being trying the durand-kerner method but I can't get it to work. Are there any easier ways of doing it?
Here is the my code using the durand-kerner method
#include <iostream>
#include <complex>
#include <math.h>
using namespace std;
typedef complex<double> dcmplx;
dcmplx f(dcmplx x)
{
// the function we are interested in
double a4 = 5;
double a0 = 1;
return (a4 * x * exp(-x) * cos(x) )+ a0;
}
int main()
{
dcmplx p(.9,2);
dcmplx q(.1, .5);
dcmplx r(.7,1);
dcmplx s(.3, .5);
dcmplx p0, q0, r0, s0;
int max_iterations = 100;
bool done = false;
int i=0;
while (i<max_iterations && done == false)
{
p0 = p;
q0 = q;
r0 = r;
s0 = s;
p = p0 - f(p0)/((p0-q)*(p0-r)*(p0-s));
q = q0 - f(q0)/((q0-p)*(q0-r)*(q0-s));
r = r0 - f(r0)/((r0-p)*(r0-q)*(r0-s0));
s = s0 - f(s0)/((s0-p)*(s0-q)*(s0-r));
// if convergence within small epsilon, declare done
if (abs(p-p0)<1e-5 && abs(q-q0)<1e-5 && abs(r-r0)<1e-5 && abs(s-s0)<1e-5)
done = true;
i++;
}
cout<<"roots are :\n";
cout << p << "\n";
cout << q << "\n";
cout << r << "\n";
cout << s << "\n";
cout << "number steps taken: "<< i << endl;
return 0;
}

This approach makes use of the bisection method, and the fact that you can do a little math to find an upper bound for the highest zero, respectively.
Reproduced at http://ideone.com/fFLjsh
#include <iostream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <utility>
#define MINX (-20.0f)
//MAXX Happens to be an upper bound for all zeroes of the function...
#define MAXX (1.0f)
#define NUM_INTERVALS (1000000)
#define NUM_BISECTION_ITERATIONS (30)
using namespace std;
double f(double x){
return 5 * x * exp(-x) * cos(x) + 1;
}
double bisection_method(double x0, double x1){
for (unsigned int i = 0; i < NUM_BISECTION_ITERATIONS; i++){
double midpoint = 0.5*x0 + 0.5*x1;
f(x0) * f(midpoint) < 0 ? x1 = midpoint : x0 = midpoint;
}
return 0.5*x0 + 0.5*x1;
}
int main(int argc, char** argv){
vector<pair<double, double>> relevant_intervals;
for (unsigned int i = 0; i < NUM_INTERVALS - 1; i++){
double x0 = MINX + (MAXX - MINX) / NUM_INTERVALS * (i);
double x1 = MINX + (MAXX - MINX) / NUM_INTERVALS * (i + 1);
if (f(x0) * f(x1) < 0)
relevant_intervals.push_back(make_pair(x0, x1));
}
cout << fixed << setprecision(20);
for (const auto & x : relevant_intervals){
cout << "One solution is approximately " << bisection_method(x.first, x.second) << endl;
}
}

I am not familiar with Durand-Kerner method, but according to Wiki http://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method, it is suitable only for solving polynomial equations. Note the line in the wiki page: "The explanation is for equations of degree four. It is easily generalized to other degrees."
Your equation is not polynomial. The numerical solution will probably not converge.
Regardless of that your function f returns wrong formula: return a4 * x * exp(-abs(x)) * cos(x) + a0; (you forgot about complex modulo, i.e. abs)
and your iterations seem also wrong. They should read:
p = p0 - f(p0)/((p0-q0)*(p0-r0)*(p0-s0));
q = q0 - f(q0)/((q0-p)*(q0-r0)*(q0-s0));
r = r0 - f(r0)/((r0-p)*(r0-q)*(r0-s0));
s = s0 - f(s0)/((s0-p)*(s0-q)*(s0-r));
but even if you make these changes, the solution will not converge - it will be oscilating. The reason is probably as written above - the method is not suitable for this type of equation.

Related

C++ Newton Raphson method is slower than bisection?

My task is to find the root of a function with both the Newton Raphson and the bisection method within an error margin of 10E-7.
The point of all that is, that we learn that the Newton Raphson method is faster and more effective.
Now for some reason I come to the opposite result. Although I am aware that the initial guess of the root in both methods strongly affects the number of necessary iterations. But I entered a similar guess in both algorithms and my fellow students dont get the result I do.
Bisection method:
#include <iostream>
#include <iomanip>
using namespace std;
//Declaring the given function
double func1(double x) {
return 0.00000000027 * (x - 10000000) - 0.16460351745 * (-1 + ((1000000000) / (x))) * 1 / (sqrt(x));
}
int main() {
std::fixed;
//Initial guess: root ist at 10 to the 7.
double x1 = 10000000;
double x2 = 1000000000;
double eps = 0.0000001;
int i = 0;
double x0[100000];
x0[0] =0;
//Exception handler
if (func1(x1) * func1(x2) > 0) {
cout << "Root is not inside the bracket.";
goto end;
}
goto start;
//Bisection Algorithm
while (abs(x0[i] - x0[i-1]) >= eps) {
start:
i = i + 1;
x0[i] = 0.5 * (x1 + x2);
if (func1(x1) * func1(x0[i]) < 0) {
x2 = x0[i];
}
else {
x1 = x0[i];
}
}
cout << endl << "Bisection Method: " << fixed << setprecision(10) << x0[i] << endl << "Iterations: " << i << endl << endl << endl << endl << endl;
end:
return 0;
}
}
Newton Raphson:
#include <iostream>
#include <iomanip>
using namespace std;
// Declaring the function and its derivative
double func1(double x) {
return 0.00000000027 * (x - 10000000) - 0.16460351745 * (-1 + ((1000000000) / (x))) * 1 / (sqrt(x));
}
double funcderiv1(double x) {
return 0.00000000027+((0.1646035174)/(2*x*x*sqrt(x)))*(30000000-x);
}
int main()
{
std::fixed;
double eps = 1;
double x_start = 10000000;
double c;
int i = 0;
while (eps >= 0.0000001) {
c = x_start - ((func1(x_start)) / (funcderiv1(x_start)));
eps = abs(func1(x_start) / funcderiv1(x_start));
x_start = c;
i = i + 1;
}
cout << fixed << setprecision(5) << "RESULT " << c << endl << " Iterations: " << i << endl;
}
The root is at 17903534.23630
Does anyone know why my bisection method needs 55 iterations while Newton Raphson takes like 82?
For the function
f(x) = A * (x - B) - C * (D / x - 1) / sqrt(x)
A = 0.00000000027
B = 10000000
C = 0.16460351745
D = 1000000000
the correct derivative is:
f'(x) = A - C (x - 3D) / (2 * x * x * sqrt(x))
Compare this with your expression:
g(x) = A - C (x - 3B) / (2 * x * x * sqrt(x))
After fixing the formula (by adding two zeros), your code makes 6 iterations:
RESULT 17903534.23630
Iterations: 6

Problem: "Cannot convert argument 1 from 'double' to 'char(*)(double)'"

I have a problem with the following assignment. The problem is to find the integral of the function. It gives me the error "Cannot convert argument 1 from 'double' to 'char(*)(double)'". I think the problem is in the bottom, where I define the function. And I am not even sure if I should use char for p.
Does anyone know, what the problem is?
/*43. Modify program chapter6_11 to estimate the integral of the function
f (x) = 3x − 2x^2.*/
#include <iostream> //Required for cin, cout
#include <fstream>
#include <cstdlib> //Required for srand(), rand().
#include <cmath> //Required for pow().
using namespace std;
/*-----------------------------------------------------------------*/
/* Program chapter6_11 */
/* */
/* This program finds the real roots of a cubic polynomial */
/* using the Newton-Raphson method. */
double integral(char(p)(double x), double a, double b, double n);
int main(){
// Declare objects.
int iterations(0);
double a1, a2, a3, x, p, dp, tol;
cout << "Enter coefficients a1, a2, a3 (here -2, 3 and 0)\n";
cin >> a1 >> a2 >> a3;
cout << "Enter initial guess for root\n";
cin >> x;
// Evaluate p at initial guess.
p = -2* x * x + 3 * x + 0;
// Determine tolerance.
tol = fabs(p);
while (tol > 0.001 && iterations < 100)
{
// Calculate the derivative.
dp = 2 * -2 * x + 3;
// Calculate next estimated root.
x = x - p / dp;
// Evaluate p at estimated root.
p = -2 * x * x + 3 * x + 0;
tol = fabs(p);
iterations++;
}
if (tol < 0.001)
{
cout << "Root is " << x << endl;
cout << iterations << " iterations\n";
cout << "Integral is" << integral(p, -100000, 100000, 1000);
}
else
cout << "Did not converge after 100 iterations\n";
return 0;
}
double integral(char(p)(double x), double a, double b, double n) {
double step = (b - a) / n; // width of each small rectangle
double area = 0.0; // signed area
for (int i = 0; i < n; i++) {
area += p(a + (i + 0.5) * step) * step; // sum up each small rectangle
}
return area;
}
You are calling integral,
cout << "Integral is" << integral(p, -100000, 100000, 1000);
Where p is not a pointer to a function returning a char and taking a double
char func(double x);
maybe you meant to define such at function?

Quasi-Monte Carlo Integration for inverse cumulative Normal Distribution

I am trying to integrate functions, which includes changing of variables with ICDF function (gsl_cdf_gaussian_Pinv(x[1], 1)), but the results are always wrong:
#include <fstream>
#include <iostream>
#include <memory>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <math.h>
#include <stdio.h>
#include <gaussinv.c>
#define _USE_MATH_DEFINES
using namespace std;
double f(double[], int);
double int_mcnd(double(*)(double[], int), double[], double[], int, int);
double varr[100];
int k = 0;
double hj = 0;
double mj = 1;
# include "sobol.hpp"
int DIM_NUM = 10;
int main() {
const int n = 10; /* define how many integrals */
// const int m = 1000000; /* define how many points */
double a[n] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* left end-points */
double b[n] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /* right end-points */
double result;
int i, m;
int ntimes;
cout.setf(ios::fixed | ios::showpoint);
// current time in seconds (begin calculations)
time_t seconds_i;
seconds_i = time(NULL);
m = 1; // initial number of intervals
ntimes = 20; // number of interval doublings with nmax=2^ntimes
cout << setw(12) << n << "D Integral" << endl;
for (i = 0; i <= ntimes; i = i + 1) {
result = int_mcnd(f, a, b, n, m);
cout << setw(10) << m << " " << setprecision(30) << result << endl;
m = m * 2;
}
// current time in seconds (end of calculations)
time_t seconds_f;
seconds_f = time(NULL);
cout << endl << "total elapsed time = " << seconds_f - seconds_i << " seconds" << endl << endl;
return 0;
}
double f(double x[], int n) {
double y;
int j;
y = 0.0;
/* define Multidimensional Gaussian distribution and covariance */
/* X=(x1, k=2, mu = (0, covariance matrix = (v 0 0 0
* x2 0 0 v 0 0
* x3 0 0 0 v 0
* x4) 0) 0 0 0 v) */
double v = 1;
double determinant = pow(v, 10);
double inverse = 1 / v;
double rang = gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1) - gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1) +
gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1);
y = (1 / sqrt(pow(2 * M_PI, 10) * determinant) * exp(-0.5 * (inverse * pow(gsl_cdf_gaussian_Pinv(x[0], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[1], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[2], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[3], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[4], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[5], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[6], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[7], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[8], 1), 2) +
inverse * pow(gsl_cdf_gaussian_Pinv(x[9], 1), 2))));
return y;
}
/*==============================================================
input:
fn - a multiple argument real function (supplied by the user)
a[] - left end-points of the interval of integration
b[] - right end-points of the interval of integration
n - dimension of integral
m - number of random points
output:
r - result of integration
================================================================*/
double int_mcnd(double(*fn)(double[], int), double a[], double b[], int n, int m) {
double r, x[n], p;
int i, j;
double rarr[DIM_NUM];
long long int seed;
seed = 1;
long long int seed_in;
long long int seed_out;
srand(time(NULL)); /* initial seed value (use system time) */
r = 0.0;
p = 1.0;
// step 1: calculate the common factor p
for (j = 0; j < n; j = j + 1) {
// p = p * (b[j] - a[j]);
p=p*(gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1)-gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1));
}
// step 2: integration
for (i = 1; i <= m; i = i + 1) {
seed_in = seed;
i8_sobol(DIM_NUM, &seed, rarr);
seed_out = seed;
// calculate random x[] points
for (j = 0; j < n; j = j + 1) {
x[j] = a[j] + (b[j] - a[j]) * rarr[j];
}
r = r + fn(x, n);
}
cout << endl << "p = " << p << " seconds" << endl << endl;
r = r * p / m;
return r;
}
The problem is in the parametrization parameter p, which I suggest to be
p=p*(gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1)-gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1))
instead of standard - p = p * (b[j] - a[j]);
I want to integrate not only within [0,1]^N intervals, but also in [-20;20].
I can't define my mistake. Can somebody help, please?

Newtons Method finding cube root, answer comes out as 0 every time

I am using a program with C++ that will calculate the cube root of a given float point number using Newton Methods. My program compiles, but the answer always comes out to zero. Here's the program:
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
const double epsilon = 0.00000001;
double A = 0;
double x1 = A / 10;
double x2 = 0;
int iter = 0;
cout << "Please enter a number to square. " << endl;
cin >> A;
while ((fabs(x1 - x2) > epsilon) && (iter < 100)) {
x1 = x2;
x2 = ((2 / 3 * x1) + (A / (3 * x1 * x1)));
++iter;
}
cout << "The answer is : " << x2 << endl;
}
You were assigning variables to be zero, so you weren't going into the loop and you were also dividing by zero because you set x1=x2 and along with what was said in the comments to your post. So I moved some assigning and declarations and everything worked out fine
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
const double epsilon = 0.00000001;
double A = 0;
double x1 = 0;
double x2 = 1;
int iter = 0;
cout << "Please enter a number to square. " << endl;
cin >> A;
x1 = A / 10.0;
while ((fabs(x1 - x2) > epsilon) && (iter < 100)) {
x1 = x2;
x2 = ((2.0 / 3.0 * x1) + (A / (3.0 * x1 * x1)));
++iter;
}
cout << "The answer is : " << x2 << endl;
}

Initializing dynamic pointer to multidimensional array

I am new to programming and am trying to implement A star search algorithm on C++. I am having segmentation fault:11 because of not initializing my pointer. I have tried it several different ways to no avail.
I am still confused about the whole pointer and dynamic memory allocation concept.
Can anyone help me figure it out? Thank you.
#include <iostream>
#include <vector>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;
// Definition of the heuristic. The heuristic in this problem is the distance between
// two coordinates
double heuristic(double x1, double y1, double x2, double y2) {
double dx, dy;
dx = x1 - x2;
dy = y1 - y2;
return sqrt(dx*dx - dy*dy);
//return sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));
}
// ----- A Star Search Algorithm (f = g + h)----
double** a_star_search(double points[][2]) {
int count = 1;
double** points1 = NULL;
// points1[10][2];
double x1 = points[0][0];
double y1 = points[0][1];
points1[count - 1][0] = x1;
points1[count - 1][1] = y1;
while (count <= 10) {
double tempx1;
double tempy1;
double distance = 10000000;
for (int i = 0; i < 10; i++) {
if (points[i][0] != 0 && points[i][1] != 0) {
double distance2 = heuristic(x1, y1, points[i][0], points[i][1]);
if (distance2 < distance) {
tempx1 = points[i][0];
tempy1 = points[i][1];
distance = distance2;
}
}
}
x1 = tempx1;
y1 = tempy1;
count++;
points1[count - 1][0] = x1;
points1[count - 1][1] = y1;
}
return points1;
}
int main() {
double points[7][2];
int counter = 0;
ifstream infile("waypoints.txt");
int a, b;
while (infile >> a >> b)
{
points[counter][0] = a;
points[counter][1] = b;
counter++;
}
points[6][0] = points[0][0];
points[6][1] = points[0][1];
double** points1 = a_star_search(points);
cout << "Initial Sequence: ";
for (int i = 0;i < 7;i++) {
cout << "(" <<points[i][0] << " , " << points[i][1] << "), ";
}
cout << "\n\nOptimized Sequence: ";
for (int i = 0;i < 7;i++) {
cout << "(" << points1[i][0] << " , " << points1[i][1] << "), ";
}
cout << "\n\nTotal Distance after A* search: ";
double totaldistance = 0;
for (int i = 0;i < 6;i++) {
double dis = heuristic(points1[i][0], points1[i][1], points1[i + 1][0], points1[i + 1][1]);
cout << dis << "+";
totaldistance = totaldistance + dis;
}
cout<< "=" << totaldistance <<endl;
}
You are not allocating memory dynamically for double** points1 variable after setting it to NULL in your a_star_search function. As pointed out by #user4581301, use std::vector. This will simplify your code significantly and worth spending the time to learn STL containers.