I'm trying to generate valid trees given certain graph edges (which can be considered as a network). Following is the code which reads the graph edges from a file;
FILE *fin = fopen("somefile.txt", "r");
for (int i = 0; i <=edges; i++) {
fscanf(fin, "%d%d%d", &u, &v, &w);
graph[u][v]=w;
}
fclose(fin);
Now I want to generate the maximum number of possible trees (or topology) for a given root u and a given size N given these edges.
For example, if there are edges; 1--->2 ;1--->3; 3--->4. Now if N is 1; possible trees from u=1 is 1---->2 and 1--->3. If N is 2, then possible trees are 1--->2 & 3 or 1--->3---->4
What would be the best way of achieving this? I'm not concerned about complexity issues. I'll appreciate the help!
it may not the best implementation but
something like this should work
map<vertex,list<edge>> vertexToedgeThatIncludeIt
void Coloredge(edgeList)
{
for each edge in list:
edge.color=True
}
void init()
{
for each edge:
{
vertexToedgeThatIncludeIt[edge.vertex1].append(edge)
vertexToedgeThatIncludeIt[edge.vertex2].append(edge)
}
}
edge* findUnColoredvertex(edgeList,startPoistion,founfAt)
{
skip to startPoistion
for each edge In edgeList:
if edge not colored return edge
update founfAt
return NULL
}
void spanTree(vertexToedgeThatIncludeIt,spanTreeList,lastvertex)
{
if(spanTreeList.size==NumberOfTotalvertex)
{
print spanningTree
return
}
nextedge=findUnColoredvertex(vertexToedgeThatIncludeIt[lastvertex],0,founfAt)
while(nextedge!=NULL)
{
spanTreeList.append(nextedge);
Coloredge(vertexToedgeThatIncludeIt[lastvertex]);
spanTree(vertexToedgeThatIncludeIt,spanTreeList,nextedge.othervertex)
spanTreeList.pop();
UnColoredge(vertexToedgeThatIncludeIt[lastvertex])
nextedge=findUnColoredvertex(vertexToedgeThatIncludeIt[lastvertex],founfAt,founfAt)
}
}
Related
I've implemented A* pathfinding which works flawlessly for smaller grids. However, when the maps become large and no longer maze-structured, such as the map pictured below, the algorithm becomes increasingly slow.
As per A*'s definition, I'm using an open list and a closed list. The open list is implemented using an std::set. The closed list is implemented using Qt's QSet.
The QSet is Qt's implementation of an std::unordered_list.
After profiling my application, I noticed that the re-balancing of the std::set's tree is the most expensive operation. This is noticeable when running the algorithm in two different maps, the one shown below with a large open list size and another maze-like map with a much lower open list size.
In the maze-like map, the size of my open list would fluctuate between 20 and 120 nodes. The open map slowly grew up to more than 2000 nodes.
So my question is if there is any way to reduce the size of the open list?
I have tried the following approaches:
Change open list to std::priority_queue: I was unable to implement this because I need to check the open list to see if it already contains the element. And correct me if I'm wrong, but wouldn't the priority_queue run into the same issue of re-balancing?
Use a higher heuristic weight: This didn't solve the problem, the order of magnitude of nodes in the open list was still identical.
Clipping the nodes in the open list: This resulted in a way faster run-through but often resulted in a path not being found. Initially I thought this would work as I'd only trim the values with a higher F (heuristic + movement) cost which would have become irrelevant. This assumption proved incorrect.
Thanks in advance.
EDIT1:
Added some code for clarification.
std::shared_ptr<Node> Pathfinding::findPath(float heuristicWeight) {
int i = 0;
while (!m_sOpen.empty()) {
++i;
std::shared_ptr<Node> current = *m_sOpen.begin();
m_sOpen.erase(current);
m_sClosed.insert(*current);
if (updateNeighbours(current, heuristicWeight)) {
return std::make_shared<Node>(*m_sClosed.find(*m_nEnd));
}
if (i % 100 == 0) {
qInfo() << "Sizes: " << i << " open_size= " << m_sOpen.size() << " & closed_size= " << m_sClosed.size();
}
}
return NULL;
}
bool Pathfinding::updateNeighbours(std::shared_ptr<Node> current, float heuristicWeight) {
int maxRows = wm.getRows(); // Rows in map
int maxCols = wm.getCols(); // Cols in map
for (int x = clamp((current->getX()-1),0,maxCols-1); x <= clamp((current->getX()+1),0,maxCols-1); ++x) {
for (int y = clamp((current->getY()-1),0,maxRows-1); y <= clamp((current->getY()+1),0,maxRows-1); ++y) {
bool exists = false;
Node n = Node(x,y); // Node to compare against and insert if nessecary.
// Tile contains information about the location in the grid.
Tile * t = wm.m_tTiles[(x)+(maxCols * y)].get();
if (t->getValue() != INFINITY) { // Tile is not a wall.
for (std::set<std::shared_ptr<Node>>::iterator it = m_sOpen.begin(); it != m_sOpen.end(); ++it) {
if (**it == n) {
exists = true;
if ((*it)->getF() > (current->getG() + moveCost(*it,current)) + (*it)->getH()) {
(*it)->setG(current->getG() + moveCost(*it,current));
(*it)->setParent(current);
}
break;
}
}
bool exists_closed = (m_sClosed.find(n) != m_sClosed.end());
if (!exists && !exists_closed) {
std::shared_ptr<Node> sN = std::make_shared<Node>(n);
sN->setParent(current);
sN->setG(current->getG() + moveCost(sN,current));
sN->setH(manhattenCost(sN,m_nEnd)*heuristicWeight);
if (sN->getH() == 0) { m_sClosed.insert(*sN); return true; }
else m_sOpen.insert(sN);
}
}
}
}
return false;
}
Switch from a std::set to a std::priority_queue. There is no need to check if a node is already in the open set before adding it to the queue. It is cheaper to just not insert it in the closed set if it is already there.
I have been working on a graph implementation for the last few days. All of this is really new to me, and I am stuck on two parts of my implementation. I am implementing a digraph of courses from an input file. From the file, I can determine which courses are prereqs for other courses. I then create a digraph with courses as nodes, and edges connecting courses that are prereqs. I also want to find the total number of nodes and edges, and perform a topological sort on the graph (I will later be adding weights to the edges). Here is my implementation.
Digraph.h
class vertex{
public:
typedef std::pair<int, vertex*> ve;
std::vector<ve> adjacency;
std::string course;
vertex(std::string c){
course = c;
}
};
class Digraph{
public:
void addVertex(std::string&);
void addEdge(std::string& from, std::string& to, int cost);
typedef std::map<std::string, vertex *> vmap;
vmap work;
int getNumVertices();
int getNumEdges();
void getTopoSort();
};
Digraph.cpp
void Digraph::addVertex(std::string& course){
vmap::iterator iter = work.begin();
iter = work.find(course);
if(iter == work.end()){
vertex *v;
v = new vertex(course);
work[course] = v;
return;
}
}
void Digraph::addEdge(std::string& from, std::string& to, int cost){
vertex *f = (work.find(from)->second);
vertex *t = (work.find(to)->second);
std::pair<int, vertex *> edge = std::make_pair(cost, t);
f->adjacency.push_back(edge);
}
Finding the number of nodes was easy just return work.size. I have confirmed this is working properly. I am lost on how I would return the number of edges in my graph. It seems it would be simple, but everything I tried doesn't work. Secondly, I am completely lost on how to perform a topological sort on this graph. Any assistance is appreciated.
A simple way would be to iterate through all vertices in your graph, add up their neighbor counts and then divide by two:
int Digraph::getNumEdges(){
int count = 0;
for (const auto & v : work) {
count += v.second->adjacency.size();
}
return count / 2;
}
To use the range based for loop, you need to use c++11. With g++ that would be --std=c++11 on the command line.
EDIT:
I just realized you have a directed graph, and you probably want to count one for each direction. In such case: don't divide by two!
int Digraph::getNumEdges(){
int count = 0;
for (const auto & v : work) {
count += v.second->adjacency.size();
}
return count;
}
First, for the number of edges, it would be simpler to count them directly when you build the graph (just add a counter in your Digraph class and increment it each time you add an edge … )
For the topological sort, first I have a question: your edges are from prereqs to dependant courses ? That is you have a link A -> B if A is a prereq of B ? If this not the case, you need to invert your graph.
You to main algorithm in order to build a topological sort: one based on a simple DFS (http://en.wikipedia.org/wiki/Depth-first_search) and the other relying on in-degrees (http://en.wikipedia.org/wiki/Directed_graph#Indegree_and_outdegree) of your vertices (courses in your case.)
Normally, you need to verify that your graph doesn't contain any cycle, which will normally be the case if your data are coherent.
Let's consider the DFS based algorithm: a DFS traverses each vertices from a given root following edges as they appear. We can easily prove that order of last encounter of a vertex forms a reverse topological order. So, all we need is to push in a stack the current vertex after the calls on its successors.
I made a quick and dirty implementation for you, using C++11 again.
First, add the following to the Digraph class:
typedef std::unordered_set<vertex*> marks_set;
marks_set marks;
typedef std::deque<vertex*> stack;
stack topo;
void dfs(vertex* vcur);
Then here comes the code:
void Digraph::dfs(vertex* vcur) {
marks.insert(vcur);
for (const auto & adj : vcur->adjacency) {
vertex* suc = adj.second;
if (marks.find(suc) == marks.end()) {
this->dfs(suc);
} // you can detect cycle in the else statement
}
topo.push_back(vcur);
}
void Digraph::getTopoSort() {
// It should be a good idea to separate this algorithm from the graph itself
// You probably don't want the inner state of it in your graph,
// but that's your part.
// Be sure marks and topo are empty
marks.clear();
topo.clear();
// Run the DFS on all connected components
for (const auto & v : work) {
if (marks.find(v.second) == marks.end()) {
this->dfs(v.second);
}
}
// Display it
for (const auto v : topo) {
std::cout << v->course << "\n";
}
}
The code compiles but I haven't tested. If for any reasons you have an issue with the recursive algorithm (the function Digraph::dfs), it can be derecursified using a stack containing the parent of the target vertex and the iterator to the current successor, the iterator reach the end of the adjacency list, you can push the parent in the topological sort.
The other algorithm is almost as simple: for each vertices you need to count the number of predecessor (in-degree) which can be done while building the graph. In order to compute the topological sort, you look for the first vertex with a in-degree of 0 (no predecessor), you then decrease the in-degree of all its successors and continue with the next vertex with 0. If the graph has no cycle, there will always be a vertex with a in-degree of 0 (at beginning of course, but also during the algorithm run as you decrease it) until all vertices have been seen. The order of vertices encounter form a topological sort (this is related to the Bellman shortest-path algorithm.)
Note that these 2 algorithms are listed here: http://en.wikipedia.org/wiki/Topological_sorting. The one using in-degree is described in terms of removing edges which we simply simulate by decreasing the in-degree (a far less destructive approach … )
Over the last week, I have implemented a Digraph by parsing an input file. The graph is guaranteed to have no cycles. I have successfully created the graph, used methods to return the number of vertices and edges, and performed a topological sort of the graph. The graph is composed of different major courses and their prereqs. Here is my graph setup:
class vertex{
public:
typedef std::pair<int, vertex*> ve;
std::vector<ve> adjacency;
std::string course;
vertex(std::string c){
course = c;
}
};
class Digraph{
public:
typedef std::map<std::string, vertex *> vmap;
vmap work;
typedef std::unordered_set<vertex*> marksSet;
marksSet marks;
typedef std::deque<vertex*> stack;
stack topo;
void dfs(vertex* vcur);
void addVertex(std::string&);
void addEdge(std::string& from, std::string& to, int cost);
int getNumVertices();
int getNumEdges();
void getTopoSort();
};
The implementation
//function to add vertex's to the graph
void Digraph::addVertex(std::string& course){
vmap::iterator iter = work.begin();
iter = work.find(course);
if(iter == work.end()){
vertex *v;
v = new vertex(course);
work[course] = v;
return;
}
}
//method to add edges to the graph
void Digraph::addEdge(std::string& from, std::string& to, int cost){
vertex *f = (work.find(from)->second);
vertex *t = (work.find(to)->second);
std::pair<int, vertex *> edge = std::make_pair(cost, t);
f->adjacency.push_back(edge);
}
//method to return the number of vertices in the graph
int Digraph::getNumVertices(){
return work.size();
}
//method to return the number of edges in the graph
int Digraph::getNumEdges(){
int count = 0;
for (const auto & v : work) {
count += v.second->adjacency.size();
}
return count;
}
//recursive function used by the topological sort method
void Digraph::dfs(vertex* vcur) {
marks.insert(vcur);
for (const auto & adj : vcur->adjacency) {
vertex* suc = adj.second;
if (marks.find(suc) == marks.end()) {
this->dfs(suc);
}
}
topo.push_front(vcur);
}
//method to calculate and print out a topological sort of the graph
void Digraph::getTopoSort(){
marks.clear();
topo.clear();
for (const auto & v : work) {
if (marks.find(v.second) == marks.end()) {
this->dfs(v.second);
}
}
// Display it
for (const auto v : topo) {
std::cout << v->course << "\n";
}
}
For the last part of my implementation, I have been trying to do 2 things. Find the shortest path from the first vertex to every other vertices, and also find the shortest path that visits every vertex and returns to the first one. I am completely lost on this implementation. I assumed from reading I need to use Dijkstra's algorithm to implement this. I have been trying for the last 3 days to no avail. Did i set up my digraph in a bad way to implement these steps? Any guidance is appreciated.
The fact that there are no cycles makes the problem much simpler. Finding the shortest paths and a minimal "grand tour" are O(n).
Implement Dijkstra and run it, without a "destination" node; just keep going until all nodes have been visited. Once every node has been marked (with its distance to the root), you can start at any node and follow the shortest (and only) path back to the root by always stepping to the only neighbor whose distance is less than this one. If you want, you can construct these paths quite easily as you go, and mark each node with the full path back to the root, but copying those paths can push the cost to O(n2) if you're not careful.
And once all the nodes are marked, you can construct a minimal grand tour. Start at the root; when you visit a node, iterate over its unvisited neighbors (i.e. all but the one you just came from), visiting each, then go back the one you came from. (I can put this with more mathematical rigor, or give an example, if you like.)
I have coded DFS as the way it is on my mind and didn't referred any Text book or Pseudo-code for ideas. I think I have some lines of codes that are making unnecessary calculations. Any ideas on reducing the complexity of my algorithm ?
vector<int>visited;
bool isFound(vector<int>vec,int value)
{
if(std::find(vec.begin(),vec.end(),value)==vec.end())
return false;
else
return true;
}
void dfs(int **graph,int numOfNodes,int node)
{
if(isFound(visited,node)==false)
visited.push_back(node);
vector<int>neighbours;
for(int i=0;i<numOfNodes;i++)
if(graph[node][i]==1)
neighbours.push_back(i);
for(int i=0;i<neighbours.size();i++)
if(isFound(visited,neighbours[i])==false)
dfs(graph,numOfNodes,neighbours[i]);
}
void depthFirstSearch(int **graph,int numOfNodes)
{
for(int i=0;i<numOfNodes;i++)
dfs(graph,numOfNodes,i);
}
PS: Could somebody please sent me a link teaching me how can to insert C++ code with good quality. I've tried syntax highlighting but it didn't work out.
Your DFS has O(n^2) time complexity, which is really bad (it should run in O(n + m)).
This line ruins your implementation, because searching in vector takes time proportional to its length:
if(std::find(vec.begin(),vec.end(),value)==vec.end())
To avoid this, you can remember what was visited in an array of boolean values.
Second problem with your DFS is that for bigger graph it will probably cause stack overflow, because worst case recursion depth is equal to number of vertices in graph. Remedy to this problem is also simple: use std::list<int> as your own stack.
So, code that does DFS should look more or less like this:
// n is number of vertices in graph
bool visited[n]; // in this array we save visited vertices
std::list<int> stack;
std::list<int> order;
for(int i = 0; i < n; i++){
if(!visited[i]){
stack.push_back(i);
while(!stack.empty()){
int top = stack.back();
stack.pop_back();
if(visited[top])
continue;
visited[top] = true;
order.push_back(top);
for(all neighbours of top)
if(!visited[neighbour])
stack.push_back(neighbour);
}
}
}
I need to use (not implement) an array based version of Dijkstras algo .The task is that given a set of line segments(obstacles) and start/end points I have to find and draw the shortest path from start/end point.I have done the calculating part etc..but dont know how to use dijkstras with my code.My code is as follows
class Point
{
public:
int x;
int y;
Point()
{
}
void CopyPoint(Point p)
{
this->x=p.x;
this->y=p.y;
}
};
class NeighbourInfo
{
public:
Point x;
Point y;
double distance;
NeighbourInfo()
{
distance=0.0;
}
};
class LineSegment
{
public:
Point Point1;
Point Point2;
NeighbourInfo neighbours[100];
LineSegment()
{
}
void main()//in this I use my classes and some code to fill out the datastructure
{
int NoOfSegments=i;
for(int j=0;j<NoOfSegments;j++)
{
for(int k=0;k<NoOfSegments;k++)
{
if( SimpleIntersect(segments[j],segments[k]) )
{
segments[j].neighbours[k].distance=INFINITY;
segments[j].neighbours[k].x.CopyPoint(segments[k].Point1);
segments[j].neighbours[k].y.CopyPoint(segments[k].Point2);
cout<<"Intersect"<<endl;
cout<<segments[j].neighbours[k].distance<<endl;
}
else
{
segments[j].neighbours[k].distance=
EuclidianDistance(segments[j].Point1.x,segments[j].Point1.y,segments[k].Point2.x,segments[k ].Point2.y);
segments[j].neighbours[k].x.CopyPoint(segments[k].Point1);
segments[j].neighbours[k].y.CopyPoint(segments[k].Point2);
}
}
}
}
Now I have the distances from each segmnets to all other segments, amd using this data(in neighbourinfo) I want to use array based Dijkstras(restriction ) to trace out the shortest path from start/end points.There is more code , but have shortened the problem for the ease of the reader
Please Help!!Thanks and plz no .net lib/code as I am using core C++ only..Thanks in advance
But I need the array based version(strictly..) I am not suppose to use any other implemntation.
Dijkstras
This is how Dijkstra's works:
Its not a simple algorithm. So you will have to map this algorithm to your own code.
But good luck.
List<Nodes> found; // All processed nodes;
List<Nodes> front; // All nodes that have been reached (but not processed)
// This list is sorted by the cost of getting to this node.
List<Nodes> remaining; // All nodes that have not been explored.
remaining.remove(startNode);
front.add(startNode);
startNode.setCost(0); // Cost nothing to get to start.
while(!front.empty())
{
Node current = front.getFirstNode();
front.remove(current);
found.add(current);
if (current == endNode)
{ return current.cost(); // we found the end
}
List<Edge> edges = current.getEdges();
for(loop = edges.begin(); loop != edges.end(); ++loop)
{
Node dst = edge.getDst();
if (found.find(dst) != found.end())
{ continue; // If we have already processed this node ignore it.
}
// The cost to get here. Is the cost to get to the last node.
// Plus the cost to traverse the edge.
int cost = current.cost() + loop.cost();
Node f = front.find(dst);
if (f != front.end())
{
f.setCost(std::min(f.cost(), cost));
continue; // If the node is on the front line just update the cost
// Then continue with the next node.
}
// Its a new node.
// remove it from the remaining and add it to the front (setting the cost).
remaining.remove(dst);
front.add(dst);
dst.setCost(cost);
}
}