How can i make this algorithm more memory efficient? - c++

I have been working on this piece of code for a couple of days and it seems
to work just fine for search trees of relative small size, but working with higher ones gives segmentation fault.
I have tried to find the specific place where such error comes from by using printing flags, and it seems to break at the is_goal() function. But the code of that function can be assumed as correct.
So the problems seems to be a memory problem, that's why I have the queue in the heap, and also the Nodes that I am creating. But it still crashes.
Are there any more memory saving tricks that can be taking into account that I am not using? Or maybe there is a better way to save such nodes?
It is important to note that I need to use BFS (I can't use A* to make the search tree smaller).
Also if you need to know, the map is a hash table where I save the coloring of the nodes so I don't have duplicates when exploring (This is because the hash saves depending on the state information and not the Node information).
EDIT: i have been told to indicate the goal to accomplish, such is to find the goal state in the search tree, the goal is to be be able to iterate over
big problems like rubik 3x3x3, n-puzzle 4x4 5x5, tower of hanoi and such.To do so, the memory used has to be minimal since the search tree of such problems are really big, the final objective is to compare this algorithm with others like a*, dfid, ida*, and so on. I hope this is enough information.
Node* BFS(state_t start ){
state_t state, child;
int d, ruleid;
state_map_t *map = new_state_map();
ruleid_iterator_t iter;
std::queue<Node*> *open = new std::queue<Node*>();
state_map_add( map, &start, 1);
Node* n = new Node(start);
open->push(n);
while( !open->empty() ) {
n = open->front();
state = n->get_state();
open->pop();
if (is_goal(&state) == 1) return n;
init_fwd_iter( &iter, &state );
while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
apply_fwd_rule( ruleid, &state, &child );
const int *old_child_c = state_map_get( map, &child );
if ( old_child_c == NULL ) {
state_map_add( map, &child, 1 );
Node* nchild = new Node(child);
open->push(nchild);
}
}
}
return NULL;
}

I see a number of memory leaks.
open is never deleted but maybe could allocated in the stack instead of in the heap.
std::queue<Node*> open;
More important none of the node you push in the queue are deleted this is probably the origin of very big memory consumption.
Delete the nodes that you remove from the queue and that you don't plan to reuse. Delete the nodes of the queue before your get rid of the queue.
Node* BFS(state_t start ){
state_t state, child;
int d, ruleid;
state_map_t *map = new_state_map();
ruleid_iterator_t iter;
std::queue<Node*> open;
state_map_add( map, &start, 1);
Node* n = new Node(start);
open.push(n);
while( !open.empty() ) {
n = open.front();
state = n->get_state();
open.pop();
if (is_goal(&state) == 1) {
for (std::queue<Node*>::iterator it = open.begin(); it != open.end(); ++it)
delete *it;
return n;
}
else {
delete n;
}
init_fwd_iter( &iter, &state );
while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
apply_fwd_rule( ruleid, &state, &child );
const int *old_child_c = state_map_get( map, &child );
if ( old_child_c == NULL ) {
state_map_add( map, &child, 1 );
Node* nchild = new Node(child);
open.push(nchild);
}
}
}
return NULL;
}

Related

Trie structure, lock-free inserting

I tried to implement lock free Trie structure, but I am stuck on inserting nodes. At first I believed it was easy (my trie structure would not have any delete methods) but even swapping one pointer atomically can be tricky.
I want to swap pointer to point to structure(TrieNode) atomically only when it was nullptr so as to be sure that I do not lose other nods that other thread could insert inbetween.
struct TrieNode{
int t =0;
std::shared_ptr<TrieNode> child{nullptr};
};
std::shared_ptr<TrieNode> root;
auto p = std::atomic_load(&root);
auto node = std::make_shared<TrieNode>();
node->t=1;
auto tmp = std::shared_ptr<TrieNode>{nullptr};
std::cout<<std::atomic_compare_exchange_strong( &(p->child), &tmp,node)<<std::endl;
std::cout<<node->t;
With this code I get exit code -1073741819 (0xC0000005).
EDIT: Thank you for all your coments. Maybe I did not specify my problem so I want to address it now.After around 10 hours of coding last day I changed few things. Now I use ordinarry pointers and for now it is working. I did not test it for now if its race free with multiple threads inserting words. I plan to do it today.
const int ALPHABET_SIZE =4;
enum Alphabet {A,T,G,C,END};
class LFTrie{
private:
struct TrieNode{
std::atomic<TrieNode*> children[ALPHABET_SIZE+1];
};
std::atomic<TrieNode*> root = new TrieNode();
public:
void Insert(std::string word){
auto p =root.load();
int index;
for(int i=0; i<=word.size();i++){
if(i==word.size())
index = END;
else
index = WhatIndex(word[i]);
auto expected = p->children[index].load();
if(!expected){
auto node = new TrieNode();
if(! p->children[index].compare_exchange_strong(expected,node))
delete node;
}
p = p->children[index];
}
}
};
Now I believe it will work with many threads inserting different words . And yes, in this solution I discard node if there next pointer is not null. Sorry for the trouble (I am not native speaker).
CAS pattern should be something like:
auto expected = p->child;
while( !expected ){
if (success at CAS(&p->child, &expected, make_null_replace() ))
break;
}
if you aren't paying attention to the return value/expected and testing that you are replacing null, stored locally, you are in trouble.
On failure, you need to throw away the new node you made.

Implementing a scheduling algorithm (assignment) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So I am on my 2nd year of computer science and I am struggling with a part of one of my assignments.
Basically, we had to make a stack, a queue and a scheduling algorithm.
I've made the stack and queue part which will technically give me a pass, but I would like to do the remaining part as well just to be sure.
We're allowed to use ONLY iostream library, nothing else.
These are the .h files provided by our teacher:
http://pastebin.com/TcBzULZj
We HAVE to use these.
I am struggling with the algorithm as it is supposed to be a subclass of queue, using an integer for priority and storing integer values to represent process IDs.
How should I approach that?
I am not asking you to do my homework for me or anything like that, I just want to tips and a little push in the right direction :)
############################################
EDIT
I tried to do it this way:
http://pastebin.com/mFchEc6T
It does compile and start, but as soon as I try to do anything in the program it gives some memory error and turns off my program.
I guess there's something wrong with the pointers but I dont know what.
Basically the idea behind that function was to go through all the nodes from the top of the queue and compare their priority to the priority of "temp" node.
It would swap places with nodes as long as "temp" had higher priority than them (green on picture) and as soon as it hit a node with the same priority (blue) it would stop there and wait for its turn, before nodes with higher priority (red) are done.
I bet these pointers are messed up but I just can't get my head around it for life, even though I struggled with this for like 2 days already.
You can adding a new value with priority P after all values with priorities higher than P.
Pop values from the beginning of the list.
For example:
If you have values 1, 2, 3, 4, 5 with priorities 99, 54, 111, 27, 978
In list you have: 5(978), 3(111), 1(99), 2(54), 4(27).
If you need add value 6 with priority 105, you add it after value 3 with priority 111.
Look at the simple example of queue with priorities.
#include <iostream>
class Queue {
public:
Queue() :
queue( 0 )
{
}
void Push( int value, int priority = 0 );
bool Pop( int& value );
private:
struct Node {
Node* Next;
int Value;
int Priority;
Node( int value, int priority ) :
Next( 0 ),
Value( value ),
Priority( priority )
{
}
};
Node* queue;
Queue( const Queue& );
Queue& operator=( const Queue& );
};
void Queue::Push( int value, int priority)
{
Node* node = new Node( value, priority );
if( queue == 0 || queue->Priority < node->Priority ) {
node->Next = queue;
queue = node;
} else {
Node* i = queue;
while( i->Next != 0 && node->Priority <= i->Next->Priority ) {
i = i->Next;
}
node->Next = i->Next;
i->Next = node;
}
}
bool Queue::Pop( int& value )
{
if( queue == 0 ) {
return false;
}
value = queue->Value;
Node* tmp = queue;
queue = queue->Next;
delete tmp;
return true;
}
int main( int argc, const char* argv[] )
{
Queue queue;
queue.Push( 3, 100 );
queue.Push( 2, 200 );
queue.Push( 1, 500 );
int x;
while( queue.Pop( x ) ) {
std::cout << x << std::endl;
}
return 0;
}

How to resolve a bad_alloc that seems unlikely to be an out-of-memory issue?

I'm writing a bit of code for searching a maze with BFS in C++ (my primary language is Python, but I wanted to excersise my C++ brain a bit...), and I stumbled across this strange error.
Here are the relevant data structures:
struct Maze {
std::pair<int, int> start;
std::pair<int, int> goal;
std::pair<int,int> dims;
std::set<std::pair<int, int> > passable;
};
struct SearchNode {
std::pair<int, int> cell;
Maze* pMaze;
SearchNode* parent;
std::vector<SearchNode*> children;
};
Assume that I've already got a method void parseFile(Maze* maze, char* filename) that reads in a maze text file, storing the (row, col) pairs of the start and goal squares as well as a set corresponding to the (row, col) pairs that are "passable" in the maze.
There are a few other functions as well:
bool isPassable(Maze* maze, std::pair<int,int> testCell);
std::vector<SearchNode*> getPassableChildren(SearchNode sn);
void mazeSearch(Maze* maze);
Here are their implementations:
// <...snip...>
inline bool isPassable(Maze* maze, std::pair<int,int> cell) {
return maze->passable.find(cell) != maze->passable.end();
}
std::vector<SearchNode*> getPassableChildren(SearchNode sn) {
// Store a cached copy of the children, so if we require multiple queries
// we do not have to re-compute children.
if(sn.children.empty()) {
Maze* mazePointer = sn.pMaze;
int r = sn.cell.first;
int c = sn.cell.second;
for(int i = 0; i <= 2; ++i) {
for(int j = 0; j <= 2; ++j) {
if (!(i == 1 && j == 1)) {
std::pair<int,int> childCell(r+i-1, c+j-1);
if(isPassable(mazePointer, childCell)) {
// Build child SN
SearchNode child;
child.cell = childCell;
child.parent = &sn;
child.pMaze = mazePointer;
sn.children.push_back(&child);
}
}
}
}
}
return sn.children;
}
void mazeSearch(Maze* maze) {
std::set<std::pair<int,int> > visited;
std::deque<SearchNode> workQueue;
// Create root node.
SearchNode root;
root.cell = maze->start;
root.parent = NULL;
root.pMaze = maze;
workQueue.push_back(root);
visited.insert(root.cell);
while(!workQueue.empty()) {
SearchNode sn = workQueue.front();
workQueue.pop_front();
for(SearchNode* passableNeighbor : getPassableChildren(sn)) {
// THIS IF-STATEMENT IS BROKEN
if(passableNeighbor->cell.first == maze->goal.first &&
passableNeighbor->cell.second == maze->goal.second) {
printf("Found a path.\n");
return;
}
// Check to make sure it is not in our visited set.
// THIS STATEMENT IS ALSO BROKEN
if (visited.find(passableNeighbor->cell) == visited.end()) {
workQueue.push_back(*passableNeighbor);
visited.insert(passableNeighbor->cell);
}
}
}
printf("No path found.\n");
}
// <...snip...>
The code compiles fine under GCC 4.6.3: $g++ maze.cc -g -std=c++0x
However, $./a.out smallMaze.txt produces
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
I've done some sanity checking with Valgrind and GDB:
Valgrind points out that Conditional jump or move depends on uninitialised value(s) in the line that begins
if(passableNeighbor->cell.first == maze->goal.first
and the line nearby that does a set lookup,
if(visited.find(passableNeighbor->cell) == visited.end())
When I inspect these passableNeighbor pointers in GDB, it does look like the underlying SearchNode object hasn't had it's child cell initialized properly, with all sorts of weird values cropping up. I suspect that this has to do with my lack of understanding of how C++ allocates objects.
So it's pretty clear that the underlying issue is that the passableNeighbor object somehow has corrupt data in it. Is this an artifact of how I wrote the getPassableChildren() method? Any other thoughts?
I've looked around at std::bad_alloc and it seems like this exception is usually related to running out of memory, but I'm getting this error on my very first node expanded during BFS, so it seems extremely unlikely that I'm hitting any memory limit.
This part has a problem
if(isPassable(mazePointer, childCell)) {
// Build child SN
SearchNode child;
child.cell = childCell;
child.parent = &sn;
child.pMaze = mazePointer;
sn.children.push_back(&child);
}
in that it fills the children with pointers to a local variable. When you leave the if-statement, all the pointers are invalid.
If you create a new child here, you have better store its value than store a pointer.
You are adding to the children vector the address of a local variable, a big no-no
SearchNode child;
child.cell = childCell;
child.parent = &sn;
child.pMaze = mazePointer;
sn.children.push_back(&child);
Use some sort of allocation, or make your children be a vector<SearchNode>
E.g:
SearchNode *child = new SearchNode();
child->cell = childCell;
child->parent = &sn;
child->pMaze = mazePointer;
sn.children.push_back(child);
Then you will need to clean this up later, or make your vector vector<unique_ptr<SearchNode>> and push on unique_ptr<SearchNode>(child) and the de-allocation will be done for you

Delete and add elements to vector inside main loop

I searched before but couldn't find any answers. I am somewhat new to c++, so hopefully this question won't be too stupid.
I am trying to add and remove elements in a vector, in my case populated with particles during a big update or drawing loop over all particles. For example remove some particles because they died, but also add a few other ones because one particle collided with an object and I want to show a small particle burst at the point of collision. I made this simple test code in a demo file to get to the bottom of the problem.
I think the problem is since I delete and add particles the iterator pointer becomes invalid. Deletion works, but when I add a few random ones I get a null pointer. the code below is somewhat verbose, I know I should use iterators with begin() and end() but I had the same problem with those, and played with the code a bit, trying more javascript array style looping because I am more familiar with that.
void testApp::drawParticles()
{
int i=0;
int max = particles.size();
vector<Particle*>::iterator it = particles.begin();
while ( i < max ) {
Particle * p = particles[i];
if ( ofRandom(1) > .9 ) {
it = particles.erase(it);
max = particles.size();
} else {
ofSetColor(255, 255, 0);
ofCircle( p->x, p->y, p->z, 10);
if ( ofRandom(1) < .1 ) addSomeNewOnes();
i++;
it++;
}
}
}
void testApp::addSomeNewOnes()
{
int max = ofRandom(4);
for ( int i=0; i<max; i++ ) {
Particle * p = new Particle();
p->x = ofRandom( -ofGetWidth()/2, ofGetWidth()/2 );
p->y = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
p->z = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
particles.push_back( p );
}
}
Every time you insert in to a vector, the iterators to it are potentially invalidated. You cannot do this:
if ( ofRandom(1) < .1 ) addSomeNewOnes();
it++
Because after the call to addSomeNewOnes(), it is invalid.
You can use the iterator returned by a call to vector::insert, but in your case that would mean re-engineering your code.
This is something you might want to do, anyway, as your code is a bit kludgy.
You could loop at it from the end, which should allow you to delete your current (since you're only deleting off of the end) and add new ones which get added to the end:
Vector<Particle*>::iterator it = particles.end();
while (iter != particles.begin()) {
Particle * p = *iter;
if ( ofRandom(1) > .9 ) {
particles.erase(iter);
} else {
ofSetColor(255, 255, 0);
ofCircle( p->x, p->y, p->z, 10);
if ( ofRandom(1) < .1 ) addSomeNewOnes();
}
iter--;
}
If you are not adding, based on the info here, iterators in STL are stable so you should be able to iterate forwards and still be able to achieve the same result.
Iterators are invalidated in some cases when the underlying data changes.
You'll have to break out of the loop and start again.
You should be able to do that by wrapping your whole drawParticles function in a while(notDone) loop, and setting notDone to true when you're done modifying the vector.
Here's another SO question with the rules: Iterator invalidation rules
it = particles.erase(it);
will return an iterator pointing to the new location of the element following the one erased. If the one erased happens to be the last one, it will point to particles.end(). it++ on "end" is an error.
Also, if:
if ( ofRandom(1) < .1 ) addSomeNewOnes();
evaluates to true and addSomeNewOnes() is called, as others have said, that will also invalidate the iterator.
Are you inserting and deleting at the location of the iterator? If so,
insert and erase return iterators which will be valid, and you can use
those. Something like:
std::vector<T>::iterator i = v.begin();
while ( i != v.end() ) {
if ( someCondition ) {
i = v.erase( i );
} else {
++ i;
}
}
is a more or less standard idiom.
For random insertions and deletions, you have to work with indexs, which
you update according to the number of elements inserted or deleted, and
whether the insertion or deletion was in front of or behind the current
position.
There's an easy way to make this work correctly without worrying about invalidation rules: just build a new vector for the next iteration.
typedef vector<Particle*> ParticleVector;
// modifies the particle vector passed in
void testApp::drawParticles(ParticleVector &particles)
{
ParticleVector next;
next.reserve(particles.size()); // seems like a reasonable guess
for (auto it = particles.begin(); it != particles.end(); ++it)
{
Particle *p = *it;
if (ofRandom(1) > .9) {
// don't copy to the next cycle
delete p;
} else {
// copy to the next cycle
next.push_back(p);
ofSetColor(255, 255, 0);
ofCircle(p->x, p->y, p->z, 10);
if (ofRandom(1) < .1)
addSomeNewOnesTo(next);
}
}
particles.swap(next);
}
Note how much easier it is to refactor like this when you're not using globals, btw.
void testApp::addSomeNewOnesTo(ParticleVector &particles)
{
int max = ofRandom(4);
for ( int i=0; i<max; i++ ) {
Particle * p = new Particle();
p->x = ofRandom( -ofGetWidth()/2, ofGetWidth()/2 );
p->y = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
p->z = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
particles.push_back( p );
}
}
On another note : Isn't there a memory leak in your implementation?
You are using
vector<Particle*> particles
and also using particles.erase().
Wont that just delete your pointer to Particle,and not created object?

c++ directed graph depth first search

I am attempting to write a method DFS method for a directed graph. Right now I am running into a segmentation fault, and I am really unsure as to where it is. From what I understand of directed graphs I believe that my logic is right... but a fresh set of eyes would be a very nice help.
Here is my function:
void wdigraph::depth_first (int v) const {
static int fVertex = -1;
static bool* visited = NULL;
if( fVertex == -1 ) {
fVertex = v;
visited = new bool[size];
for( int x = 0; x < size; x++ ) {
visited[x] = false;
}
}
cout << label[v];
visited[v] = true;
for (int v = 0; v < adj_matrix.size(); v++) {
for( int x = 0; x < adj_matrix.size(); x++) {
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
cout << " -> ";
depth_first(x);
}
if ( v == fVertex ) {
fVertex = -1;
delete [] visited;
visited = NULL;
}
}
}
}
class definition:
class wdigraph {
public:
wdigraph(int =NO_NODES); // default constructor
~wdigraph() {}; // destructor
int get_size() { return size; } // returns size of digraph
void depth_first(int) const;// traverses graph using depth-first search
void print_graph() const; // prints adjacency matrix of digraph
private:
int size; // size of digraph
vector<char> label; // node labels
vector< vector<int> > adj_matrix; // adjacency matrix
};
thanks!
You are deleting visited before the end of the program.
Coming back to the starting vertex doesn't mean you finished.
For example, for the graph of V = {1,2,3}, E={(1,2),(2,1),(1,3)}.
Also, notice you are using v as the input parameter and also as the for-loop variable.
There are a few things you might want to consider. The first is that function level static variables are not usually a good idea, you can probably redesign and make those either regular variables (at the cost of extra allocations) or instance members and keep them alive.
The function assumes that the adjacency matrix is square, but the initialization code is not shown, so it should be checked. The assumption can be removed by making the inner loop condition adj_matrix[v].size() (given a node v) or else if that is an invariant, add an assert before that inner loop: assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" ); --the same goes for the member size and the size of the adj_matrix it self.
The whole algorithm seems more complex than it should, a DFS starting at node v has the general shape of:
dfs( v )
set visited[ v ]
operate on node (print node label...)
for each node reachable from v:
if not visited[ node ]:
dfs( node )
Your algorithm seems to be (incorrectly by the way) transversing the graph in the opposite direction. You set the given node as visited, and then try to locate any node that is the start point of an edge to that node. That is, instead of following nodes reachable from v, you are trying to get nodes for which v is reachable. If that is the case (i.e. if the objective is printing all paths that converge in v) then you must be careful not to hit the same edge twice or you will end up in an infinite loop -> stackoverflow.
To see that you will end with stackoverlow, consider this example. The start node is 1. You create the visited vector and mark position 1 as visited. You find that there is an edge (0,1) in the tree, and that triggers the if: adj_matrix[0][1] != 0 && visited[1], so you enter recursively with start node being 1 again. This time you don't construct the auxiliary data, but remark visited[1], enter the loop, find the same edge and call recursively...
I see a couple of problems:
The following line
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
should be changed to
if( adj_matrix[v][x] != 0 && visited[x] == false ) {
(You want to recurse only on vertices that have not been visited already.)
Also, you're creating a new variable v in the for loop that hides the parameter v: that's legal C++, but it's almost always a terrible idea.