Would you please help me with my problem. I'm trying to write a program where objects in different class interact. I base my model on the gsl library to resolve my ordinary differential equations (ode).
Instances of different classes consume each other, so they get or loose mass when they eat or are eaten.
My 2 ode are like b[i] = sum of consumption - sum of consumed. I calculate consumption as follow, with 1 being the consumer and 0, the prey.
conso[1] = y[0] * x[1] * y[1]
The original code comes from "sample code using gsl routines" as follow with modifications. The instances of class A and B are included in maps of class C.
I'm new to c++ and I don't see how I can integrate a loop in the ode to make it calculate what has been consumed by each instance, and remove it from the other instances that have been eaten. The best would be to use functions and variables that are in the istances class but the function where the ode are has to be static. I thought about array but it seems that arrays can't be parameters of the odes.
The other problem is that for each instance, the parameters has to change and be taken in the class, but how I did here, in the loop with the iterators, the ode will work for the last instance... Again I would have like to use an array of class C that take the parameter of the instances in class A and B, but because the function is static I can't use the array of the class "C". I'm in real trouble !
Do you have any ideas ? Thank you !
// include files
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv.h>
// ************************* C.h ****************************
class C
{
public :
C(std::map(std::map<std::string,A> &A, std::map<std::string,B> &B);
~C();
int integ(void);
int static rhs (double t, const double y[], double f[], void *params_ptr);
private :
std::map<std::string,A> &A,
std::map<std::string,B> &B,
};
//*************************** C.cpp ****************************
int C::integ (void)
{
int dimension = 2; // number of differential equations
double eps_abs = 1.e-8; // absolute error requested
double eps_rel = 1.e-10; // relative error requested
// define the type of routine for making steps:
const gsl_odeiv_step_type *type_ptr = gsl_odeiv_step_rkf45;
// allocate/initialize the stepper, the control function, and the
// evolution function.
gsl_odeiv_step *step_ptr = gsl_odeiv_step_alloc (type_ptr, dimension);
gsl_odeiv_control *control_ptr = gsl_odeiv_control_y_new (eps_abs, eps_rel);
gsl_odeiv_evolve *evolve_ptr = gsl_odeiv_evolve_alloc (dimension);
gsl_odeiv_system my_system; // structure with the rhs function, etc.
// parameter for the diffeq
for(itA=A.begin(); itA!=A.end(); ++itA)
{
x = itA->second.getx();
my_system.params = &x; // parameters to pass to rhs
}
for(itB=B.begin(); itB!=B.end(); ++itB)
{
z = itB->second.getz();
my_system.params = &z; // parameters to pass to rhs
}
double y[2]; // 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 = 1e-6; // starting step size for ode solver
// load values into the my_system structure
my_system.function = rhs; // the right-hand-side functions dy[i]/dt
my_system.dimension = dimension; // number of diffeq's
tmin = 0.; // starting t value
tmax = 100.; // final t value
delta_t = 1.;
for(itA=A.begin(); itA!=A.end(); ++itA)
{
y[0] = itA->second.getY(); // initial y value
}
for(itB=B.begin(); itB!=B.end(); ++itB)
{
y[1] = itB->second.getY(); // initial y value
}
t = tmin; // initialize t
// print initial values
cout << scientific << setprecision (5) << setw (12) << t << " "
<< setw (12) << y[0] << " " << setw (12) << y[1] << endl;
// step to tmax from tmin
for (t_next = tmin + delta_t; t_next <= tmax; t_next += delta_t)
{
while (t < t_next) // evolve from t to t_next
{
gsl_odeiv_evolve_apply (evolve_ptr, control_ptr, step_ptr,
&my_system, &t, t_next, &h, y);
}
// print at t = t_next
cout << scientific << setprecision (5) << setw (12) << t << " "
<< setw (12) << y[0] << " " << setw (12) << y[1] << endl;
}
// all done; free up the gsl_odeiv stuff
gsl_odeiv_evolve_free (evolve_ptr);
gsl_odeiv_control_free (control_ptr);
gsl_odeiv_step_free (step_ptr);
return 0;
}
//*************************** rhs ****************************
int C :: rhs (double , const double y[], double f[], void *params_ptr)
{
// get parameter(s) from params_ptr; here, just a double
double x = *(double *) params_ptr;
double z = *(double *) params_ptr;
// evaluate the right-hand-side functions at t
f[1] = x * y[1] + sum consumption - sum consumed; //objects of class A
f[0] = - z * y[0] - sum consumed; //objects of class B
return GSL_SUCCESS; // GSL_SUCCESS defined in gsl/errno.h as 0
}
I tried to add consumption, but it says "error: 'void' must be the first and only parameter if
specified" :
int C :: rhs (double , const double y[], double f[], void *params_ptr, void conso)
{
// get parameter(s) from params_ptr; here, just a double
double x = *(double *) params_ptr;
double z = *(double *) params_ptr;
// evaluate the right-hand-side functions at t
f[0] = z * y[0]; //objects of class A
f[1] = - x * y[1] + conso; //objects of class B
return GSL_SUCCESS; // GSL_SUCCESS defined in gsl/errno.h as 0
}
//***And in int C :: integ :
for(itA=A.begin(); itA!=A.end(); ++itA)
{
for(itB=B.begin(); itB!=B.end(); ++itB)
{
void conso = itA->second.conso(itB->second, x);
}
}
//***With in class A :
void A :: conso(Group &prey, double x)
{
double conso=0;
conso = x * y * prey.gety();
}
Related
2nd task:
For a function f : R^n → R the gradient at a point ~x ∈ R^n is to be calculated:
- Implement a function
CMyVector gradient(CMyVector x, double (*function)(CMyVector x)),
which is given in the first parameter the location ~x and in the second parameter the function f as function pointer in the second parameter, and which calculates the gradient ~g = grad f(~x) numerically
by
gi = f(x1, . . . , xi-1, xi + h, xi+1 . . . , xn) - f(x1, . . . , xn)/h
to fixed h = 10^-8.
My currently written program:
Header
#pragma once
#include <vector>
#include <math.h>
class CMyVektor
{
private:
/* data */
int Dimension = 0;
std::vector<double>Vector;
public:
CMyVektor();
~CMyVektor();
//Public Method
void set_Dimension(int Dimension /* Aktuelle Dim*/);
void set_specified_Value(int index, int Value);
double get_specified_Value(int key);
int get_Vector_Dimension();
int get_length_Vektor();
double& operator [](int index);
string umwandlung()
};
CMyVektor::CMyVektor(/* args */)
{
Vector.resize(0, 0);
}
CMyVektor::~CMyVektor()
{
for (size_t i = 0; i < Vector.size(); i++)
{
delete Vector[i];
}
}
void CMyVektor::set_Dimension(int Dimension /* Aktuelle Dim*/)
{
Vector.resize(Dimension);
};
void CMyVektor::set_specified_Value(int index, int Value)
{
if (Vector.empty())
{
Vector.push_back(Value);
}
else {
Vector[index] = Value;
}
};
double CMyVektor::get_specified_Value(int key)
{
// vom intervall anfang - ende des Vectors
for (unsigned i = 0; i < Vector.size(); i++)
{
if (Vector[i] == key) {
return Vector[i];
}
}
};
int CMyVektor::get_Vector_Dimension()
{
return Vector.size();
};
// Berechnet den Betrag "länge" eines Vectors.
int CMyVektor::get_length_Vektor()
{
int length = 0;
for (size_t i = 0; i < Vector.size(); i++)
{
length += Vector[i]^2
}
return sqrt(length);
}
// [] Operator überladen
double& CMyVektor::operator [](int index)
{
return Vector[index];
}
main.cpp
#include <iostream>
#include "ClassVektor.h"
using namespace std;
CMyVektor operator+(CMyVektor a, CMyVektor b);
CMyVektor operator*(double lambda, CMyVektor a);
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x));
int main() {
CMyVektor V1;
CMyVektor V2;
CMyVektor C;
C.set_Dimension(V1.get_length_Vector());
C= V1 + V2;
std::cout << "Addition : "<< "(";;
for (int i = 0; i < C.get_length_Vector(); i++)
{
std::cout << C[i] << " ";
}
std::cout << ")" << endl;
C = lamda * C;
std::cout << "Skalarprodukt: "<< C[0]<< " ";
}
// Vector Addition
CMyVektor operator+(CMyVektor a, CMyVektor b)
{
int ai = 0, bi = 0;
int counter = 0;
CMyVektor c;
c.set_Dimension(a.get_length_Vector());
// Wenn Dimension Gleich dann addition
if (a.get_length_Vector() == b.get_length_Vector())
{
while (counter < a.get_length_Vector())
{
c[counter] = a[ai] + b[bi];
counter++;
}
return c;
}
}
//Berechnet das Skalarprodukt
CMyVektor operator*(double lambda, CMyVektor a)
{
CMyVektor c;
c.set_Dimension(1);
for (unsigned i = 0; i < a.get_length_Vector(); i++)
{
c[0] += lambda * a[i];
}
return c;
}
/*
* Differenzenquotient : (F(x0+h)+F'(x0)) / h
* Erster Parameter die Stelle X - Zweiter Parameter die Funktion
* Bestimmt numerisch den Gradienten.
*/
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x))
{
}
My problem now is that I don't quite know how to deal with the
CMyVector gradient(CMyVector x, double (*function)(CMyVector x))
function and how to define a function that corresponds to it.
I hope that it is enough information. Many thanks.
The function parameter is the f in the difference formula. It takes a CMyVector parameter x and returns a double value. You need to supply a function parameter name. I'll assume func for now.
I don't see a parameter for h. Are you going to pass a single small value into the gradient function or assume a constant?
The parameter x is a vector. Will you add a constant h to each element?
This function specification is a mess.
Function returns a double. How do you plan to turn that into a vector?
No wonder you're confused. I am.
Are you trying to do something like this?
You are given a function signature
CMyVector gradient(CMyVector x, double (*function)(CMyVector x))
Without knowing the exact definition I will assume, that at least the basic numerical vector operations are defined. That means, that the following statements compile:
CMyVector x {2.,5.,7.};
CMyVector y {1.,7.,4.};
CMyVector z {0.,0.,0.};
double a = 0.;
// vector addition and assigment
z = x + y;
// vector scalar multiplication and division
z = z * a;
z = x / 0.1;
Also we need to know the dimension of the CMyVector class. I assumed and will continue to do so that it is three dimensional.
The next step is to understand the function signature. You get two parameters. The first one denotes the point, at which you are supposed to calculate the gradient. The second is a pointer to the function f in your formula. You do not know it, but can call it on a vector from within your gradient function definition. That means, inside of the definition you can do something like
double f_at_x = function(x);
and the f_at_x will hold the value f(x) after that operation.
Armed with this, we can try to implement the formula, that you mentioned in the question title:
CMyVector gradient(CMyVector x, double (*function)(CMyVector x)) {
double h = 0.001;
// calculate first element of the gradient
CMyVector e1 {1.0, 0.0, 0.0};
double result1 = ( function(x + e1*h) - function(x) )/h;
// calculate second element of the gradient
CMyVector e2 {0.0, 1.0, 0.0};
double result2 = ( function(x + e2*h) - function(x) )/h;
// calculate third element of the gradient
CMyVector e3 {0.0, 0.0, 1.0};
double result3 = ( function(x + e3*h) - function(x) )/h;
// return the result
return CMyVector {result1, result2, result3};
}
There are several thing worth to mention in this code. First and most important I have chosen h = 0.001. This may like a very arbitrary choice, but the choice of the step size will very much impact the precision of your result. You can find a whole lot of discussion about that topic here. I took the same value that according to that wikipedia page a lot of handheld calculators use internally. That might not be the best choice for the floating point precision of your processor, but should be a fair one to start with.
Secondly the code looks very ugly for an advanced programmer. We are doing almost the same thing for each of the three dimensions. Ususally you would like to do that in a for loop. The exact way of how this is done depends on how the CMyVector type is defined.
Since the CMyVektor is just rewritting the valarray container, I will directly use the valarray:
#include <iostream>
#include <valarray>
using namespace std;
using CMyVektor = valarray<double>;
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x));
const double h = 0.00000001;
int main()
{
// sum(x_i^2 + x_i)--> gradient: 2*x_i + 1
auto fun = [](CMyVektor x) {return (x*x + x).sum();};
CMyVektor d = gradient(CMyVektor{1,2,3,4,5}, fun);
for (auto i: d) cout << i<<' ';
return 0;
}
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x)){
CMyVektor grads(x.size());
CMyVektor pos(x.size());
for (int i = 0; i<x.size(); i++){
pos[i] = 1;
grads[i] = (funktion(x + h * pos) - funktion(x))/ h;
pos[i] = 0;
}
return grads;
}
The prints out 3 5 7 9 11 which is what is expected from the given function and the given location
/*I need to use the result from the (delta) function inside the (sol_ec_II) function for a school assignment.*/
#include <iostream>
#include <ctgmath>
using namespace std;
double delta(double a, double b, double c) {
return (b * b) - (4 * a * c);/* so I need to take this value [(b * b) - (4 * a * c)]
and use it in sol_ec_II in the places where I wrote "delta". */
}
void sol_ec_II(double a, double b, double c) {
if (delta < 0) {//here
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);//here
double x2 = -1 * b + sqrt(delta);//here
}
}
// I would also need to use the (delta) function inside the (sol_ec_II) so they use the same
a, b, c values like this:
void sol_ec_II(double a, double b, double c) {
delta(a, b, c);
if (delta < 0) {
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);
double x2 = -1 * b + sqrt(delta);
}
}
//so I don't understand how to get the value that results from delta(a, b, c) and use it inside the if statement and sqrt.
The result "comes out" of the function call at the time you call it. Look, you already know how sqrt works. sqrt is a function! You write sqrt(something) and that calls the function sqrt and it calls the function sqrt with the argument something and then the return value from sqrt gets used in the place where you wrote sqrt(something). e.g. 1 + sqrt(4) calculates 3.
Likewise the return value from delta gets used in the place where you wrote delta(a, b, c). If you want to call delta and then call sqrt (i.e. calculate the square root of the delta) you write sqrt(delta(a, b, c)).
Obviously, just calculating a number is pretty useless. You probably want to do something with the number, like saving it in a variable or printing it. Examples:
cout << "the square root of the delta is " << sqrt(delta(a,b,c)) << endl;
cout << "the delta plus one is " << (delta(a,b,c) + 1) << endl;
double the_delta = delta(a,b,c);
cout << "the delta is " << the_delta << " and the square root of the delta is " << sqrt(the_delta) << endl;
if (delta(a,b,c) < 0)
cout << "the delta is negative" << endl;
else
cout << "the delta isn't negative" << endl;
Note: Every time the computer runs delta(a,b,c) it calls the delta function. It doesn't remember the calculation from last time. You can see this because if you put cout instructions inside the delta function, they get printed every time the computer runs delta(a,b,c).
Of course I will not give you the solution for your program. I hope this helps you understand how functions work.
here you should pass parameters to deleta function in order to execute it:
void sol_ec_II(double a, double b, double c) {
if (delta(a,b,c) < 0) {//here
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);//here
double x2 = -1 * b + sqrt(delta);//here
}
}
or you could save the result in a new variable called result for example, and after that use it, like that:
void sol_ec_II(double a, double b, double c) {
double result = delta(a,b,c);
if (result < 0) {//here
cout << endl << "Polinomul NU are solutii.";
}
else {
double x1 = -1 * b - sqrt(delta);//here
double x2 = -1 * b + sqrt(delta);//here
}
}
The Same thing for the second function, always to execute a function use parenthesis and pass between them the arguments that the function expects.
To reuse the value you get from calling a function multiple time use a variable:
double delta(double,double,double) { return 1.2; /*ignore this for now*/ }
void sol_ec_II(double a, double b, double c) {
const auto kDelta = delta(a, b, c);
if (kDelta < 0.0) {
// do stuff
} else {
const auto kRootD = sqrt(kDelta); // same idea
const auto x1 = -b - kRootD;
const auto x2 = -b + kRootD;
// use the variables
}
}
I use auto out of habit, you don't need to, double is fine.
I have a working Integrator class that will compute the definite Integral of basic functions of a single variable. I have tested the integrations of some basic functions and it appears to be working correctly.
I'm now at the point where I would like to expand this class to be able to perform multiple Integrals of the same function... and this is where I've hit a roadblock...
Here is my Integrator Class and some basic usage examples:
Integrator.h
#pragma once
#include <algorithm>
#include <utility>
#include <functional>
struct Limits {
double lower;
double upper;
Limits() : lower{ 0 }, upper{ 0 } {}
Limits(double a, double b) : lower{ a }, upper{ b } {
if (a > b) std::swap(lower, upper);
}
void applyLimits(double a, double b) {
lower = a;
upper = b;
if (a > b) std::swap(lower, upper);
}
};
class Integrator {
private:
Limits limits_;
std::function<double(double)> integrand_;
double dx_;
double dy_;
double integral_;
int step_size_;
public:
Integrator(Limits limits, int stepSize, std::function<double(double)> integrand, double dy = 0)
: limits_{ limits },
step_size_{ stepSize },
integrand_{ integrand },
dx_{ 0 }, dy_{ 0 }
{}
~Integrator() = default;
constexpr double dx() const { return this->dx_; }
constexpr double dy() const { return this->dy_; }
constexpr double integral() const { return this->integral_; }
Limits limits() const { return limits_; }
std::function<double(double)>* integrand() { return &this->integrand_; }
// This is always a 1st order of integration!
constexpr double evaluate() {
double distance = limits_.upper - limits_.lower; // Distance is defined as X0 to XN. (upperLimit - lowerLimit)
dx_ = distance / step_size_; // Calculate the amount of iterations by dividing
// the x-distance by the dx stepsize
integral_ = 0; // Initialize area to zero
for (auto i = 0; i < step_size_; i++) { // For each dx step or iteration calculate the area at Xi
dy_ = integrand_(limits_.lower + i * dx_);
double area = dy_ * dx_; // Where the width along x is defines as dxStepSize*i
integral_ += area; // and height(dy) is f(x) at Xi. Sum all of the results
}
return integral_;
}
};
main.cpp
#include <iostream>
#include <exception>
#include <cmath>
#include "Integrator.h"
constexpr double PI = 3.14159265358979;
constexpr double funcA(double x) {
return x;
}
constexpr double funcB(double x) {
return (x*x);
}
constexpr double funcC(double x) {
return ((0.5*(x*x)) + (3*x) - (1/x));
}
double funcD(double x) {
return sin(x);
}
int main() {
try {
std::cout << "Integration of f(x) = x from a=3.0 to b=5.0\nwith an expected output of 8\n";
Integrator integratorA(Limits(3.0, 5.0), 10000, &funcA);
std::cout << integratorA.evaluate() << '\n';
std::cout << "\n\nIntegration of f(x) = x^2 from a=2.0 to b=20.0\nwith an expected output of 2664\n";
Integrator integratorB(Limits(2.0, 20.0), 10000, &funcB);
std::cout << integratorB.evaluate() << '\n';
std::cout << "\n\nIntegration of f(x) = (1\\2)x^2 + 3x - (1\\x) from a=1.0 to b=10.0\nwith an expected output of 312.6974\n";
Integrator integratorC(Limits(1.0, 10.0), 10000, &funcC);
std::cout << integratorC.evaluate() << '\n';
std::cout << "\n\nIntegration of f(x) = sin(x) from a=0.0 to b=" <<PI<< "\nwith an expected output of 2\n";
Integrator integratorD(Limits(0.0, PI), 10000, &funcD);
std::cout << integratorD.evaluate() << '\n';
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Output
Integration of f(x) = x from a=3.0 to b=5.0
with an expected output of 8
7.9998
Integration of f(x) = x^2 from a=2.0 to b=20.0
with an expected output of 2664
2663.64
Integration of f(x) = (1\2)x^2 + 3x - (1\x) from a=1.0 to b=10.0
with an expected output of 312.6974
312.663
Integration of f(x) = sin(x) from a=0.0 to b=3.14159
with an expected output of 2
2
I was thinking of adding another function to this class similar to its evaluate() function... It currently looks something like this:
double integrate(Limits limits, double dy) {
double total = 0;
dy_ = dy;
for (int i = 0; i < step_size_; i++) {
double yi = limits_.lower*i*dy_;
double dx = static_cast<double>(yi - limits.lower) / stepSize;
double innerArea = 0;
for (int j = 0; j < step_size_; j++) {
Integrator inner(limits, step_size_, integrand_, dy_);
innerArea += inner.evaluate();
}
double outerArea = innerArea * dy_;
total += outerArea;
}
integral_ = total;
return integral_;
}
And this is where I'm getting confused or stumped... I'm not sure how to implement this function properly when it comes to the limits of integration with respect to the inner and outer integrals.
Take for example the following integral below:
The inner integral's upper limit is based on y for each iteration of computation... This has to be done dynamically. The outer integral is straight forward as it goes from [3,5] as opposed to [1,y].
I think I'm on the right track, but something in the above approach is totally off... I'm getting completely wrong values from expected or intended values...
Any and all suggestions and or tips are highly welcomed!
Edit - Note - I supplied the wrong image above, that has been updated...
The expected output should be: 65.582 with the correctly supplied function f(x) = 1/2x^2 + 3x - (1/x). And when I try to compute the double integral I end up getting this...
And here is the added code to the driver program or main.cpp...
std::cout << "\n\nTesting Double Integration of f(x) = (1\\2)x^2 + 3x - (1\\x) from [3,5] and [1,y]\nwith an expected output of 65.582\n";
Integrator integratorE(Limits(3, 5), 1000, &funcC);
double dy = integratorE.limits().upper - integratorE.limits().lower;
integratorE.integrate(Limits(1, integratorE.integral()), dy);
std::cout << integratorE.integral() << '\n';
However, it is not printing anything to the console...
Edit
I wasn't getting output for I wasn't waiting long enough. The iterations were defined as 1000 by the step_size. This will end up generating 1000^1000 total iterations... I had overlooked this in the construction of the Integrator object. I had changed this in my code to have a step_size of 100. And now my application is outputting a value of 2.68306e+189 which is clearly wrong! When I increase the step_size to 500 it is giving me something on the order of 6.62804e+190 which is still wrong.
After going back and watching the video again... I started to break down the double looping structure in my class's integrate() function.
I removed some unneeded parameters from both the constructor and this function's signature. I removed the dependency of passing in the dy since I'm able to calculate and store this value internally.
I had done a minor overhaul of my integrate member function. I'm now calculating both the dy and dx at the appropriate times using the appropriate limits of integration with respect to the step_size.
Instead of creating an instance of an Integrator within this function and using that instance's evaluate() function. I completely removed this behavior since I don't need to do this as this class stores an instance of the function of integration called integrand where this is an std::function<T> object. With this, I can just calculate the current y by passing in the xi into that integrand. Then I can use that to calculate the inner area for the summation.
My updated function looks like this:
double integrate(double lower = 0.0, double upper = 0.0) {
// Since we are not using the inner upper limit directly
// make sure that it is still greater than the lower limit
if (upper <= lower) {
upper = lower + 1;
}
Limits limits(lower, upper);
double outerSum = 0;
dy_ = static_cast<double>(limits_.upper - limits_.lower) / step_size_;
for (int i = 0; i < step_size_; i++) {
double yi = limits_.lower+i*dy_;
double dx_ = static_cast<double>(yi - limits.lower) / step_size_;
double innerSum = 0;
for (int j = 0; j < step_size_; j++) {
double xi = limits.lower + dx_ * j;
double fx = integrand_(xi);
double innerArea = fx*dx_;
innerSum += innerArea;
}
double outerArea = innerSum * dy_;
outerSum += outerArea;
}
integral_ = outerSum;
return integral_;
}
And here is the usage of this function within my main class:
std::cout << "\n\nTesting Double Integration of f(x) = (1\\2)x^2 + 3x - (1\\x) from [3,5] and [1,y]\nwith an expected output of 65.582\n";
Integrator integratorE(Limits(3, 5), 100, &funcC);
//double dy = integratorE.limits().upper - integratorE.limits().lower;
integratorE.integrate(1);
std::cout << integratorE.integral() << '\n';
And this is giving me an output of:
Testing Double Integration of f(x) = (1\2)x^2 + 3x - (1\x) from [3,5] and [1,y]
with an expected output of 65.582
64.6426
With a step_size of 100 iterations and an output of:
Testing Double Integration of f(x) = (1\2)x^2 + 3x - (1\x) from [3,5] and [1,y]
with an expected output of 65.582
65.3933
With a step_size of 500 iterations.
So as this class now stands, I can use evaluate() to perform a single definite integration of a single variable and I can use integrate(lower,upper) to perform at least a double definite integration of a single variable.
Take a look at the following transfer function:
With Matlab Simulink:
The result is
In State-space representation, the system can be modeled as follows:
In Matlab, we can model the system in the state-space representation:
which yields the following plot:
which is exactly the result generated by using transfer function. I'm trying to generate same results with odeint but failed. This is the code
#include <iostream>
#include <Eigen/Dense>
#include <boost/numeric/odeint.hpp>
#include <iomanip>
#include <fstream>
using namespace std;
using namespace boost::numeric::odeint;
typedef std::vector< double > state_type;
void equations(const state_type &y, state_type &dy, double x)
{
Eigen::MatrixXd A(3, 3), B(3,1);
/*
x = y[0]
dx = y[1] = dy[0]
ddx = y[2] = dy[1]
dddx = dy[2]
*/
const double r(1);
A << 0, 1, 0,
0, 0, 1,
-24, -26, -9;
B << 0, 0, 1;
//#####################( ODE Equations )################################
Eigen::MatrixXd X(3, 1), dX(3,1);
X << y[0], y[1], y[2];
dX = A*X + B*r;
dy[0] = dX(0,0);
dy[1] = dX(1,0);
dy[2] = dX(2,0);
}
int main(int argc, char **argv)
{
const double dt = 0.01;
runge_kutta_dopri5 < state_type > stepper;
state_type y(3);
// initial values
y[0] = 0.0; // x1
y[1] = 0.0; // x2
y[2] = 0.0; // x3
ofstream data("file.txt");
for (double t(0.0); t <= 5.0; t += dt){
data << t << " " << 2*y[0] << " " << 7*y[1] << " " << 1*y[2] << std::endl;
stepper.do_step(equations, y, t, dt);
}
return 0;
}
And this is the result for all state vector
None of the preceding variables match the results generated by Matlab. Any suggestions to fix this code?
Look at the expression you have for y. When you multiply a 1x3 matrix with a 3x1 matrix, the result should be a 1x1 matrix, where the value of the single element is the dot product of the two matrices. What you're currently doing is element-wise multiplication when you write to data instead of calculating the dot product.
I was writing a program for finding roots for a class, and had finished and got it working perfectly. As I go to turn it in, I see the document requires the .cpp to compile using Visual Studio 2012 - so I try that out. I normally use Dev C++ - and I've come to find it allows me to compile "funky things" such as dynamically declaring arrays without using malloc or new operators.
So, after finding the error associated with how I wrongly defined my arrays - I tried to fix the problem using malloc, calloc, and new/delete and well - it kept giving me memory allocation errors. The whole 46981239487532-byte error.
Now, I tried to "return" the program to the way it used to be and now I can't even get that to work. I'm not even entirely sure how I set up the arrays to work in Dev C++ in the first place. Here the code:
#include <iostream>
#include <stdlib.h>
#include <math.h>
using namespace std;
float newton(float a, float b, float poly[],float n, float *fx, float *derfx);
float horner(float poly[], int n, float x, float *derx);
float bisection(float a, float b, float poly[], float n, float *fx);
int main(int argc, char *argv[])
{
float a, b, derr1 = 0, dummyvar = 0, fr1 = 0, fr0;
float constants[argc-3];
//float* constants = NULL;
//constants = new float[argc-3];
//constants = (float*)calloc(argc-3,sizeof(float));
//In order to get a and b from being a char to floating point, the following lines are used.
//The indexes are set relative to the size of argv array in order to allow for dynamically sized inputs. atof is a char to float converter.
a = atof(argv[argc-2]);
b = atof(argv[argc-1]);
//In order to get a easy to work with array for horners method,
//all of the values excluding the last two are put into a new floating point array
for (int i = 0; i <= argc - 3; i++){
constants[i] = atof(argv[i+1]);
}
bisection(a, b, constants, argc - 3, &fr0);
newton(a, b, constants, argc - 3, &fr1, &derr1);
cout << "f(a) = " << horner(constants,argc-3,a,&dummyvar);
cout << ", f(b) = " << horner(constants,argc-3,b,&dummyvar);
cout << ", f(Bisection Root) = " << fr0;
cout << ", f(Newton Root) = "<<fr1<<", f'(Newton Root) = "<<derr1<<endl;
return 0;
}
// Poly[] is the polynomial constants, n is the number of degrees of the polynomial (the size of poly[]), x is the value of the function we want the solution for.
float horner(float poly[], int n, float x, float *derx)
{
float fx[2] = {0, 0};
fx[0] = poly[0]; // Initialize fx to the largest degree constant.
float derconstant[n];
//float* derconstant = NULL;
//derconstant = new float[n];
//derconstant = (float*)calloc(n,sizeof(float));
derconstant[0] = poly[0];
// Each term is multiplied by the last by X, then you add the next poly constant. The end result is the function at X.
for (int i = 1; i < n; i++){
fx[0] = fx[0]*x + poly[i];
// Each itteration has the constant saved to form the derivative function, which is evaluated in the next for loop.
derconstant[i]=fx[0];
}
// The same method is used to calculate the derivative at X, only using n-1 instead of n.
fx[1] = derconstant[0]; // Initialize fx[1] to the largest derivative degree constant.
for (int i = 1; i < n - 1; i++){
fx[1] = fx[1]*x + derconstant[i];
}
*derx = fx[1];
return fx[0];
}
float bisection(float a, float b, float poly[], float n, float *fx)
{
float r0 =0, count0 = 0;
float c = (a + b)/2; // c is the midpoint from a to b
float fc, fa, fb;
int rootfound = 0;
float *derx;
derx = 0; // Needs to be defined so that my method for horner's method will work for bisection.
fa = horner(poly, n, a, derx); // The following three lines use horner's method to get fa,fb, and fc.
fb = horner(poly, n, b, derx);
fc = horner(poly, n, c, derx);
while ((count0 <= 100000) || (rootfound == 0)) { // The algorithm has a limit of 1000 itterations to solve the root.
if (count0 <= 100000) {
count0++;
if ((c == r0) && (fabs(fc) <= 0.0001)) {
rootfound=1;
cout << "Bisection Root: " << r0 << endl;
cout << "Iterations: " << count0+1 << endl;
*fx = fc;
break;
}
else
{
if (((fc > 0) && (fb > 0)) || ((fc < 0) && (fb < 0))) { // Checks if fb and fc are the same sign.
b = c; // If fc and fb have the same sign, thenb "moves" to c.
r0 = c; // Sets the current root approximation to the last c value.
c = (a + b)/2; // c is recalculated.
}
else
{
a=c; // Shift a to c for next itteration.
r0=c; // Sets the current root approximation to the last c value.
c=(a+b)/2; // Calculate next c for next itteration.
}
fa = horner(poly, n, a, derx); // The following three send the new a,b,and c values to horner's method for recalculation.
fb = horner(poly, n, b, derx);
fc = horner(poly, n, c, derx);
}
}
else
{
cout << "Bisection Method could not find root within 100000 itterations" << endl;
break;
}
}
return 0;
}
float newton(float a, float b, float poly[],float n, float *fx, float *derfx){
float x0, x1;
int rootfound1 = 1, count1 = 0;
x0 = (a + b)/2;
x1 = x0;
float fx0, derfx0;
fx0 = horner(poly, n, x0, &derfx0);
while ((count1 <= 100000) || (rootfound1 == 0)) {
count1++;
if (count1 <= 100000) {
if ((fabs(fx0) <= 0.0001)) {
rootfound1 = 1;
cout << "Newtons Root: " << x1 << endl;
cout << "Iterations: " << count1 << endl;
break;
}
else
{
x1 = x0 - (fx0/derfx0);
x0 = x1;
fx0 = horner(poly, n, x0, &derfx0);
*derfx = derfx0;
*fx = fx0;
}
}
else
{
cout << "Newtons Method could not find a root within 100000 itterations" << endl;
break;
}
}
return 0;
}
So I've spent the past several hours trying to sort this out, and ultimately, I've given in to asking.Everywhere I look has just said to define as
float* constants = NULL;
constants = new float[size];
but this keeps crashing my programs - presumably from allocating too much memory somehow. I've commented out the things I've tried in various ways and combonations. If you want a more tl;dr to the "trouble spots", they are at the very beginning of the main and horner functions.
Here is one issue, in main you allocate space for argc-3 floats (in various ways) for constants but your code in the loop writes past the end of the array.
Change:
for( int i = 0; i<=argc-3; i++){
to
for( int i = 0; i<argc-3; i++){
That alone could be enough to cause your allocation errors.
Edit: Also note if you allocate space for something using new, you need to delete it with delete, otherwise you will continue to use up memory and possibly run out (especially if you do it in a loop of 100,000).
Edit 2: As Galik mentions below, because you are using derconstant = new float[n] to allocate the memory, you need to use delete [] derconstant to free the memory. This is important when you start allocating space for class objects as the delete [] form will call the destructor of each element in the array.