I want to use the dijkstra-tool coming with the graphviz package to calculate the shortest path in a directed graph with positive (including 0) edge weights.
But it seams that it does not consider the edge weights.
I call it like this:
dijkstra -dp "Start Node" graph.dot > results.dot
graph.dot contains:
digraph{
"Start Node" -> "B" [len=0];
"B" -> "A" [len=5];
...
results.dot contains:
digraph {
graph [maxdist=385.000];
"12_nach_48_1_1" [dist=40.000,
prev="12_von_69_1_1"];
"12_nach_69_0_1" [dist=43.000,
prev="12_von_48_0_1"];
...
The problem was in the script producing my .dot file.
dijkstra did everything as it should.
Related
The 'constraint=false'sometimes' allows the clusters to get out of order, even when doing so, causes longer edges. I wish to both have all subgraph clusters line up 'and' keep the order of the subgraph clusters intact. (which in my case, since I alway will only connect the edge to an node neighboring cluster, will result in edge that don't cross over an intervening subgraph. Sometimes it works as expected, but in the example I am posting, you can see the '2nd' subgraph for some reason shows up in the third position (which causes the links to go farther than they need to.)
Is there a way to achieve both the lining up of all the tops of the subgraphs 'and' maintaining a specific order of subgraphs left to right?
I have read many posts, and have tried many of the things suggested, but I can't seem to find a combination that works. When constraint=true, the 'order' seems to be correct, but the alignment is wrong. When constraint=false... The alignment is correct and 'sometimes' the order is correct, but other like the example posted, the order is invalid.
digraph G {
ranksep=.05;
splines=line;
subgraph cluster_1 {
label="1";
choice0_0[label="1"];
choice0_1[label="2"];
choice0_2[label="3"];
choice0_0 -> choice0_1 -> choice0_2 [style="invis"];
}
subgraph cluster_2 {
label="2";
choice1_0[label="1"];
choice1_1[label="2"];
choice1_2[label="3"];
choice1_0 -> choice1_1 -> choice1_2 [style="invis"];
}
subgraph cluster_3 {
label="3";
choice2_0[label="1"];
choice2_1[label="2"];
choice2_2[label="3"];
choice2_0 -> choice2_1 -> choice2_2 [style="invis"];
}
edge[constraint=false];
choice0_2 -> choice1_1;
choice1_1 -> choice2_2;
}
dot -Tps x.gv -o x.ps
(where x.gv contains the code pasted above)
No errors are displayed when this is run, but this example the order of the 2nd and 3rd subgraph is swapped.
I had a directed weighted graph G, where weight is duration of transition.
I wrote all paths search algorithm between two vertices using DFS with modification: the search continues until total weight of path (the sum of the weights of its parts) will be less some value.
My code works in small graph, but in big graph (|V|=1800, |E|=50870) it freezes.
def find_paths(self, start, end, weight_limit=10):
res = []
def dfs(start, end, path=[], weight=0):
path = path + [start]
if len(path) > 1:
weight += self.weights[(path[-2], start)]
if weight > weight_limit:
return []
if start == end:
res.append((path, weight))
return [path]
if start not in self.adjacent:
return []
paths = []
for node in self.adjacent[start]:
if node not in path:
paths.extend(dfs(node, end, path, weight))
return paths
dfs(start, end)
return res
Your code seems correct (especially since it works on small graphs).
The problem is that there can be lots of paths between the nodes. For a fully connected graph the number of paths is on the order of N! which is a lot. Since you need all of them your program is going to be slow (especially if you run out of ram and need to swap things to disk).
If you limit the maximum total weight like you did in your code assuming all weights are one you still run in O(weight), which I assume you set to a large value since the graph is large.
You need to figure out if you really need all those paths.
If you are looking for the shortest path use Dijkstra or something for finding the shortest path.
Given a .dot representation of a graph, I'd like to be able to compile some statistics about each node. Statistics could be: # of edges, # of levels, # of nodes.
Is there a package available that lets me do this?
Yes, this comes with graphviz out of the box.
General statistics about a graph can be obtained by feeding your graph into gc - count graph components:
gc (...) prints to standard output the number of nodes, edges, connected
com- ponents or clusters contained in the input files.
If you would like to generate more specific stats about your graph, you can use the tool gvpr - graph pattern scanning and processing language.
gvpr allows executing a custom script against your graph. The script may simply gather custom statistics like in your case, or it may even modify the input graph.
The above linked documentation is very complete and explains all the available properties and features better than I can do here. Below just a simple example to get you started.
If we have the following graph graph.gv:
digraph graphinfotest {
a -> {b; c; d} -> e;
b -> c;
}
The following gvpr script (in file graphinfo.gvpr):
BEG_G {
int n = nNodes($G);
int e = nEdges($G);
printf("There are %d nodes and %d edges in %s\n", n, e, $G.name);
}
N {
printf("Node %s - indegree %d, outdegree %d\n", $.name, $.indegree, $.outdegree);
}
Called with
gvpr -f graphinfo.gvpr graph.gv
Will produce the following output:
There are 5 nodes and 7 edges in graphinfotest
Node a - indegree 0, outdegree 3
Node b - indegree 1, outdegree 2
Node c - indegree 2, outdegree 1
Node d - indegree 1, outdegree 1
Node e - indegree 3, outdegree 0
What is the difference between the terms edge and path in graph data structure?
An edge is something that connects two nodes. A path is a series of edges in sequence that defines a "path" from node A to node B.
http://en.wikipedia.org/wiki/Graph_(data_structure)
Edge: connects node one node to another. So there no nodes present between node A and B.
eg. A<-->B or A-->B or A<---B.
Path: Connects 1 or more nodes to each other. So path contains 1 or more edges.
eg. 1.) A---B---C : here path is ABC
2.)
A
/ \
B C
/
D
Here different paths are A-B-C and A-C.
Different edges are: A-B, B-C, A-C.
I hope this clears your doubt
Edge is a connection between two vertices of the graph.
Consider the graph a b
6---4----5
| | \ e
c | d| 1
| | / f
3----2
g
a,b,c,d,e represents the edges of the graphs where as a path can be path from a to g that can be a,b,d,g or a,c,g.
Edge is a point/dot ( maybe starting point, mid point, ending point).
Path is a line( sequence of point/dot makes a line).
A graph is two tuple G = (V, E), where:
V -> set of vertices (points/nodes or whatever you call it)
E -> set of edges (a line which connects any two vertices)
Such that: (v,u) belongs to E (set of edges) => v, u belongs to V (set of vertices).
Now, when we talk about paths: These are series of connected edges, which starts from a vertex and ends in another vertex.
Then you have several types of graphs : i.e. Connected/disconnected directed/undirected weighted/unweighted graphs.
Further reading : http://en.wikipedia.org/wiki/Graph_(mathematics)
Hope it helps!!
An edge connects two nodes and path is sequence of nodes and edges.
How can we detect if a directed graph is cyclic? I thought using breadth first search, but I'm not sure. Any ideas?
What you really need, I believe, is a topological sorting algorithm like the one described here:
http://en.wikipedia.org/wiki/Topological_sorting
If the directed graph has a cycle then the algorithm will fail.
The comments/replies that I've seen so far seem to be missing the fact that in a directed graph there may be more than one way to get from node X to node Y without there being any (directed) cycles in the graph.
Usually depth-first search is used instead. I don't know if BFS is applicable easily.
In DFS, a spanning tree is built in order of visiting. If a the ancestor of a node in the tree is visited (i.e. a back-edge is created), then we detect a cycle.
See http://www.cs.nyu.edu/courses/summer04/G22.1170-001/6a-Graphs-More.pdf for a more detailed explanation.
Use DFS to search if any path is cyclic
class Node<T> { T value; List<Node<T>> adjacent; }
class Graph<T>{
List<Node<T>> nodes;
public boolean isCyclicRec()
{
for (Node<T> node : nodes)
{
Set<Node<T>> initPath = new HashSet<>();
if (isCyclicRec(node, initPath))
{
return true;
}
}
return false;
}
private boolean isCyclicRec(Node<T> currNode, Set<Node<T>> path)
{
if (path.contains(currNode))
{
return true;
}
else
{
path.add(currNode);
for (Node<T> node : currNode.adjacent)
{
if (isCyclicRec(node, path))
{
return true;
}
else
{
path.remove(node);
}
}
}
return false;
}
approach:1
how about a level no assignment to detect a cycle. eg: consider the graph below. A->(B,C) B->D D->(E,F) E,F->(G) E->D As you perform a DFS start assigning a level no to the node you visit (root A=0). level no of node = parent+1. So A=0, B=1, D=2, F=3, G=4 then, recursion reaches D, so E=3. Dont mark level for G (G already a level no assigned which is grater than E) Now E also has an edge to D. So levelization would say D should get a level no of 4. But D already has a "lower level" assigned to it of 2. Thus any time you attempt to assign a level number to a node while doing DFS that already has a lower level number set to it, you know the directed graph has a cycle..
approach2:
use 3 colors. white, gray, black. color only white nodes, white nodes to gray as you go down the DFS, color gray nodes to black when recursion unfolds (all children are processed). if not all children yet processed and you hit a gray node thats a cycle.
eg: all white to begin in above direct graph.
color A, B, D, F,G are colored white-gray. G is leaf so all children processed color it gray to black. recursion unfolds to F(all children processed) color it black. now you reach D, D has unprocessed children, so color E gray, G already colored black so dont go further down. E also has edge to D, so while still processing D (D still gray), you find an edge back to D(a gray node), a cycle is detected.
Testing for Topological sort over the given graph will lead you to the solution. If the algorithm for topsort, i.e the edges should always be directed in one way fails, then it means that the graph contains cycles.
Another simple solution would be a mark-and-sweep approach. Basically, for each node in tree you flag it as "visited" and then move on to it's children. If you ever see a node with the "visted" flag set, you know there's a cycle.
If modifying the graph to include a "visited" bit isn't possible, a set of node pointers can be used instead. To flag a node as visited, you place a pointer to it in the set. If the pointer is already in the set, there's a cycle.