After reading this code, I see two issues.

First, this line:
   p=. 1 1 $ y
should be
   p=. ,. y

The original supported multiple start nodes, and I do not yet see any
simplicity advantages to considering only a single starting node.  We
already need to deal with multiple paths, so why not allow that right
from the start?

But this is a problem for me:
  from =. {:"1 p               NB. anodes of current path-ends
here, you assume that paths do not branch, and I explicitly want to
allow branches.

You could probably do something with
   to=. p { g
   nto=. +/"1 to >_1
   p=. (+/"1 nto)#p
   ...

but hypothetically speaking I could get similar performance
characteristics by using a sparse array for the graph?

Thanks,

-- 
Raul

On Thu, Feb 14, 2013 at 7:40 PM, Mike Day <[email protected]> wrote:
> Not very sophisticated,  and the first verb (wrapa) below doesn't even
> reproduce your answer for N=6 ,  but it might be a starting point for
> further work.  The second verb (wrapb) does work for N=6, but apparently
> greatly overestimates the number for your larger 2000 node graph!
>
> wrapa=: 1 : 0
> :
>   g =. <: > >:@I.each <"1 m   NB. unboxed list of bnodes for each anode,
> with _1 as filler
>   p =. 1 1 $ y                NB. initial path matrix
>   N =. x
> while. N =.<: N do.
>   from =. {:"1 p               NB. anodes of current path-ends
>   to   =. from{g               NB. bnodes for each anode
>   nto  =. +/"1 to >_1          NB. count number of bnodes for each anode
>   p    =. nto#p                NB. expand rows of path matrix
>   p    =. p,. _1 -.~,to        NB. append new path-ends
>   p    =. ~.p                  NB. remove repeats
>   p    =. (#~ {:@$ = #@~."1) p NB. exclude paths with repeated nodes
> end.
> p
> )
>
>    [w6=:I."1]6 graph wrap 0   NB. original
> 0 4  6 14 15 16
> 0 4  6 14 15 18
> 0 6  7 14 15 16
> 0 6  8 14 15 16
> 0 6 12 14 15 16
> 0 6 14 15 16 18
> 0 3  6 14 15 18
>
>    [w6a=:/:~ 6 graph wrapa 0 NB. new
> 0 14 15 6 16  7
> 0 14 15 6 16  8
> 0 14 15 6 16 12
> 0 14 15 6 18  3
>
>    w6 -. /:~"1 w6a  NB. paths missed by new approach
> 0 4  6 14 15 16
> 0 4  6 14 15 18
> 0 6 14 15 16 18
>
> I don't see how these are "paths",  and so I'm probably missing something
> that you require.
>
> However, this verb does yield the same results for N=6; the paths seem to be
> trees:
>
> wrapb=: 1 : 0
> :
>   g =. <: > >:@I.each <"1 m   NB. unboxed list of bnodes for each anode,
> with _1 as filler
>   p =. 1 1 $ y                NB. initial path matrix
>   N =. x
> while. N =.<: N do.
>   from =. p                    NB. all anodes of current paths
>   to   =. from{g               NB. bnodes for each anode
>   nto  =. +/"1^:2 to >_1       NB. count number of bnodes for each anode
>   p    =. nto#p                NB. expand rows of path matrix
>   p    =. /:~"1 p,. _1 -.~,to  NB. append new bnodes and sort
>   p    =. ~.p                  NB. remove repeats
>   p    =. (#~ {:@$ = #@~."1) p NB. exclude paths with repeated nodes
> end.
> p
> )
>
> But now it produces too many "paths" in your larger example,  albeit pretty
> fast:
>    timer'#10 graph2 wrapb 0'  NB. apparently 12 times too many "paths"
> +--------+-----+
> |0.868896|72258|
> +--------+-----+
>
> ("timer" is a variant of ts which shows time in seconds and the result)
>
> wrapa is quicker but presumably wronger!
>
>    timer'#10 graph2 wrapa 0'   NB. apparently 10 times too few "paths"
> +---------+---+
> |0.0170898|556|
> +---------+---+
>
> Anyway,  I should think some variation on one of these verbs might scale
> better than the incidence matrix approach,  and produce something like the
> results you need!
>
> Mike
>
>
> On 13/02/2013 9:38 PM, Raul Miller wrote:
>
>> Since I messed up the description, I'll just pose an example solution
>> and ask for improvements.
>>
>> graph=: 1= ?.20 20$10
>>
>> start=: ,:0=i.#graph
>>
>> gather=: 1 :'[: ~.@; <@u'
>>
>> wrap=: 1 :0
>> :
>>    graph=. m
>>    start=. ,:(i.#graph) e. y
>>    N=. x
>>    paths=. (+./ .* # (+."1 =@i.@#))&graph"1 gather^:(N-1) start
>>    (N=+/"1 paths)#paths
>> )
>>
>> Here's a representation of the graph I'm using:
>>     #.graph
>> 64 1536 4 72 3200 8224 296960 8225 65536 8192 32 524800 48 513 65 160
>> 16416 32849 576 526466
>>     $#:#.graph
>> 20 20
>>
>> Here's a count of visitable sets of six nodes starting from node 0
>>     #6 graph wrap 0
>> 17
>>
>> In other words, wrap is an adverb which takes a graph and derives a
>> verb to generate the distinct visitable sets of length x starting from
>> the list of nodes indexed by the right argument.
>>
>> Now, let's say that we wanted to scale this up to deal with a couple
>> thousand nodes (but with similar connectivity):
>>    graph2=: 1=?.2000 2000$1000
>>
>> Here, the algorithm I implemented starts getting slow when I look for
>> paths of length 100 (it's just under 6000 paths).
>>
>>     #10 graph2 wrap 0
>> 5945
>>
>>     ts '#10 graph2 wrap 0'
>> 13.7496 4.34907e8
>>
>> That's a bit slow. Now let's imagine that I'm interested in finding
>> this path count for paths of length 100, in a reasonable amount of
>> time (let's say "less than a minute" for the sake of argument).  In
>> this case, I believe that my reference implementation can only serve
>> as an example.
>>
>> Better?
>>
>> Thanks,
>
>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to