tsk1979 has asked for the wisdom of the Perl Monks concerning the following question:
I was experimenting with creating graphs in perl. No drawing involved, but simple graphs.
For example, imagine the start node A
Level 1 nodes are B1,B2
Level 3 nodes are C1,C2
Level 4 node is D
No all possible paths are
A-B1-C1-D
A-B1-C2-D
A-B2-C1-D
A-B2-C2-D
Now lets say I wanted a program to randomly create graphs.
So I would choose 4 levels or 5 levels etc.
The starting level would have just 1 node.
The subsequent levels can have 2-5 nodes(random, using rand() function.
Now lets say I wanted to print all possible paths in the format I listed above
I am wondering how to use perl for traversing all possible paths of the graph, and which is the fastest way to create a random graph.
I am leaning towards using hashes
My nodes can be identified by levels A,B,C,D... and so on
Then the hash can be node.B.1, node.B.2., node.B.3
The upper limit is controlled by rand() function.
I guess this is the right way.
After creating the hashes for all the nodes, I have to create paths, infact all possible paths, and print them as
A-B1-C2-D and so on etc.,
Re: Print all possible paths in a graph and some graph creation too!
by Ratazong (Monsignor) on Aug 17, 2010 at 06:20 UTC
|
CPAN::graph seems to be the thing you want to look at. It will give you some basic functionality for storing graphs and lots of functions to work on them.
HTH, Rata
| [reply] |
Re: Print all possible paths in a graph and some graph creation too!
by BrowserUk (Patriarch) on Aug 17, 2010 at 06:49 UTC
|
Now lets say I wanted a program to randomly create graphs. So I would choose 4 levels or 5 levels etc. The starting level would have just 1 node. The subsequent levels can have 2-5 nodes(random, using rand() function.
I think you need to clarify the range of expectations for your randomly generated graphs.
Your example starts with a single node, ends with a single node, and has all intervening nodes cross connected. Is that typical of what you want to generate? How about a direct path from node A to (say) Cn? Or Bn to D?
Perhaps you could hand generate 3 or 4 more examples that fit your expectations?
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
|
Okay, imagine my nodes as routes.
So if you want to go from level 1 to level 3, you have to pass through 1 level 2 node.
the ending node can be single, or there can be multiple nodes.
Imagine, all nodes are bus stops, and the paths are buses. A bus as to stop at all nodes it passes through.
So when going from level 1 to level 5, it has to pass through 1 node of each intermediate level.
All I want to do is
1. Create a random graph with 1 starting node, and 4-5 levels, with number of points at each level random. Last level can have one or many nodes, no issues here.
2. Print all possible Paths from A to the end nodes
So its more like a tree where you cannot go from the first level to an intermediate level by skipping the levels between the two.
| [reply] |
|
A quick solution to your issue (with a complexity of O((n*m)^2) (n being the number of levels and m the maximum nodes per level):
- as a structure for your nodes, simply have a hash with the name of the node-level (A, B, ...) and the numbers of nodes on that level
- As an algorithm, try the following
- traverse through each level
- generate all possible node-names of that level
- take all paths you already found and add the new node-names to each of them
The code below solves your issue. It is however just a short hack and in no way optimized. But it hopefully gives you an idea.
HTH, Rata
use strict;
use warnings;
my %nodes = ( A => 2, B => 4, C => 5, D => 1);
my @path = ("");
my @newpath;
foreach my $k (sort (keys(%nodes))) # each level
{
my @nodename;
for (my $i = 1; $i <= $nodes{$k}; $i++)
{
push (@nodename, "$k$i"); # generate
+ node-names for each level
}
foreach my $old (@path) # take all
+old paths
{
foreach my $new (@nodename) # appen
+d new node to each
{
push (@newpath, "$old-$new");
}
}
@path = @newpath; # save
+old paths
@newpath = (); # clear lis
+t of new paths
}
print join("\n", @path); # print all paths (each in a new line)
exit 0;
| [reply] [d/l] |
|
|
| [reply] |
Re: Print all possible paths in a graph and some graph creation too!
by pemungkah (Priest) on Aug 17, 2010 at 06:32 UTC
|
It's a good approach, particularly well-suited for sparse adjacency situations. Have you looked at Graph? It has random graphs and all-pairs-shortest-path, so theoretically you could just enumerate the "bottom" nodes and iterate over them, doing all-pairs-shortest-paths to get the paths. Graph can print them too.
This is of course assuming that all you want to do is solve the problem. If you're needing to implement the graph algorithms for some other reason, you'll have a fair amount more work to do - but hashes of hashes (or arrays of arrays, for that matter) would work fine. | [reply] |
|
All I need to do is
1. Create a graph randomly
2. Identify all possible paths from start node to all the end nodes
Graph creation with hashes seems to be the easier bit.
Its creating all the paths which is an issue.
| [reply] |
|
I guess it's just me, but last time I needed to do something like this (verify that there were no cycles in macro definitions), Graph let concentrate on what I wanted to do and let me forget about the nit-picky graph management.
Then again, I have written an AVL tree implementation in FORTRAN, so I shouldn't talk too much about doing things the hard way.
I'd implement something like this:
Create root-node hash
Current level is zero
Establish limits: max & min nodes per level, number of levels
root{A0} = add_levels($current_level, $level_limit, $min_nodes, $max_n
+odes);
sub add_levels {
return if current level is > the limit, bump it if not
calculate a random number between high and low limit
new_level = {};
for $n (0..$local_limit) {
generate $name from level and $n
new_level{$name} = add_levels($current_level, $limit, $min, $max
+)
}
return $new_level;
}
The printing code will be similar, but you'll instead pass a string down the recursive call tree, adding level names until you run out of levels, then printing it. The recursion plus the loop will automatically follow all paths for you.
I have written a program to do this but I'm not posting it; you'll learn a lot more if you follow this outline and write it yourself; as you don't want to handwave the details via Graph, I assume there's a reason for writing it yourself -- and me writing it for you won't teach you anywhere near as much.
I recommend running under the debugger, as you'll be able to x the growing data structure as you go along and see if it's working. | [reply] [d/l] |
Re: Print all possible paths in a graph and some graph creation too!
by MidLifeXis (Monsignor) on Aug 17, 2010 at 14:48 UTC
|
Perhaps a breadth-first search of the graph? Is this homework? It sounds a lot like problems from my undergrad studies.
| [reply] |
|
Nope, I am actually trying to create some graphs as test scenarios for software, to see if it breaks.
| [reply] |
|
|