The error is on line 76 int res[mSize]; the problem is on mSize. It seems like a simple fix but I can't figure it out. If someone can figure it out or point me in the right direction that would be greatly appreciated.
Also, the deconstructor ~MyContainer(), I am not sure if I am using it right or if there is a correct place to put it.
Here is my code:
#include <iostream>
using namespace std;
class MyContainer
{
private:
int* mHead; // head of the member array
int mSize; // size of the member array
public:
MyContainer();
MyContainer(int*, int);
//~MyContainer();
void Add(int);
void Delete(int);
int GetSize();
void DisplayAll();
int FindMissing();
~MyContainer() {}
};
MyContainer::MyContainer()
{
mHead = NULL;
mSize = 0;
}
MyContainer::MyContainer(int* a, int b)
{
mHead = a;
mSize = b;
}
void MyContainer::Add(int a)
{
*(mHead + mSize) = a;
mSize++;
}
void MyContainer::Delete(int a)
{
int index;
for (int i = 0; i < mSize; i++)
{
if (*(mHead + i) == a)
{
index = i;
break;
}
}
for (int i = index; i < mSize; i++)
{
*(mHead + i) = *(mHead + i + 1);
}
mSize--;
}
int MyContainer::GetSize()
{
return mSize;
}
void MyContainer::DisplayAll()
{
cout << "\n";
for (int i = 0; i < mSize; i++)
{
cout << *(mHead + i) << " ";
}
}
int MyContainer::FindMissing()
{
int res[mSize];
int temp;
int flag = 0;
for (int i = 1; i <= mSize; i++)
{
flag = 0;
for (int j = 0; j < mSize; j++)
{
if (*(mHead + j) == i)
{
flag = 1;
break;
}
}
if (flag == 0)
{
temp = i;
break;
}
}
return temp;
}
int main()
{
const int cSize = 5;
int lArray[cSize] = { 2, 3, 7, 6, 8 };
MyContainer lContainer(lArray, cSize);
lContainer.DisplayAll();
lContainer.Delete(7);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl; lContainer.Add(-1);
lContainer.Add(-10);
lContainer.Add(15);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl;
cout << "First missing positive is: " << lContainer.FindMissing() << endl;
system("PAUSE"); return 0;
}
int res[mSize];
The size of the array mSize must be known at compile time. You cannot use a variable here. An option may be to define a macro with an largish value that will not exceeded.
static const int kLargeSize =100;
int res[kLargeSize];
Edited in response to the comments - const and constexpr are a better option than a macro.
Or even better, you can use std::vector - https://en.cppreference.com/w/cpp/container/vector
I am using following code to run kmeans algorithm on Iris flower dataset- https://github.com/marcoscastro/kmeans/blob/master/kmeans.cpp
I have modified the above code to read input from files. Below is my code -
#include <iostream>
#include <vector>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <fstream>
using namespace std;
class Point
{
private:
int id_point, id_cluster;
vector<double> values;
int total_values;
string name;
public:
Point(int id_point, vector<double>& values, string name = "")
{
this->id_point = id_point;
total_values = values.size();
for(int i = 0; i < total_values; i++)
this->values.push_back(values[i]);
this->name = name;
this->id_cluster = -1;
}
int getID()
{
return id_point;
}
void setCluster(int id_cluster)
{
this->id_cluster = id_cluster;
}
int getCluster()
{
return id_cluster;
}
double getValue(int index)
{
return values[index];
}
int getTotalValues()
{
return total_values;
}
void addValue(double value)
{
values.push_back(value);
}
string getName()
{
return name;
}
};
class Cluster
{
private:
int id_cluster;
vector<double> central_values;
vector<Point> points;
public:
Cluster(int id_cluster, Point point)
{
this->id_cluster = id_cluster;
int total_values = point.getTotalValues();
for(int i = 0; i < total_values; i++)
central_values.push_back(point.getValue(i));
points.push_back(point);
}
void addPoint(Point point)
{
points.push_back(point);
}
bool removePoint(int id_point)
{
int total_points = points.size();
for(int i = 0; i < total_points; i++)
{
if(points[i].getID() == id_point)
{
points.erase(points.begin() + i);
return true;
}
}
return false;
}
double getCentralValue(int index)
{
return central_values[index];
}
void setCentralValue(int index, double value)
{
central_values[index] = value;
}
Point getPoint(int index)
{
return points[index];
}
int getTotalPoints()
{
return points.size();
}
int getID()
{
return id_cluster;
}
};
class KMeans
{
private:
int K; // number of clusters
int total_values, total_points, max_iterations;
vector<Cluster> clusters;
// return ID of nearest center (uses euclidean distance)
int getIDNearestCenter(Point point)
{
double sum = 0.0, min_dist;
int id_cluster_center = 0;
for(int i = 0; i < total_values; i++)
{
sum += pow(clusters[0].getCentralValue(i) -
point.getValue(i), 2.0);
}
min_dist = sqrt(sum);
for(int i = 1; i < K; i++)
{
double dist;
sum = 0.0;
for(int j = 0; j < total_values; j++)
{
sum += pow(clusters[i].getCentralValue(j) -
point.getValue(j), 2.0);
}
dist = sqrt(sum);
if(dist < min_dist)
{
min_dist = dist;
id_cluster_center = i;
}
}
return id_cluster_center;
}
public:
KMeans(int K, int total_points, int total_values, int max_iterations)
{
this->K = K;
this->total_points = total_points;
this->total_values = total_values;
this->max_iterations = max_iterations;
}
void run(vector<Point> & points)
{
if(K > total_points)
return;
vector<int> prohibited_indexes;
printf("Inside run \n");
// choose K distinct values for the centers of the clusters
printf(" K distinct cluster\n");
for(int i = 0; i < K; i++)
{
while(true)
{
int index_point = rand() % total_points;
if(find(prohibited_indexes.begin(), prohibited_indexes.end(),
index_point) == prohibited_indexes.end())
{
printf("i= %d\n",i);
prohibited_indexes.push_back(index_point);
points[index_point].setCluster(i);
Cluster cluster(i, points[index_point]);
clusters.push_back(cluster);
break;
}
}
}
int iter = 1;
printf(" Each point to nearest cluster\n");
while(true)
{
bool done = true;
// associates each point to the nearest center
for(int i = 0; i < total_points; i++)
{
int id_old_cluster = points[i].getCluster();
int id_nearest_center = getIDNearestCenter(points[i]);
if(id_old_cluster != id_nearest_center)
{
if(id_old_cluster != -1)
clusters[id_old_cluster].removePoint(points[i].getID());
points[i].setCluster(id_nearest_center);
clusters[id_nearest_center].addPoint(points[i]);
done = false;
}
}
// recalculating the center of each cluster
for(int i = 0; i < K; i++)
{
for(int j = 0; j < total_values; j++)
{
int total_points_cluster = clusters[i].getTotalPoints();
double sum = 0.0;
if(total_points_cluster > 0)
{
for(int p = 0; p < total_points_cluster; p++)
sum += clusters[i].getPoint(p).getValue(j);
clusters[i].setCentralValue(j, sum / total_points_cluster);
}
}
}
if(done == true || iter >= max_iterations)
{
cout << "Break in iteration " << iter << "\n\n";
break;
}
iter++;
}
// shows elements of clusters
for(int i = 0; i < K; i++)
{
int total_points_cluster = clusters[i].getTotalPoints();
cout << "Cluster " << clusters[i].getID() + 1 << endl;
for(int j = 0; j < total_points_cluster; j++)
{
cout << "Point " << clusters[i].getPoint(j).getID() + 1 << ": ";
for(int p = 0; p < total_values; p++)
cout << clusters[i].getPoint(j).getValue(p) << " ";
string point_name = clusters[i].getPoint(j).getName();
if(point_name != "")
cout << "- " << point_name;
cout << endl;
}
cout << "Cluster values: ";
for(int j = 0; j < total_values; j++)
cout << clusters[i].getCentralValue(j) << " ";
cout << "\n\n";
}
}
};
int main(int argc, char *argv[])
{
srand(time(NULL));
int total_points, total_values, K, max_iterations, has_name;
ifstream inFile("datafile.txt");
if (!inFile) {
cerr << "Unable to open file datafile.txt";
exit(1); // call system to stop
}
inFile >> total_points >> total_values >> K >> max_iterations >> has_name;
cout << "Details- \n";
vector<Point> points;
string point_name,str;
int i=0;
while(inFile.eof())
{
string temp;
vector<double> values;
for(int j = 0; j < total_values; j++)
{
double value;
inFile >> value;
values.push_back(value);
}
if(has_name)
{
inFile >> point_name;
Point p(i, values, point_name);
points.push_back(p);
i++;
}
else
{
inFile >> temp;
Point p(i, values);
points.push_back(p);
i++;
}
}
inFile.close();
KMeans kmeans(K, total_points, total_values, max_iterations);
kmeans.run(points);
return 0;
}
Output of code is -
Details-
15043100000Inside run
K distinct cluster i= 0
Segmentation fault
When I run it in gdb, the error shown is -
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401db6 in Point::setCluster (this=0x540, id_cluster=0)
at kmeans.cpp:41
41 this->id_cluster = id_cluster;
I am stuck at this as I cannot find the cause for this segmentation fault.
My dataset file looks like -
150 4 3 10000 1
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
. . .
7.0,3.2,4.7,1.4,Iris-versicolor
6.4,3.2,4.5,1.5,Iris-versicolor
6.9,3.1,4.9,1.5,Iris-versicolor
5.5,2.3,4.0,1.3,Iris-versicolor
6.5,2.8,4.6,1.5,Iris-versicolor
. . .
in KMeans::run(vector<Point>&) you call points[index_point].setCluster(i); without any guarantee that index_point is within bounds.
index_point is determined by int index_point = rand() % total_points;, and total_points is retrieved from the input file "datafile.txt" which could be anything. It certainly does not have to match points.size(), but it should. Make sure it does, or just use points.size() instead.
A bit offtopic, but using rand() and only using modulo is almost always wrong. If you use C++11 or newer, please consider using std::uniform_int_distribution.
points[index_point].setCluster(i); could be accessing the vector out of bounds. The code you quoted actually always sets a number of total_points in the vector points before calling run, while your modified code just reads until end of file and has no guarantees that the number of total points passed to the constructor of KMeans matches the value of entries in points. Either fix your file I/O or fix the logic of bounds checking.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
So far, I wrote my code in C (performance is of utmost importance). However, I would like to start writing my algorithms in a generic way. So, I decided to try out C++. I took a simple code in C and translated it into C++ with templates. To my disappointment, the C++ code runs 2.5 times slower. (the C code is compiled with gcc -O3; the C++ code is compiled with g++ -O3)
Am I doing something wrong in C++? Why is there such a performance hit?
Here is the C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static int df_output = 0;
int nCalls = 0;
typedef struct {
int *pancakes;
int n;
} STATE;
STATE **solution;
void shuffle(STATE *s) {
int i;
for (i = 0; i < s->n; i++) {
int i1 = rand() % s->n;
int i2 = rand() % s->n;
int temp = s->pancakes[i1];
s->pancakes[i1] = s->pancakes[i2];
s->pancakes[i2] = temp;
}
}
STATE *copyState(STATE *s) {
STATE *res = malloc(sizeof(STATE));
res->n = s->n;
res->pancakes = (int *)malloc(res->n * sizeof(int));
memcpy(res->pancakes, s->pancakes, res->n * sizeof(int));
return res;
}
// reverse n pancakes
void makeMove(STATE *s, int n) {
int i;
for (i = 0; i < n/2; i++) {
int temp = s->pancakes[i];
s->pancakes[i] = s->pancakes[n - 1 - i];
s->pancakes[n - 1 - i]=temp;
}
}
void printState(STATE *s) {
int i;
printf("[");
for (i = 0; i < s->n; i++) {
printf("%d", s->pancakes[i]);
if (i < s->n - 1)
printf(", ");
}
printf("]");
}
int heuristic(STATE *s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s->n; i++)
if (abs(s->pancakes[i]-s->pancakes[i-1])>1)
res++;
if (s->pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) printf("\t");
}
int df(STATE *s, int g, int left) {
int h = heuristic(s), i;
if (g == 0) printf("Thereshold: %d\n", left);
if (df_output) {
tabs(g);
printf("g=%d,left=%d ", g, left); printState(s); printf("\n");}
if (h == 0) {
assert(left == 0);
solution = (STATE **)malloc((g+1) * sizeof(STATE *));
solution[g] = copyState(s);
return 1;
}
if (left == 0)
return 0;
for (i = 2; i <= s->n; i++) {
makeMove(s, i);
if (df(s, g+1, left-1)) {
makeMove(s, i);
solution[g] = copyState(s);
return 1;
}
makeMove(s, i);
}
return 0;
}
void ida(STATE *s) {
int threshold = 0, i;
while (!df(s, 0, threshold)) threshold++;
for (i = 0; i <= threshold; i++) {
printf("%d. ", i);
printState(solution[i]);
printf("\n");
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
STATE *s = (STATE *)malloc(sizeof(STATE));
int i, n;
int myInstance[] = {0,5,4,7,2,6,1,3};
s->n = 8;
s->pancakes = myInstance;
printState(s); printf("\n");
ida(s);
printf("%d calls to heuristic()", nCalls);
return 0;
}
Here is the C++ code:
#include <iostream>
#include "stdlib.h"
#include "string.h"
#include "assert.h"
using namespace std;
static int df_output = 0;
int nCalls = 0;
class PancakeState {
public:
int *pancakes;
int n;
PancakeState *copyState();
void printState();
};
PancakeState *PancakeState::copyState() {
PancakeState *res = new PancakeState();
res->n = this->n;
res->pancakes = (int *)malloc(this->n * sizeof(int));
memcpy(res->pancakes, this->pancakes,
this->n * sizeof(int));
return res;
}
void PancakeState::printState() {
int i;
cout << "[";
for (i = 0; i < this->n; i++) {
cout << this->pancakes[i];
if (i < this->n - 1)
cout << ", ";
}
cout << "]";
}
class PancakeMove {
public:
PancakeMove(int n) {this->n = n;}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
int bf(PancakeState &);
PancakeMove *getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
int Pancake::bf(PancakeState &s) {
return s.n - 1;
}
PancakeMove *Pancake::getMove(int i) {
return new PancakeMove(i + 2);
}
// reverse n pancakes
void Pancake::makeMove(PancakeState &s, PancakeMove &m) {
int i;
int n = m.n;
for (i = 0; i < n/2; i++) {
int temp = s.pancakes[i];
s.pancakes[i] = s.pancakes[n - 1 - i];
s.pancakes[n - 1 - i]=temp;
}
}
void Pancake::unmakeMove(PancakeState &state, PancakeMove &move) {
makeMove(state, move);
}
int Pancake::heuristic(PancakeState &s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s.n; i++)
if (abs(s.pancakes[i]-s.pancakes[i-1])>1)
res++;
if (s.pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) cout << "\t";
}
template <class Domain, class State, class Move>
class Alg {
public:
State **solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
void ida(Domain &d, State &s);
};
template <class Domain, class State, class Move>
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
cout << "Thereshold:" << this->threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
solution = (State **)malloc((g+1) * sizeof(State *));
solution[g] = s.copyState();
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
Move *move = d.getMove(i);
d.makeMove(s, *move);
if (this->df(d, s, g+1)) {
d.unmakeMove(s, *move);
solution[g] = s.copyState();
delete move;
return 1;
}
d.unmakeMove(s, *move);
delete move;
}
return 0;
}
template <class Domain, class State, class Move>
void Alg<Domain, State, Move>::ida(Domain &d, State &s) {
int i;
this->threshold = 0;
while (!this->df(d, s, 0)) threshold++;
for (i = 0; i <= threshold; i++) {
cout << i << ".";
this->solution[i]->printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
Pancake *d = new Pancake();
PancakeState *s = new PancakeState();
int myInstance[] = {0,5,4,7,2,6,1,3};
s->pancakes = myInstance;
s->n = 8;
s->printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
alg->ida(*d, *s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
You have a lot of malloc() and operator new calls in there. Stop doing that, and performance will improve. And don't use malloc() in C++, use operator new always.
For example, PancakeMove is a small, trivial struct. But you allocate instances of it dynamically, which is slow. Just pass it around by value.
Basically, you are allocating a lot of small things on the heap instead of on the stack. That's pretty "expensive", so will take extra time.
This code (which is modified from your original code) runs within 1ms of the C code:
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <vector>
using namespace std;
static int df_output = 0;
int nCalls = 0;
class PancakeState {
public:
PancakeState(int n) : n(n), pancakes(n)
{
}
PancakeState(int n, int *v) : n(n), pancakes(n)
{
for(int i = 0; i < n; i++)
pancakes[i] = v[i];
}
PancakeState(): n(0) {}
public:
vector<int> pancakes;
int n;
PancakeState *copyState();
void printState();
};
void PancakeState::printState() {
int i;
cout << "[";
for (i = 0; i < this->n; i++) {
cout << this->pancakes[i];
if (i < this->n - 1)
cout << ", ";
}
cout << "]";
}
class PancakeMove {
public:
PancakeMove(int n) : n(n) {}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
int bf(PancakeState&);
PancakeMove getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
int Pancake::bf(PancakeState& s) {
return s.n - 1;
}
PancakeMove Pancake::getMove(int i) {
return PancakeMove(i + 2);
}
// reverse n pancakes
void Pancake::makeMove(PancakeState &s, PancakeMove &m) {
int i;
int n = m.n;
for (i = 0; i < n/2; i++) {
int temp = s.pancakes[i];
s.pancakes[i] = s.pancakes[n - 1 - i];
s.pancakes[n - 1 - i]=temp;
}
}
void Pancake::unmakeMove(PancakeState &state, PancakeMove &move) {
makeMove(state, move);
}
int Pancake::heuristic(PancakeState &s) {
int i, res = 0;
nCalls++;
for (i = 1; i < s.n; i++)
if (abs(s.pancakes[i]-s.pancakes[i-1])>1)
res++;
if (s.pancakes[0] != 0) res++;
return res;
}
void tabs(int g) {
int i;
for (i = 0; i < g; i++) cout << "\t";
}
template <class Domain, class State, class Move>
class Alg {
public:
vector<State> solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
void ida(Domain &d, State &s);
};
template <class Domain, class State, class Move>
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
cout << "Thereshold:" << threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
solution.resize(g+1);
solution[g] = s;
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
Move move = d.getMove(i);
d.makeMove(s, move);
if (this->df(d, s, g+1)) {
d.unmakeMove(s, move);
solution[g] = s;
return 1;
}
d.unmakeMove(s, move);
}
return 0;
}
template <class Domain, class State, class Move>
void Alg<Domain, State, Move>::ida(Domain &d, State &s) {
int i;
this->threshold = 0;
while (!this->df(d, s, 0)) threshold++;
for (i = 0; i <= threshold; i++) {
cout << i << ".";
solution[i].printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
Pancake d = Pancake();
int myInstance[] = {0,5,4,7,2,6,1,3};
PancakeState s(8, myInstance);
s.printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
alg->ida(d, s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
As an extra benefit of not making so many direct allocations, it also doesn't leak 22 lumps of memory throughout the execution, which is quite a useful feature.
(If you want to see what changed, here's a diff - ignoring whitespace only changes):
--- pcake.orig.cpp 2014-04-13 15:43:24.861417827 +0100
+++ pcake.cpp 2014-04-13 15:42:25.145165372 +0100
## -1,7 +1,9 ##
#include <iostream>
-#include "stdlib.h"
-#include "string.h"
-#include "assert.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <vector>
+
using namespace std;
static int df_output = 0;
## -9,21 +11,22 ##
class PancakeState {
public:
- int *pancakes;
+ PancakeState(int n) : n(n), pancakes(n)
+ {
+ }
+ PancakeState(int n, int *v) : n(n), pancakes(n)
+ {
+ for(int i = 0; i < n; i++)
+ pancakes[i] = v[i];
+ }
+ PancakeState(): n(0) {}
+public:
+ vector<int> pancakes;
int n;
PancakeState *copyState();
void printState();
};
-PancakeState *PancakeState::copyState() {
- PancakeState *res = new PancakeState();
- res->n = this->n;
- res->pancakes = (int *)malloc(this->n * sizeof(int));
- memcpy(res->pancakes, this->pancakes,
- this->n * sizeof(int));
- return res;
-}
-
void PancakeState::printState() {
int i;
cout << "[";
## -37,25 +40,25 ##
class PancakeMove {
public:
- PancakeMove(int n) {this->n = n;}
+ PancakeMove(int n) : n(n) {}
int n;
};
class Pancake {
public:
int heuristic (PancakeState &);
- int bf(PancakeState &);
- PancakeMove *getMove(int);
+ int bf(PancakeState&);
+ PancakeMove getMove(int);
void makeMove(PancakeState &, PancakeMove &);
void unmakeMove(PancakeState &, PancakeMove &);
};
-int Pancake::bf(PancakeState &s) {
+int Pancake::bf(PancakeState& s) {
return s.n - 1;
}
-PancakeMove *Pancake::getMove(int i) {
- return new PancakeMove(i + 2);
+PancakeMove Pancake::getMove(int i) {
+ return PancakeMove(i + 2);
}
// reverse n pancakes
## -91,7 +94,7 ##
template <class Domain, class State, class Move>
class Alg {
public:
- State **solution;
+ vector<State> solution;
int threshold;
bool verbose;
int df(Domain &d, State &s, int g);
## -102,30 +105,28 ##
int Alg<Domain, State, Move>::df(Domain &d, State &s, int g) {
int h = d.heuristic(s), i;
if (g == 0)
- cout << "Thereshold:" << this->threshold << "\n";
+ cout << "Thereshold:" << threshold << "\n";
if (this->verbose) {
tabs(g);
cout << "g=" << g;
s.printState(); cout << "\n";
}
if (h == 0) {
- solution = (State **)malloc((g+1) * sizeof(State *));
- solution[g] = s.copyState();
+ solution.resize(g+1);
+ solution[g] = s;
return 1;
}
if (g == this->threshold)
return 0;
for (i = 0; i < d.bf(s); i++) {
- Move *move = d.getMove(i);
- d.makeMove(s, *move);
+ Move move = d.getMove(i);
+ d.makeMove(s, move);
if (this->df(d, s, g+1)) {
- d.unmakeMove(s, *move);
- solution[g] = s.copyState();
- delete move;
+ d.unmakeMove(s, move);
+ solution[g] = s;
return 1;
}
- d.unmakeMove(s, *move);
- delete move;
+ d.unmakeMove(s, move);
}
return 0;
}
## -138,23 +139,22 ##
for (i = 0; i <= threshold; i++) {
cout << i << ".";
- this->solution[i]->printState();
+ solution[i].printState();
cout << "\n";
//if (i < threshold - 1) printf("->");
}
}
int main(int argc, char **argv) {
- Pancake *d = new Pancake();
- PancakeState *s = new PancakeState();
+ Pancake d = Pancake();
int myInstance[] = {0,5,4,7,2,6,1,3};
- s->pancakes = myInstance;
- s->n = 8;
- s->printState(); cout << "\n";
+ PancakeState s(8, myInstance);
+ s.printState(); cout << "\n";
Alg<Pancake, PancakeState, PancakeMove> *alg = new Alg<Pancake, PancakeState, PancakeMove>();
//alg->verbose = true;
- alg->ida(*d, *s);
+ alg->ida(d, s);
cout << nCalls < "calls to heuristic()";
delete alg;
return 0;
}
+
I'm writing a genetic algorithm for which I'm creating a "crossover" operator as a class object that is passed the two parent "chromosomes" Because the input and therefore the output chromosomes are variable lengths, my idea was two divide the input chromosomes and place in a sort of storage class variable, then resize the input chromosomes, and then finally refill the input chromosomes. I'm getting a bad_alloc error, however. If someone could spot my error I'd very much appreciate the help.
Thanks! My class code is below. Note that "plan_vector" is a 2d vector of int types.
#include <iostream>
#include <vector>
#include <eo>
class wetland_vector : public std::vector<int> {
public:
wetland_vector() : std::vector<int>(1, 0) {
}
};
std::istream& operator>>(std::istream& is, wetland_vector& q) {
for (unsigned int i = 0, n = 1; i < q.size(); ++i) {
is >> q[i];
}
return is;
}
std::ostream& operator<<(std::ostream& os, const wetland_vector& q) {
os << q[0];
for (unsigned int i = 1, n = 1; i < q.size(); ++i) {
os << " " << q[i];
}
os << " ";
return os;
}
class wetland_vector_Init : public eoInit<wetland_vector> {
public:
void operator()(wetland_vector& q) {
for (unsigned int i = 0, n = q.size(); i < n; ++i) {
q[i] = rng.random(10);
}
}
};
class plan_vector : public eoVector<double, wetland_vector> {
};
int read_plan_vector(plan_vector _plan_vector) {
for (unsigned i = 0; i < _plan_vector.size(); i++) {
//Call function that reads Quad[1]
//Call function that reads Quad[2]
//etc
return 0;
}
return 0;
};
class eoMutate : public eoMonOp<plan_vector> {
int subbasin_id_min;
int subbasin_id_max;
int wetland_id_min;
int wetland_id_max;
bool operator() (plan_vector& _plan_vector) {
//decide which Quad to mutate
int mutate_quad_ID = rng.random(_plan_vector.size());
//decide which Gene in Quad to mutate
int mutate_gene_ID = rng.random(_plan_vector[mutate_quad_ID].size());
//mutation procedure if first slot in the Quad is selected for mutation
if (mutate_quad_ID = 0) {
_plan_vector[mutate_quad_ID][mutate_gene_ID] = rng.random(subbasin_id_max);
}
//mutation procedure if second slot in the Quad is selected for mutation
if (mutate_quad_ID = 1) {
_plan_vector[mutate_quad_ID][mutate_gene_ID] = rng.random(subbasin_id_max);
}
//note: you'll need to add more for additional wetland characteristics
return true;
};
public:
void set_bounds(int, int, int, int);
};
void eoMutate::set_bounds(int a, int b, int c, int d) {
subbasin_id_min = a;
subbasin_id_max = b;
wetland_id_min = c;
wetland_id_max = d;
}
double evaluate(const plan_vector& _plan_vector) {
int count = 0;
for (int i = 0; i < _plan_vector.size(); i++) {
for (int j = 0; j < _plan_vector[i].size(); j++) {
count += _plan_vector[i][j];
}
}
return (count);
}
class eoQuadCross : public eoQuadOp<plan_vector> {
public:
std::string className() const {
return "eoQuadCross";
}
plan_vector a1;
plan_vector a2;
plan_vector b1;
plan_vector b2;
bool operator() (plan_vector& a, plan_vector& b) {
int cross_position_a = rng.random(a.size() - 1);
int cross_position_b = rng.random(b.size() - 1);
for (int i = 0; i < cross_position_a; i++) {
a1.push_back(a[i]);
}
for (int i = cross_position_a; i < a.size(); i++) {
a2.push_back(a[i]);
}
for (int i = 0; i < cross_position_b; i++) {
b1.push_back(b[i]);
}
for (int i = cross_position_b; i < b.size(); i++) {
b2.push_back(b[i]);
}
int size_a = b2.size() + a1.size();
int size_b = a2.size() + b1.size();
a.resize(size_a);
b.resize(size_b);
for (int i = 0; i < b2.size(); i++) {
a.push_back(b2[i]);
}
for (int i = 0; i < a1.size(); i++) {
a.push_back(a1[i]);
}
for (int i = 0; i < a2.size(); i++) {
b.push_back(a2[i]);
}
for (int i = 0; i < b1.size(); i++) {
b.push_back(b1[i]);
};
//Return bool
return true;
}
};
int main() {
unsigned int vec_size_min = 1;
unsigned int vec_size_max = 10;
unsigned int pop_size = 100;
//BEGIN COPY PARAMETRES
const unsigned int MAX_GEN = 100;
const unsigned int MIN_GEN = 5;
const unsigned int STEADY_GEN = 50;
const float P_CROSS = 0.8;
const float P_MUT = 0.5;
const double EPSILON = 0.01;
double SIGMA = 0.3;
const double uniformMutRate = 0.5;
const double detMutRate = 0.5;
const double normalMutRate = 0.5;
//END COPY PARAMETERS
rng.reseed(1);
//Create population
wetland_vector_Init atom_init;
eoInitVariableLength<plan_vector> vec_init(vec_size_min, vec_size_max, atom_init);
eoPop<plan_vector> pop(pop_size, vec_init);
//Create variation operators
eoMutate mutate;
mutate.set_bounds(1, 453, 1, 4);
eoQuadCross crossover;
eoDetTournamentSelect<plan_vector> select(3);
eoSGATransform<plan_vector> transform(crossover, .5, mutate, .2);
//Create fitness function
eoEvalFuncPtr<plan_vector> eval(evaluate);
//Evaluate initial population and cout
apply<plan_vector > (eval, pop);
std::cout << pop << std::endl;
//Set GA for execution and execute
eoGenContinue<plan_vector> GenCount(5);
eoSGA<plan_vector> gga(select, crossover, .5, mutate, .1, eval, GenCount);
gga(pop);
//cout final population and end
std::cout << pop << std::endl;
std::cout << "The End" << std::endl;
}
a1.~vector();
a2.~vector();
b1.~vector();
b2.~vector();
You shall not destruct the vectors manually, otherwise the next time you try to access them (upon next call to the operator ()) you get undefined behavior.
Why do you call vector destructor manually?? You should let C++ call that for you. If you want to clear the vector use clear member function