good chemistry is complicated,and a little bit messy -LW PerlMonks

### Re^9: Finding All Paths From a Graph From a Given Source and End Node

by BrowserUk (Pope)
 on Nov 02, 2010 at 15:43 UTC ( #869027=note: print w/replies, xml ) Need Help??

ehm? :) Z => "K", "A", "Z",

I assume from that you are complaining that the graph has a self-referential node?

But why? A graph with self referencing nodes is still a graph, and algorithms have to handle them.

Is my (currently running) run of your algorithm ever going to stop

It did.! Just counting, it took 12% longer than mine which invokes a callback for each path.

```c:\test>junk
5014604
458

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.
• Comment on Re^9: Finding All Paths From a Graph From a Given Source and End Node

Replies are listed 'Best First'.
Re^10: Finding All Paths From a Graph From a Given Source and End Node
by LanX (Cardinal) on Nov 02, 2010 at 15:56 UTC
It did.! Just counting, it took 12% longer than mine which invokes a callback for each path.

interesting ... I'll take a look at it tomorrow!

Cheers Rolf

UPDATE: I expected this part { %\$seen } to be quite expensive .... does it even make sense?

UPDATE: I expected this part { %\$seen } to be quite expensive .... does it even make sense?

Well, it does no harm :)

Um. Do you mean:

• Does the syntax make sense?

It just makes a copy (anonymous reference) of the seen hash(ref).

• Or; why make a copy?

I make a copy because I want any changes made to it at deeper levels of recursion, to be unwound as the recursion unwinds.

It's purpose is obviously to prevent the algorithm from going in circles when it re-encounters a node it has already visited. But when we visit a node a deeper level we don't to permanently prevent it from visiting that node again if it reaches it via different path earlier in the recursion but later in the iteration.

Hm. Not sure that description works?

Essentially, the hash(ref) \$seen and array(ref) \$path contain the same information, but arrays are no good for lookup, and hashes are unordered which is no good for paths. Hence using both.

There is a potential optimisation there. I could just build the hash from the array at each level instead of passing it through. In fact, I'll try that later.

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.

Hi,

Even though this thread is about 6 months old I find it really very useful, as I am currently working on a similar project and have struggled with it, being quite a young programmer.I have read through it all and feel that I might be able to get the help that I need.

I have a network containing about 2500 edges (directed) and I am looking at being able to work out all the routes downstream from a given beginning node. The difference from neversaint's problem is that both beginning and end nodes are supplied in his.My initial concerns was that it'd result in very large output that may not be manageable but considering that it is currently not a very large network and that I really need to identify all the routes i am willing to give it a try.

I will be happy to have your inputs and thoughts

Thank you very much in advance

And the culprit was ... usage of self-documenting variable names.

Simply avoiding the array-copy my @path=@_ makes a factor 4.5 performance boost...

Fascinating!!! What a pity Perl doesn't support aliasing out of the box!

```{
my %seen;
sub track {
my \$last=\$_[-1];
\$seen{\$last}=1;

for my \$next (@{\$graph{\$last}}) {
next if \$seen{\$next};
if (\$next eq \$stop) {
#print join ("->",@_,\$stop),"\n";
\$anzahl++;
print "\$anzahl at ",time-\$time0,"\n" if \$anzahl%10000==0;
} else {
track(@_,\$next);
}
}
delete \$seen{\$last};
}
}

Cheers Rolf

Simply avoiding the array-copy my @path=@_ makes a factor 4.5 performance boost...

Wow. I'm amazed that avoiding the copying of such a small array had such a dramatic affect on the performance. I guess it must be being copied very many times.

In mine, I tried building the hash from the array rather than carrying it around, and it produced an ~8% speed-up. Then I tried using \$_[n] instead of named parameters and it leached less than 5% more. The first is worth having, the second not:

```sub _findPaths3 {
return \$_[0]->( @{ \$_[4] }, \$_[3] ) if \$_[2] eq \$_[3];
my %seen; \$seen{ \$_ } = 1 for @{ \$_[4] }, \$_[2];
for ( grep !\$seen{ \$_ }, @{ \$_[1]->{ \$_[2] } } ) {
_findPaths3( \$_[0], \$_[1], \$_, \$_[3], [ @{ \$_[4] }, \$_[2] ] ),
}
}

sub findPaths3(&@) { _findPaths3( @_, [] ); }

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.

Create A New User
Node Status?
node history
Node Type: note [id://869027]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (7)
As of 2021-01-21 09:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
The STEM quote I most wish I'd made is:

Results (229 votes). Check out past polls.

Notices?