I have found some similar questions on this subject, but I wanted to ask again in order to get a more clear answer. I am writing a graph matching algorithm, where each node on the graph assigned to a priority set depending on the matching of its neighbours. Details are not really important, but I am using an std::priority_queue in order to match the highest priority nodes first. Here is the tricky point: Each time a new match is introduced, the priority of the neighbours of the matching nodes shall be updated.
This algorithm is referenced from a paper and although I have implemented the exact same algorithm, I couldn't reach the same matching percentage. I naturally suspected that std::priority_queue may not be reordered as I wanted on priority updates, so I have run some tests and then I found out other questions asking the same thing:
How to tell a std::priority_queue to refresh its ordering?
Does changing a priority queue element result in resorting the queue?
My question naturally is, how can I update the order on new matchings? Can I enforce it? Or is there any other data structure (max heap for example) that can serve to this purpose? Note that, pushing new elements into the queue is not a valid solution for me. Here is the code piece I am using (matchFace() function updates the element priorities):
while (priorityQueue.size() != 0) {
// Take the face at the top of the queue and check if it is already matched
FaceData* currentFace = priorityQueue.top();
// Pop the face at the top in any case
priorityQueue.pop();
// If the face is not already matched, try to find a matching
if (!currentFace->matched) {
// Try to match the face with one of its neighbors, add it to the unmatched faces list if it fails
int neighborId = matchFace(currentFace);
if (neighborId == -1) {
unmatchedFaces.push_back(currentFace);
} else {
matchingMap[currentFace->id] = neighborId;
}
}
}
Using the comments that I received on the problem, I decided to answer it myself. I found out there are three possible ways to overcome this problem:
Implement your own updatable priority queue or use external libraries. Boost might have some additional data structures for this purpose. I also found an Updatable Priority Queue source code here.
Use a vector to store the values and use std::make_heap function provided in the algorithm library each time an update is received. This is the easiest way but it works very slow.
Remove and re-insert the elements. If this is not a valid approach, use a map to store the element ids and instead of removing the elements, mark the elements on the map so if you encounter them multiple times you can just ignore them. An alternative strategy is to alter the items by adding a flag and marking the elements by turning the flag on.
Related
I am trying to figure out a way to implement a DFS search to find the length of the longest path from a given node on a directed graph represented as an adjacency list by using a stack, and not using recursion. Specifically, I want to implement the DFS search so that as it runs, the stack gets populated as shown in the picture below..
If that isn't clear, this video is sort of how I want the stack to be built up as my program runs (DFS starts at around 12:45 : https://www.youtube.com/watch?v=pcKY4hjDrxk
But im struggling to find a way to achieve this, as I am still pretty new to programming in general. My current code represents the graph as an unordered map, with each entry containing a vector of all the nodes that point to it. i.e:
std::unordered_map<long, std::vector<long>> nodes;
And basically, I want to implement a DFS search from all nodes with a key value of -1 in that unordered_map as shown in the picture and in the video- with the stack getting allocated as shown. I was thinking, that way I can just record when the stack reaches its maximum size, and that would be the longest path.
One thing to note is the graphs in this specific problem is that each edge will only have one outgoing degree, as shown in the picture.. Is this possible, or will I have to use some sort of recursion to do what I want? Thanks in advance for any help.
You can probably use a task list instead of recursion. If you use the task list in FIFO order like a queue, you get a breadth-first search; if you use it LIFO like a stack, you get depth-first behavior.
However, note that it is possible for a DAG with N nodes to have O(2^(N/2)) possible paths! You should not need to evaluate all possible paths to solve your problem, though, so be careful not to write an algorithm that can take exponential time.
In order to do that, you will need to mark which nodes you have processed. Also, since you are looking for the longest path, you'll need to track per-node information about the longest path found so far.
Although it's possible to achieve this without recursion, as an alternative, I would suggest you to design a function this way, which requires you to write less code and which will provide the nice intuition to understand this algorithm for you're a beginner. And you'll not need to think about creating stack by your own
const int n = 100;
vector< int > graph[n];
int ans = 0, level = 0;
int vis[n];
void dfs(int src) {
level++;
ans = max(level, ans);
for (int x: graph[src]) {
if(vis[x]) continue;
vis[x] = 1;
dfs(x);
level--;
}
}
I hard coded the value of n and graph you can change it as you need as required structure.
Where we take the advantages of the stack created for the recursion tree by the program.
This function will work in O(V+E) for a given graph of V nodes and E edges.
Note that, if your Graph is so large that the stack created default by the program can't handle, then you still have to write your own stack to handle the recursion.
I am tasked with programming an A* Search Algorithm for an assignment that involves solving an '8-Puzzle'.
One of the algorithm's steps is to:
Add all the extended paths to Q. If the descendant state is already in Q, keep only the shorter path to state in Q (where Q is a Priority Queue (PQ)).
As such, I will need to search the PQ if an identical state exists but has a shorter path. If an identical state already exists but it has a longer path, I will need to delete this state from the PQ.
I have been directed to use an STL PQ, not my own implementation. I have managed to implement other types of searches using the below to create a Min PQ - which works as desired.
auto cmp = [](Puzzle* a, Puzzle* b) {
return a->getHCost() > b->getHCost();
};
std::priority_queue<Puzzle*, std::vector<Puzzle*>, decltype(cmp)> Q(cmp);
How can I extend my implementation so that...
I can perform a brute force search - looping through each element of the STL PQ?
I can delete an element somewhere in the STL PQ by its index? - shuffling elements 'upwards' if appropriate.
You could have a secondary array named shortest[] where shortest[i] would be the shortest known path to the state i. Then whenever you get in the top of the PQ an element with state x, you check shortest[x] if it is indeed the shortest found and do whatever you want to it, else delete the element from the top of the PQ.
However, given that the states are from an 8-puzzle, you'd have to come up with an efficient way to give them a unique identifying number and ability to get it back efficiently.
It is possible to do both such things in O(1). I'm not sure if I should spoil my personal idea yet, given it is after all an assignment and you should undertake such a challenge.
I am designing a Graph in c++ using a hash table for its elements. The hashtable is using open addressing and the Graph has no more than 50.000 edges. I also designed a PRIM algorithm to find the minimum spanning tree of the graph. My PRIM algorithm creates storage for the following data:
A table named Q to put there all the nodes in the beginning. In every loop, a node is visited and in the end of the loop, it's deleted from Q.
A table named Key, one for each node. The key is changed when necessary (at least one time per loop).
A table named Parent, one for each node. In each loop, a new element is inserted in this table.
A table named A. The program stores here the final edges of the minimum spanning tree. It's the table that is returned.
What would be the most efficient data structure to use for creating these tables, assuming the graph has 50.000 edges?
Can I use arrays?
I fear that the elements for every array will be way too many. I don't even consider using linked lists, of course, because the accessing of each element will take to much time. Could I use hash tables?
But again, the elements are way to many. My algorithm works well for Graphs consisting of a few nodes (10 or 20) but I am sceptical about the situation where the Graphs consist of 40.000 nodes. Any suggestion is much appreciated.
(Since comments were getting a bit long): The only part of the problem that seems to get ugly for very large size, is that every node not yet selected has a cost and you need to find the one with lowest cost at each step, but executing each step reduces the cost of a few effectively random nodes.
A priority queue is perfect when you want to keep track of lowest cost. It is efficient for removing the lowest cost node (which you do at each step). It is efficient for adding a few newly reachable nodes, as you might on any step. But in the basic design, it does not handle reducing the cost of a few nodes that were already reachable at high cost.
So (having frequent need for a more functional priority queue), I typically create a heap of pointers to objects and in each object have an index of its heap position. The heap methods all do a callback into the object to inform it whenever its index changes. The heap also has some external calls into methods that might normally be internal only, such as the one that is perfect for efficiently fixing the heap when an existing element has its cost reduced.
I just reviewed the documentation for the std one
http://en.cppreference.com/w/cpp/container/priority_queue
to see if the features I always want to add were there in some form I hadn't noticed before (or had been added in some recent C++ version). So far as I can tell, NO. Most real world uses of priority queue (certainly all of mine) need minor extra features that I have no clue how to tack onto the standard version. So I have needed to rewrite it from scratch including the extra features. But that isn't actually hard.
The method I use has been reinvented by many people (I was doing this in C in the 70's, and wasn't first). A quick google search found one of many places my approach is described in more detail than I have described it.
http://users.encs.concordia.ca/~chvatal/notes/pq.html#heap
One step in the A* pathfinding algorithm requires searching the list of open nodes for the node you're currently interacting with, and adding that node to the list if it isn't already there, or updating its value and parent, if it's present but with a higher weight than the current version of the node.
These behaviors aren't supported in the STL priority_queue structure. How should I implement that step?
Updates since this question is getting a lot of views:
std::priority_queue may look like a good choice for this, but it isn't.
Implementing A* yourself is an enormous confidence-booster, but after you've done it, you should try to switch to using the one provided by boost. I was nervous about installing it when I asked this question, but installation is very easy and won't produce any complications; and A* isn't the only useful functionality that boost provides. (In particular, if you don't use their string-processing functionality, you'll end up writing your own copy of it; I speak from personal experience...)
You can use a plain vector or array to store the elements and then use std::make_heap, std::push_heap, std::pop_heap, std::sort_heap, std::is_heap and std::is_heap_until to manage it.
This allows you to break containment and implement custom operations on a priority queue, without having to implement the standard operations yourself.
If you are limited to STL you could use STL Set and constantly erasing and re-inserting the elements (with new priority).
Set< pair<int,int> > s; // < priority,value >
s.insert( make_pair(0,5) );
// Decrease Key operation //
s.erase( s.find( make_pair(0,5) ) );
s.insert( make_pair(1,5) );
Time complexity is still O(log N) but it will probably take more time for large sets.
STL priority_queue does not suit for A* implementation. You need a heap structure that supports the increase operation to change the priority of already inserted items. Use Boost.Heap for an implementation of many classical heaps.
EDIT: Boost.Graph library has an implementation of A* search too.
Here is the solution I used for this if you really want to use std::priority_queue:
When you need to update a node that is already in the priority queue, just insert a new node having the same state and a new cost value and parent into the queue. The most recently updated copy of this node will come off the queue first and be added to your visited set. To deal with the older duplicates, check any node coming off the queue against your visited set before processing it. If it is in the visited set then the lowest-cost path through this node has already been seen, so just ignore it and process the next node.
There are three likely solutions to this:
Track the list of nodes currently open independently of the priority queue. Try creating a list of nodes in the same manner you do for closed nodes.
Create a map of nodes (by coordinate) to open-closed state.
Install the Boost library, which includes a templated implementation of A* (I think in <graph>).
I am using an STL queue to implement a BFS (breadth first search) on a graph. I need to push a node in the queue if that node already doesn't exist in the queue. However, STL queue does not allow iteration through its elements and hence I cannot use the STL find function.
I could use a flag for each node to mark them when they are visited and push them only when the flag is false, however, I need to run BFS multiple times and after each time I will have to reset all the flags, so I ended up using a counter instead of a flag, but I still would like to know if there is a standard way of finding an item in a queue.
I assume you're implementing the concept of a "closed set" in your BFS? The standard way of doing that is to simply maintain a separate std::set or std::unordered_set of elements already encountered. That way, you get O(lg n) or O(1) lookup, while iterating through a queue, if it were supported, would take O(n) time.
the accepted answer is silly.
each of the items in a BFS search will go through three states: not-visited, visited-but-not-complete, visited. For search purposes you can trim this down to visited or not-visited...
you simply need to use a flag...
the flag just alternates.
well, with the first traversal of the tree each node will start at false (not-visited) and go to true (visited). At the second traversal it will switch to true (not-visited) and go to false (visited).
so all you have to do is to keep a separate flag that simply changes state on each traversal...
then your logic is
if ( visitedFlag ^ alternatingFlagStateOfTree )
{
visitedFlag ^= 1;
}
basically the alternatingFlagStateOfTree is just used to indicate if a true is visited or a false is visited state. Each run alternates so we just swap them around.
This entirely eliminates the need for the set(), all the memory overhead, etc. as well as eliminated any need to reset the flag values between runs.
This technique can be used for more complex states, so long as there is a consistent ending state across all items being traversed. You simply do some math to reset what the flag value is to return the state back to base-state.