This is following the question I asked in this thread : Link error missing vtable
I defined a class 'function' and two others classes 'polynomial' and 'affine' that inherit from 'function'.
class function {
public:
function(){};
virtual function* clone()const=0;
virtual float operator()(float x)const=0; //gives the image of a number by the function
virtual function* derivative()const=0;
virtual float inverse(float y)const=0;
virtual ~function(){}
};
class polynomial : public function {
protected:
int degree;
private:
float *coefficient;
public:
polynomial(int d);
virtual~polynomial();
virtual function* clone()const;
int get_degree()const;
float operator[](int i)const; //reads coefficient number i
float& operator[](int i); //updates coefficient number i
virtual float operator()(float x)const;
virtual function* derivative()const;
virtual float inverse(float y)const;
};
class affine : public polynomial {
int a;
int b;
//ax+b
public:
affine(int d,float a_, float b_);
function* clone()const;
float operator()(float x)const;
function* derivative()const;
float inverse(float y)const;
~affine(){}
};
Method inverse in polyomial does not seem to work fine. It is based on the Newton method applied to the function x->f(x)-y for fixed y (the element for which we're computing the inverse) and the current polynomial f.
float polynomial::inverse(float y)const
{
int i=0;
float x0=1;
function* deriv=derivative();
float x1=x0+(y-operator()(x0))/(deriv->operator()(x0));
while(i<=100 && abs(x1-x0)>1e-5)
{
x0=x1;
x1=x0+(y-operator()(x0))/(deriv->operator()(x0));
i++;
}
if(abs(x1-x0)<=1e-5)
{
//delete deriv; //I get memory problems when I uncomment this line
return x1;
}
else
{
cout<<"Maximum iteration reached in polynomial method 'inverse'"<<endl;
//delete deriv; //same here
return -1;
}
}
double polynomial::operator()(double x)const
{
double value=0;
for(int i=0;i<=degree;i++) value+=coefficient[i]*pow(x,i);
return value;
}
polynomial* polynomial::derivative()const
{
if(degree==0)
{
return new affine(0,0,0);
}
polynomial* deriv=new polynomial(degree-1);
for(int i=0;i<degree;i++)
deriv[i]=(i+1)*coefficient[i+1];
return deriv;
}
I test this method with p:x->x^3 :
#include "function.h"
int main(int argc, const char * argv[])
{
polynomial p(3);
for(int i=0;i<=2;i++) p[i]=0;
p[3]=1;
cout<<"27^(1/3)="<<p.inverse(27);
return 0;
}
This script outputs 27^(1/3)=Maximum iteration reached in polynomial method 'inverse'
-1 even if I put 10,000 instead of 100. I've read some articles on the internet and it seems that it's a common way to compute the inverse.
the abs function prototype is: int abs(int)
So a test like abs(x1-x0)<=1e-5 won't behave as you expect; you compare a int with a float. In this case the float will be converted to int so it the same as abs(x1-x0)<=0
This is probably why you don't get the expected result - I suggest adding a few more printouts to get to the bottom of things.
Well, the problem was in method 'derivative'. Instead of using the 'operator[]' that I redefined, I used '->coefficient[]' and the main script worked fine for p.inverse(27) (only 14 iterations). I just replaced deriv[i]=(i+1)*coefficient[i+1]; with deriv->coefficient[i]=(i+1)*coefficient[i+1];
Check This Code :
#include<iostream>
#include<cmath>
#include<math.h>
using namespace std;
void c_equation(int choose, double x);
void Processes(double x, double fx1, double fdx1, int choose);
void main()
{
int choose,choose2;
double x;
system("color A");
cout << " " << endl;
cout << "=============================================================" << endl;
cout << "Choose Equation : " << endl;
cout << "_____________________________________" << endl;
cout << "1- x-2sin(x)" << endl;
cout << "2- x^2 + 10 cos(x)" << endl;
cout << "3- e^x - 3x^2" << endl;
cout << " " << endl;
cin >> choose;
cout << "If you have values press 1/ random press 2 :" << endl;
cin >> choose2;
if (choose2 == 1)
{
cout << " " << endl;
cout << "Enter Xo : " << endl;
cin >> x;
c_equation(choose, x);
}
else if (choose2 == 2)
{
x = rand() % 20;
cout << "Xo = " << x << endl;
c_equation(choose, x);
choose2 = NULL;
}
else
{
cout << "Worng Choice !! " << endl;
choose = NULL;
choose2 = NULL;
main();
}
}
void c_equation(int choose, double x)
{
double fx;
double fdx;
double fddx;
double result;
if (choose == 1)
{
fx = x - 2 * sin(x);
fdx = 1 - 2 * cos(x);
fddx = 2 * sin(x);
result = abs((fx * fddx) / pow(fdx, 2));
}
else if (choose == 2)
{
fx = pow(x, 2) + 10 * cos(x);
fdx = 2 * x - 10 * sin(x);
fddx = 2 - 10 * cos(x);
result = abs((fx * fddx) / pow(fdx, 2));
}
else if (choose == 3)
{
fx = exp(x) - 3 * pow(x, 2);
fdx = exp(x) - 6 * x;
fddx = exp(x) - 6;
result = abs((fx * fddx) / pow(fdx, 2));
}
else
{
cout << " " << endl;
}
//------------------------------------------------------------
if (result < 1)
{
cout << "True Equation :) " << endl;
Processes(x, fx, fdx , choose);
}
else
{
system("cls");
cout << "False Equation !!" << endl;
choose = NULL;
x = NULL;
main();
}
}
void Processes(double x, double fx, double fdx , int choose)
{
double xic;
for (int i = 0; i < 3; i++)
{
xic = x - (fx / fdx);
cout << " " << endl;
cout << "Xi = " << x << " " << "F(Xi) = " << fx << " " << " F'(Xi) = " << fdx << " " << " Xi+1 = " << xic << endl;
x = xic;
if (choose == 1)
{
fx = xic - 2 * sin(xic);
fdx = 1 - 2 * cos(xic);
}
else if (choose == 2)
{
fx = pow(xic, 2) + 10 * cos(xic);
fdx = 2 * xic - 10 * sin(xic);
}
else if (choose == 3)
{
fx = exp(xic) - 3 * pow(xic, 2);
fdx = exp(xic) - 6 * xic;
}
}
}
Related
I keep getting an "exception thrown" and "Unhandled exception" error on the last for loop of my code. I am not sure why this is happening, what it means, or how to fix it. The output won't even show up long enough for me to see if it is right. Any help would be appreciated.
The error says : Exception thrown at 0x00855AC9 in Final Project.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.
Unhandled exception at 0x00855AC9 in Final Project.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.
class Geometry {
public:
string color = "blue";
void printColor() {
cout << color << endl;
}
virtual void calArea() {
cout << "Are: 0" << endl;
cout << "Shape: Unknown" << endl;
}
};
class Circle :public Geometry {
private:
double radius;
double area = 0;
public:
Circle() {
radius = 5.0;
}
void calArea() {
area = 3.14 * radius * radius;
cout << "Area: " << ", Shape: Circle, Radius: " << radius << endl;
}
};
class Square :public Geometry {
private:
double side;
double area = 0.0;
public:
Square() {
side = 5.3;
}
void calArea() {
area = side * side;
cout << "Area: " << area << ", Shape: Sqaure, Side: " << side << endl;
}
};
class Cube : public Geometry {
private:
double length;
double width;
double height;
double area;
public:
Cube() {
length = 4.0;
width = 4.0;
height = 4.0;
}
void calArea() {
area = 6 * length * width;
cout << "Area: " << ", Shape: Cube, Length: " << length << ", Width: " << width << ", Height: " << height << endl;
}
};
int main()
{
const int SIZE = 10;
int i;
Geometry* shapes[SIZE];
for ( i = 0; i < SIZE; i++) {
int choice = 1 + rand() % 3;
if (choice == 1) {
shapes[i] = new Circle();
}
else if (choice == 2) {
shapes[i] = new Square();
}
else if (choice == 3) {
shapes[i] = new Cube();
}
for (i = 0; i < SIZE; i++) {
shapes[i]->calArea();
}
}
return 0;
}
Your code has accessed uninitialized memory, the location 0xCCCCCCCC means uninitialized pointer in debug mode in visual studio
0xCC When the code is compiled with the /GZ
option,
uninitialized variables are automatically assigned
to this value (at byte level).
I think the '}' needs to be put before the last loop, then all the pointers in the array have been inited. And it would be better to use std::vector here, my final code uses it.
for ( i = 0; i < SIZE; i++) {
int choice = 1 + rand() % 3;
if (choice == 1) {
shapes[i] = new Circle();
}
else if (choice == 2) {
shapes[i] = new Square();
}
else if (choice == 3) {
shapes[i] = new Cube();
}
for (i = 0; i < SIZE; i++) {
shapes[i]->calArea();
}
}
Need to be change to:
for ( i = 0; i < SIZE; i++) {
int choice = 1 + rand() % 3;
if (choice == 1) {
shapes[i] = new Circle();
}
else if (choice == 2) {
shapes[i] = new Square();
}
else if (choice == 3) {
shapes[i] = new Cube();
}
}
for (i = 0; i < SIZE; i++) {
shapes[i]->calArea();
}
After fixing, your code still has memory leaks. May consider using a smart pointer here. Since we have stored the base type's pointer, we need a virtual destructor to make sure that the memory to be corrected deleted.
For the rand() function, you need to call srand before using it to avoid always get the same random sequence for every run. And it's better to use random since c++11.
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;
class Geometry {
public:
virtual ~Geometry() = default;
string color = "blue";
void printColor() { cout << color << endl; }
virtual void calArea() {
cout << "Are: 0" << endl;
cout << "Shape: Unknown" << endl;
}
};
class Circle : public Geometry {
private:
double radius;
double area = 0;
public:
Circle() { radius = 5.0; }
void calArea() {
area = 3.14 * radius * radius;
cout << "Area: " << area << ", Shape: Circle, Radius: " << radius << endl;
}
};
class Square : public Geometry {
private:
double side;
double area = 0.0;
public:
Square() { side = 5.3; }
void calArea() {
area = side * side;
cout << "Area: " << area << ", Shape: Sqaure, Side: " << side << endl;
}
};
class Cube : public Geometry {
private:
double length;
double width;
double height;
double area;
public:
Cube() {
length = 4.0;
width = 4.0;
height = 4.0;
}
void calArea() {
area = 6 * length * width;
cout << "Area: " << area << ", Shape: Cube, Length: " << length
<< ", Width: " << width << ", Height: " << height << endl;
}
};
int main() {
const int SIZE = 10;
int i;
std::vector<std::unique_ptr<Geometry>> shapes;
for (i = 0; i < SIZE; i++) {
int choice = 1 + rand() % 3;
if (choice == 1) {
shapes.emplace_back(new Circle());
}
else if (choice == 2) {
shapes.emplace_back(new Square());
}
else if (choice == 3) {
shapes.emplace_back(new Cube());
}
}
for (auto& ptr : shapes) {
ptr->calArea();
}
return 0;
}
Online demo
You tryed to call shapes[i] for values of i=0 to 9. These values had not yet been assigned. So you are trying to access the shape at memory location which is not in the memory assigned to your application which should result in a segmentation fault. This is most likely from a missing bracket between your for statements.
Side Note: This would have been easier for you to diagnose if you used the programming convention of declaring temporary variables in the smallest scope. That is, if both of your for statements read
for(int i = 0; i < SIZE; i++) {
you would have recieved a meaningful error for trying to declare i twice and been able to fix the typo.
So, in class for work we have to write a header class for quadratic expression. I have the header file done for the most part, however, when I proceed to run with the given .cpp file to test out the header file, it does not appear to read the values given in the array in the cpp file. When I debug, it just puts in garbage values for the values. To me I thought it made sense and can't see anything wrong with it. Unless am I missing something?
I constructed the following header file...
#pragma once
#include <cmath>
enum roots {
NO_ROOTS = 0,
ONE_ROOT = 1,
TWO_ROOTS = 2,
INFINITE_ROOTS = 3
};
class quadraticExpression
{
private:
double a, b, c;
public:
double evaluate(double x) const;
int getNumberOfRoots() const;
double getFirstRoot() const;
double getSecondRoot() const;
double getACoefficient() const;
double getBCoefficient() const;
double getCCoefficient() const;
quadraticExpression();
quadraticExpression(double a,
double b,
double c);
};
quadraticExpression::quadraticExpression()
{
a = 0;
b = 0;
c = 0;
}
inline quadraticExpression::quadraticExpression(double a, double b, double
c)
{
a = a;
b = b;
c = c;
}
;
double quadraticExpression::evaluate(double x) const
{
double y;
y = (a*(x * x)) + (b * x) + c;
return y;
}
int quadraticExpression::getNumberOfRoots() const
{
//return value from enum
double eins;
double zwei;
eins = getFirstRoot();
zwei = getSecondRoot();
if (eins == 0 && zwei == 0)
{
return TWO_ROOTS;
}
else if (eins == 0 || zwei == 0)
{
return ONE_ROOT;
}
else if (eins != 0 && zwei != 0)
{
return NO_ROOTS;
}
}
double quadraticExpression::getFirstRoot() const
{
//return one x value where y is 0
double root1 = (b * b);
double root2 = (4 * a*c);
double solutionOne;
double zUno;
zUno = (abs(b) + sqrt(root1 - root2)) / (2 * a);
solutionOne = (a*(zUno * zUno)) + (b * zUno) + c;
return solutionOne;
}
double quadraticExpression::getSecondRoot() const
{
//return another x value where y is 0
double root1 = (b * b);
double root2 = (4 * a*c);
double solutionTwo;
double zDos;
zDos = (abs(b) - sqrt(root1 - root2)) / (2 * a);
solutionTwo = (a*(zDos *zDos)) + (b *zDos) + c;
return solutionTwo;
}
double quadraticExpression::getACoefficient() const
{
return a;
}
double quadraticExpression::getBCoefficient() const
{
return b;
}
double quadraticExpression::getCCoefficient() const
{
return c;
}
And here is the .cpp tester file
#include <iostream>
#include "QuadraticExpression.h"
using namespace std;
void evaluateExpression(const quadraticExpression &);
int main()
{
quadraticExpression q[6] = { quadraticExpression(2.1, 3, -7),
quadraticExpression(1.4, 3.9, +7),
quadraticExpression(-.75, 0, 0),
quadraticExpression(0, .3, -7),
quadraticExpression(0, 0, 4),
quadraticExpression() };
for (int i = 0; i<6; i++)
evaluateExpression(q[i]);
return EXIT_SUCCESS;
}
void evaluateExpression(const quadraticExpression &q)
{
int errorsHandled = 0;
cout << q.getACoefficient() << " A " << endl;
cout << q.getBCoefficient() << " B " << endl;
cout << q.getCCoefficient() << " C " << endl;
cout << "f(-5) = " << q.evaluate(-5) << endl;
cout << "f(0) = " << q.evaluate(0) << endl;
cout << "f(5) = " << q.evaluate(5) << endl;
if (q.getNumberOfRoots() == INFINITE_ROOTS)
cout << "The Expression has Infinite Roots" << endl;
else if (q.getNumberOfRoots() == ONE_ROOT)
cout << "The Expression has One Root at x = " << q.getFirstRoot() <<
endl;
else if (q.getNumberOfRoots() == TWO_ROOTS)
{
cout << "The Expression has First Root at x = " << q.getFirstRoot() <<
endl;
cout << "The Expression has Second Root at x = " << q.getSecondRoot() <<
endl;
}
else
cout << "The Expression has No Roots" << endl;
try {
q.getFirstRoot();
}
catch (domain_error e) {
errorsHandled++;
}
try {
q.getSecondRoot();
}
catch (domain_error e) {
errorsHandled++;
}
cout << "Errors Handled: " << errorsHandled << endl;
cout << endl;
cout << endl;
}
I fathom I might not be properly acquiring the data values a, b, and c from the array given in the cpp file therefore it just collects garbage values, however I'm stumped here.
This won't work as you intend.
inline quadraticExpression::quadraticExpression(double a, double b, double c)
{
a = a;
b = b;
c = c;
}
You're just assigning the parameter variables to themselves, not assigning to the member variables of the class. Variables declared in a function take precedence over member variables with the same name.
You should give the parameters different names from the member variables, or assign like this->a = a;.
But if you're just initializing member variables from parameters, you don't need to do assignments at all, initializer lists are preferred (see C++: Where to initialize variables in constructor):
quadraticExpression::quadraticExpression(double a, double b, double c) : a(a), b(b), c(c)
{}
Similarly, the constructor with no arguments should use an initializer list:
quadraticExpression::quadraticExpression() : a(0), b(0), c(0)
{}
So I am working on an implementation of a backprop neural network :
I made this 'NEURON' class , as every beginner in neural network do .
However, I am having weird results : you see, when the dataset is small (like in the case of a XOR function, where there can be only 4 possible permutations (00, 11, 01, 10) for the dataset), the output neuron gives me very close result, no matter how many training iteration (epoch) takes place.
Ex: 1 XOR 1 gives me 0.987, and 1 XOR 0 gives me 0.986, shouldn't they be far apart ?
Here is the class code, in case :
#pragma once
#include <vector>
#include <iostream>
#include "Math.h"
#include "RandomizationUtils.h"
using namespace std;
class ClNeuron
{
public:
enum NEURON_TYPE { NEURON_TYPE_INPUT=1,NEURON_TYPE_HIDDEN=2,NEURON_TYPE_OUTPUT=3 };
private:
static const int CONST_DEFAULT_INPUT_NUMBER_PER_NEURON = 20;
static const double CONST_DEFAULT_MOMENTUM_VALUE = 0.4;
//Connection between 2 neurons
struct NEURON_CONNECTION
{
double m_weight;
double m_data;
//Last modification done to the weight
double m_weight_last_delta;
double m_momentum_value;
ClNeuron* m_source_neuron;
ClNeuron* m_target_neuron;
};
//Initialization function
void Init(unsigned long p_uid,NEURON_TYPE p_type);
bool m_initialized;
//All of the output connection of this neuron
vector<NEURON_CONNECTION*> m_output_connections;
//Al of the input connection of this neuron
vector<NEURON_CONNECTION*> m_input_connections;
//Tmp internal result buffer (containing all weights multiplicated by their inputs)
double m_result_buffer;
//special weight that always has an input of 1.0
NEURON_CONNECTION m_bias;
public:
//the type of this neuron
NEURON_TYPE m_type;
ClNeuron(NEURON_TYPE p_type);
ClNeuron(unsigned long p_uid,NEURON_TYPE p_type);
ClNeuron(unsigned long p_uid);
ClNeuron();
//Connect this neuron's output to another / others neurons' input
bool AddOutputConnection(ClNeuron* p_neuron);
//This neuron got a request to have a new input
NEURON_CONNECTION* InputConnectionRequest(ClNeuron* p_source_neuron);
//Tell the neuron to fire the sum of the processed inputs
double Fire();
//Tell the neuron to fire a particular data
double Fire(double p_data);
//Function updating all of the current neuron's weight of the OUTPUT connections , depending on an error ratio
void UpdateWeights(double p_wanted_output);
//Sum all the weight * their respective inputs into an internal buffer
void ProcessInputs();
//Print neuron & connections & weights
void PrintNeuronData();
//Unique ID of this neuron
unsigned long m_uid;
//This neuron's calculated error_delta
double m_error_gradient;
};
ClNeuron::NEURON_CONNECTION* ClNeuron::InputConnectionRequest(ClNeuron* p_neuron)
{
NEURON_CONNECTION* connection = new NEURON_CONNECTION;
if(!connection)
{
cout << "Error creating new connection, memory full ?" << endl << flush;
return NULL;
}
connection->m_weight = GetRandomDouble(-1,1);
connection->m_data = 0;
connection->m_momentum_value = CONST_DEFAULT_MOMENTUM_VALUE;
connection->m_source_neuron = p_neuron;
connection->m_target_neuron = this;
m_input_connections.push_back(connection);
return connection;
}
bool ClNeuron::AddOutputConnection(ClNeuron* p_neuron)
{
//If the remote neuron accept the us as a new input, then we add it to output list
NEURON_CONNECTION* connection = p_neuron->InputConnectionRequest(this);
if(!connection)
{
return false;
}
m_output_connections.push_back(connection);
return true;
}
double ClNeuron::Fire()
{
return Fire(m_result_buffer);
}
double ClNeuron::Fire(double p_data)
{
if(m_output_connections.size()==0)
{
cout << "Final neuron " << m_uid << " return " << p_data << endl;
return p_data;
}
for(unsigned long i=0;i<m_output_connections.size();i++)
{
m_output_connections[i]->m_data = p_data;
}
return 1;
}
void ClNeuron::ProcessInputs()
{
m_result_buffer = 0;
for(unsigned long i=0;i<m_input_connections.size();i++)
{
m_result_buffer += m_input_connections[i]->m_weight * m_input_connections[i]->m_data;
}
m_result_buffer += m_bias.m_weight ;
//sigmoid the sum
m_result_buffer = Sigmoid(m_result_buffer);
}
void ClNeuron::UpdateWeights(double p_wanted_output)
{
//Update weights from neuron to all of its inputs NOTE : p_wanted_output is the output of THIS neuron (in case their is many output neuron in the network)
if(m_type == NEURON_TYPE_OUTPUT)
{
m_error_gradient = (p_wanted_output - m_result_buffer) * SigmoidDerivative(m_result_buffer);
//Adjust the bias of this neuron
double weight_delta = 1 * m_error_gradient * 1 ;
double momentum = m_bias.m_weight_last_delta * m_bias.m_momentum_value;
m_bias.m_weight += weight_delta + momentum;
m_bias.m_weight_last_delta = weight_delta;
}
else if(m_type == NEURON_TYPE_HIDDEN)
{
double error_deriative = SigmoidDerivative(m_result_buffer);
double tmpBuffer = 0.00;
for(unsigned long i=0;i<m_output_connections.size();i++)
{
tmpBuffer += (m_output_connections[i]->m_target_neuron->m_error_gradient * m_output_connections[i]->m_weight);
}
m_error_gradient = error_deriative * tmpBuffer;
//Adjust the weights for this neuron's OUTPUT connections
for(unsigned long i=0;i<m_output_connections.size();i++)
{
double weight_delta = 1 * m_output_connections[i]->m_target_neuron->m_error_gradient * m_result_buffer ;
double momentum = m_output_connections[i]->m_weight_last_delta * m_output_connections[i]->m_momentum_value;
m_output_connections[i]->m_weight += weight_delta + momentum;
m_output_connections[i]->m_weight_last_delta = weight_delta;
}
//Adjust the bias of this neuron
double weight_delta = 1 * m_error_gradient * 1 ;
double momentum = m_bias.m_weight_last_delta * m_bias.m_momentum_value;
m_bias.m_weight += weight_delta + momentum;
m_bias.m_weight_last_delta = weight_delta;
}
if(m_type == NEURON_TYPE_INPUT)
{
//Adjust the weights for this neuron's OUTPUT connections
for(unsigned long i=0;i<m_output_connections.size();i++)
{
double weight_delta = 1 * m_output_connections[i]->m_target_neuron->m_error_gradient * m_result_buffer ;
double momentum = m_output_connections[i]->m_weight_last_delta * m_output_connections[i]->m_momentum_value;
m_output_connections[i]->m_weight += weight_delta + momentum;
m_output_connections[i]->m_weight_last_delta = weight_delta;
}
}
}
void ClNeuron::PrintNeuronData()
{
cout << endl << "========================================" << endl;
cout << "Neuron #" << m_uid << " has " << m_input_connections.size() << " input connection" << endl << endl;
for(unsigned long i=0;i<m_input_connections.size();i++)
{
cout << "----> " << "conn." << i << " | Src ID: " << m_input_connections[i]->m_source_neuron->m_uid << " | W: "<< m_input_connections[i]->m_weight << " | D: "<< m_input_connections[i]->m_data << " | RB : " << m_result_buffer << " | EF: " << endl;
}
cout << "Neuron #" << m_uid << " has " << m_output_connections.size() << " output connection" << endl << endl;
for(unsigned long i=0;i<m_output_connections.size();i++)
{
cout << "----> " << "conn." << i << " | Dst ID: " << m_output_connections[i]->m_target_neuron->m_uid << " | W: "<< m_output_connections[i]->m_weight << " | D: "<< m_output_connections[i]->m_data << " | RB : " << m_result_buffer << " | EF: " << endl;
}
cout << endl << "========================================" << endl;
}
void ClNeuron::Init(unsigned long p_uid,NEURON_TYPE p_type)
{
m_initialized = false;
m_output_connections.clear();
m_input_connections.clear();
m_input_connections.reserve(CONST_DEFAULT_INPUT_NUMBER_PER_NEURON);
m_type = p_type;
m_uid = rand() % RAND_MAX;
m_result_buffer = 0;
m_bias.m_weight = GetRandomDouble(-1,1);
m_bias.m_data = 0;
m_bias.m_momentum_value = CONST_DEFAULT_MOMENTUM_VALUE;
m_bias.m_source_neuron = NULL;
m_bias.m_target_neuron = this;
m_initialized = true;
}
ClNeuron::ClNeuron(unsigned long p_uid,NEURON_TYPE p_type)
{
Init(p_uid,p_type);
}
ClNeuron::ClNeuron(NEURON_TYPE p_type)
{
Init(0,p_type);
}
ClNeuron::ClNeuron(unsigned long p_uid)
{
Init(p_uid,NEURON_TYPE_HIDDEN);
}
ClNeuron::ClNeuron()
{
Init(0,NEURON_TYPE_HIDDEN);
}
The problem was the BIAS weight value for each neuron :
More precisely, the error gradient was always 0 for the bias, (causing the weight_delta of 0), which finally was causing the bias not to update its output weights.
I am trying to solve a quadratic equation using the bisection method. When trying to evaluate the roots I get this error: "no matching function for call".
#include "assign4.h"
#include <iostream>
using namespace std;
int main(int argc, char * argv[]){
solution s;
double root;
cout << "Enter interval endpoints: ";
cin >> s.xLeft >> s.xRight;
cout << "Enter tolerance: ";
cin >> s.epsilon;
root = s.bisect (s.xLeft, s.xRight, s.epsilon, s.f, s.error);
if (!(s.error))
cout << "Root found at " << root << "\nValue of f(x) at root is: " << s.f(root);
else
cout << "The solution of a quadratic equation with coefficients: " << endl;
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
cout << "has not been found." << endl;
return 0;
}
The error occurs where root = ... it seems to have a problem with my function f but I don't understand what is wrong. The following two bits of code are my class and class implementation files. We just started working with classes so I am uncertain if my problem lies there or simply in the above code.
#ifndef ASSIGN4_H
#define ASSIGN4_H
class solution {
public:
double xLeft, xRight;
double epsilon;
bool error;
double bisect(double, double, double, double f(double), bool&);
double f(double);
};
#endif // ASSIGN4_H
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "assign4.h"
#include <iostream>
#include <cmath>
using namespace std;
double solution::bisect (double xLeft, double xRight, double epsilon, double func(double), bool& error) {
double xMid;
double fLeft, fRight;
double fMid;
fLeft = f(xLeft);
fRight = f(xRight);
error = (fLeft * fRight) > 0;
if (error)
return -999.0;
while (fabs (xLeft - xRight) > epsilon) {
xMid = (xLeft + xRight) / 2.0;
fMid = f (xMid);
if (fMid == 0.0)
return xMid;
else if (fLeft * fMid < 0.0)
xRight = xMid;
else
xLeft = xMid;
cout << "New Interval is [" << xLeft << ", " << xRight << "]" << endl;
}
return (xLeft + xRight) / 2.0;
}
double solution::f (double x) {
return ((5 * pow(x,2.0)) + (5 * x) + 3);
}
The 4th parameter is a function pointer,
double bisect(double, double, double, double f(double), bool&);
When you call this function:
root = s.bisect (s.xLeft, s.xRight, s.epsilon, s.f, s.error);
While the member fiction double f(double) is not the same type as that parameter because this is C++ member function and not static, so the 'this' parameter is added this member function when compiling.
type add the static key word to the function.
The syntax for a function pointer is usually: double (*f)(double). Aside from that, you are attempting to pass a member function through a non-member-function pointer. Since your function does not use any member variables, the simplest solution would be to make it static:
class solution {
// ...
static double f(double);
};
If you want to use pointers to member functions.
Change
double bisect(double, double, double, double f(double), bool&);
to
double bisect(double, double, double, double (solution::*f)(double), bool&);
in declaration and definition.
Change the call from
root = s.bisect (s.xLeft, s.xRight, s.epsilon, s.f, s.error);
to
root = s.bisect (s.xLeft, s.xRight, s.epsilon, &solution::f, s.error);
This is what I have that compiles and links successfully for me.
#include <iostream>
#include <typeinfo>
#include <math.h>
using namespace std;
class solution {
public:
double xLeft, xRight;
double epsilon;
bool error;
double bisect(double, double, double, double (solution::*f)(double), bool&);
double f(double);
};
using namespace std;
double solution::bisect (double xLeft, double xRight, double epsilon, double (solution::*func)(double), bool& error) {
double xMid;
double fLeft, fRight;
double fMid;
fLeft = (this->*func)(xLeft);
fRight = (this->*func)(xRight);
error = (fLeft * fRight) > 0;
if (error)
return -999.0;
while (fabs (xLeft - xRight) > epsilon) {
xMid = (xLeft + xRight) / 2.0;
fMid = (this->*func)(xMid);
if (fMid == 0.0)
return xMid;
else if (fLeft * fMid < 0.0)
{
xRight = xMid;
fRight = fMid;
}
else
{
xLeft = xMid;
fLeft = fMid;
}
cout << "New Interval is [" << xLeft << ", " << xRight << "]" << endl;
}
return (xLeft + xRight) / 2.0;
}
double solution::f (double x) {
return ((5 * pow(x,2.0)) + (5 * x) + 3);
}
int main(int argc, char * argv[]){
solution s;
double root;
cout << "Enter interval endpoints: ";
cin >> s.xLeft >> s.xRight;
cout << "Enter tolerance: ";
cin >> s.epsilon;
root = s.bisect (s.xLeft, s.xRight, s.epsilon, &solution::f, s.error);
if (!(s.error))
cout << "Root found at " << root << "\nValue of f(x) at root is: " << s.f(root) << endl;
else
{
cout << "The solution of a quadratic equation with coefficients: " << endl;
// cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
cout << "has not been found." << endl;
}
return 0;
}
I believe it has to do with your callback function. Typically you get that kind of compiler error when you use an incorrect function call. If you want this kind of callback function, you may want to look into function pointers.
http://www.cprogramming.com/tutorial/function-pointers.html
I am having trouble with the output part of the problem, I am getting errors on the lines that say bottom right, top left, and dimension. What am i doing wrong?
I have tried many things and I just do not know how to get it to work correctly, and we have not gone over anything like this kind of output in class:
#include <iostream>
#include <cmath>
using namespace std;
class Point
{
private:
double px;
double py;
public:
void setX(const double x);
void setY(const double y);
double getX() const;
double getY() const;
};
class Triangle
{
private:
Point blPoint;
double length, height;
public:
// member functions
void setBottomLeftX(const double x);
void setBottomLeftY(const double y);
void setLength(const double inLength);
void setHeight(const double inHeight);
Point getBottomLeft() const;
Point getBottomRight() const;
Point getTopLeft() const;
double getLength() const;
double getHeight() const;
double perimeter() const;
double hypotenuse() const;
void scaleLength(const double sx);
void scaleHeight(const double sy);
void display() const;
};
// FUNCTION PROTOTYPES GO HERE:
double read_triangle(Triangle & tri);
int main()
{
// Define local variables
Triangle tri;
double sx, sy;
//Prompt the user for triangle information and fill Class Triangle object, tri,
//with this information
read_triangle(tri);
// Display triangle information
tri.display();
// Prompt and read scale factors to change length and height
cout << "Enter scale factor in x direction: ";
cin >> sx;
cout << "Enter scale factor in y direction: ";
cin >> sy;
// Apply scale factors
tri.scaleLength(sx);
tri.scaleHeight(sy);
// Display triangle information
tri.display();
return 0;
}
// FUNCTION DEFINITIONS GO HERE:
// CLASS MEMBER FUNCTION DEFINITINOS GO HERE:
void Point::setX(const double x)
{
px = x;
}
void Point::setY(const double y)
{
py = y;
}
double Point::getX() const
{
return (px);
}
double Point::getY() const
{
return (py);
}
void Triangle::setBottomLeftX(const double x)
{
/* INSERT YOUR CODE */
blPoint.setX(x);
}
void Triangle::setBottomLeftY(const double y)
{
/* INSERT YOUR CODE */
blPoint.setY(y);
}
void Triangle::setLength(const double inLength)
{
/* INSERT YOUR CODE */
length=inLength;
}
void Triangle::setHeight(const double inHeight)
{
/* INSERT YOUR CODE */
height=inHeight;
}
Point Triangle::getBottomLeft() const
{
/* INSERT YOUR CODE */
return (blPoint);
}
Point Triangle::getBottomRight() const
{
/* INSERT YOUR CODE */
Point getBottomRight;
double mx = (blPoint.getX()+ length);
getBottomRight.setX(mx);
return(getBottomRight);
}
Point Triangle::getTopLeft() const
{
/* INSERT YOUR CODE */
Point getTopLeft;
double my = (blPoint.getY()+ height);
getTopLeft.setY(my);
return (getTopLeft);
}
double Triangle::getLength() const
{
/* INSERT YOUR CODE */
return (length);
}
double Triangle::getHeight() const
{
/* INSERT YOUR CODE */
return (height);
}
double Triangle::hypotenuse() const
{
/* INSERT YOUR CODE */
//hypotenuse = (sqrt((height * height)+(length * length)));
return (sqrt((height * height)+(length * length)));
}
double Triangle::perimeter() const
{
/* INSERT YOUR CODE */
//perimeter = ((sqrt((height * height)+(length * length)))+ height + length);
return ((sqrt((height * height)+(length * length)))+ height + length);
}
void Triangle::scaleLength(const double scalefact)
{
/* INSERT YOUR CODE */
length = scalefact * length;
}
void Triangle::scaleHeight(const double scalefact)
{
/* INSERT YOUR CODE */
height = scalefact * height;
}
void Triangle::display() const
{
/* INSERT YOUR CODE */
cout <<"---------------------------------------" << endl;
cout << "Lower Left Vertex (" << blPoint.getX() << ", " << blPoint.getY() << ')' <<endl;
cout << "Top Left Vertex (" << blPoint.getX() << ", " << getTopLeft.getY() << ')' << endl;
cout << "Bottom Right Vertex (" << getBottomRight.getX() << ", " << blPoint.getY() << ')' << endl;
cout << "Dimensions (" << getBottomRight.getX()- blPoint.getX() << ", " << getTopleft.getY() - blPoint.getY() << ')' << endl;
cout << "Hypotenuse = " << hypotenuse() << endl;
cout << "Perimeter = " << perimeter() << endl;
cout <<"---------------------------------------" << endl;
}
double read_triangle(Triangle & tri)
{
/* INSERT YOUR CODE */
double x, y, inLength, inHeight;
cout << "Enter bottom left x coordinate: ";
cin >> x;
tri.setBottomLeftX(x);
cout << "Enter bottom left y coordinate: ";
cin >> y ;
tri.setBottomLeftY(y);
cout << "Enter length: ";
cin >> inLength;
tri.setLength(inLength);
cout << "Enter Height: ";
cin >> inHeight;
tri.setHeight(inHeight);
}
You are using the functions like they are variables you need to add () to call them correctly:
cout << "Top Left Vertex (" << blPoint.getX() << ", " << getTopLeft().getY() << ')' << endl;
^^
cout << "Bottom Right Vertex (" << getBottomRight().getX() << ", " << blPoint.getY() << ')' << endl;
^^
cout << "Dimensions (" << getBottomRight().getX()- blPoint.getX() << ", " << getTopLeft().getY() - blPoint.getY() << ')' << endl;
^^ ^^
Also, read_triangle does not have a return statement but you declare that it returns double. Flowing off the end of a value returning function is undefined behavior and therefore you can not rely on the results. It does not look like you are using the results so you may want to just change the function to return void and that will fix it.