Mike, thank you

recon verb does check for improvements - it would not give correct results
otherwise. It just looks a bit obscure, because it merges old and better
tables by multiplying both to bitmasks and adding - this turned out to be
the fastest way, I've tried several other ways - they are slower (funny,
that the first my idea was to do it exactly this way, but I dismissed
thinking it is too hackish and will be slow).

The way you collect path with ^:a: resembles what I come up with  (it is
below), interesting. The algo in J turned out to be amazingly fast - it
solves 600x600 in a couple of seconds (I remember doing Deijksra OSPF in
another dynamic language and it was waaaay slower for smaller networks ~50
nodes)

Danil

floyd =: 3 : 0 NB. return nexthop table and distances

nh =. ($y)$(#y)(I.,y=_)}(*:$i.)#y NB. initialize next-hop table, #y means
unreachable

for_k. i.#y do.

m =. y ~:[ny =. y <. k ({"1 +/ {) y NB. ny are improved distances, m is a
mask were there is an improvement

nh=. (nh*-.m)+m* k{"1 nh NB. set next-hop through k where there is an
improvement

y=. ny

end.

nh;y

)


floydpath =:(0{"1(13 :'(}.y),~x{~<y')^:a:) :: '' NB. x is nexthop table, y
is (src,dst), path is not empty if exists

pathtable =: (<@floydpath"2 1) ([:,"0/~ [:i.#) NB. make the table of paths
for nh y

pathtable 0 {:: floyd mx

┌─┬───┬─────┐

│0│0 1│0 1 2│

├─┼───┼─────┤

│ │1 │1 2 │

├─┼───┼─────┤

│ │ │2 │

└─┴───┴─────┘




2018-03-05 17:40 GMT+03:00 'Mike Day' via Programming <
[email protected]>:

> AND AGAIN!  Will get it right this time...
>
> Sorry for a partial message just now - I was editing and pressed send
> by mistake!
>
> Raul's obviously done a lot on this - I'd been drafting something, so I'll
> send what I was working on.
>
> I think the recon verb needs a check on whether there are any improvements.
> Anyway,  here are my tries.
>
> fwalg is the unadorned minimum distance algorithm,  fwtree the same with
> the
> additional bits to provide the tree,  and fwpath and fwpatht use the tree
> to
> return required paths.
>
> NB. input y = graph as matrix of weighted arcs
> NB. output matrix d of shortest distances between row i, col j
> fwalg =: 3 : 0
> d   =. y
> for_k. i.#d do.
>    d =. d <. k ({"1 +/ {) d
> end.
> d
> )
>
> NB. input weighted graph as matrix
> NB. using _1 as null
> fwtree =: 3 : 0
> dist =. y
> n    =. {. shape =. $ dist
> next =. <: (dist -.@e. 0 _) * >: n|i.2#n
> for_k. i.#dist do.
>  try   =. k ({"1 +/ {) dist
>  if. +/ok    =. ,dist > try do.
>    'i j' =. |:ij =. shape #: I. ok
>    ik    =. <"1 i,. k
>    ij    =. <"1 ij
>    dist  =. (ij { try)  ij } dist
>    next  =. (ik { next) ij } next
>  end.
> end.
> next
> )
>
> NB. x = result of fwtree g
> NB. y = u v
> fwpath  =: 3 : 0
> :
> next    =. x, _1
> uv      =. < 'u v'   =.  y
> path    =. u
> while. _1 < u =. uv { next do.
>       u    =. uv { next
>       uv   =. <u, v
>       path =. path, u
> end.
> )
>
> NB. tacit version
> fwpatht =: 3 : 0
> :
> {."1 }:({:,~(x,_1){~<)^:a: y
> )
>
> NB. tacit version
> fwpatht =: 3 : 0
> :
> {."1 }:({:,~(x,_1){~<)^:a: y
> )
>
> Results on Danil's mx matrix.  Perhaps it's ok for a null path just
> to include the from-node.
>
> NB.  I haven't bothered with index 1, so nodes are numbered 0 1 2 ...
> NB.  Easy enough to change.
>
>    mx
> 0 1 4
> _ 0 2
> _ _ 0
>    fwalg mx
> 0 1 3
> _ 0 2
> _ _ 0
>    fwtree mx   NB. _1 used as null.
> _1  1  1
> _1 _1  2
> _1 _1 _1
>    (fwtree mx)&fwpath each 0 1;0 2;2 0
> +---+-----+-+
> |0 1|0 1 2|2|
> +---+-----+-+
>    (fwtree mx)&fwpatht each 0 1;0 2;2 0
> +---+-----+-+
> |0 1|0 1 2|2|
> +---+-----+-+
>
> That's what I'd meant to send - sorry for earlier deficient attempts!
>
> Mike
>
>
>
>
>
>
> On 05/03/2018 09:15, Danil Osipchuk wrote:
>
>> actually it seems that it is my code which works correctly, and the
>> rosetta's one has a mistake in the initialization of the next-hop table.
>> Or
>> am I missing something?
>> the same toy example, for unidirectional graph there is no way back from
>> nodes 1 and 2 back to  0:
>>
>> [mx=: 3 3 $ 0 1 4 _ 0 2 _ _ 0
>>
>> 0 1 4
>>
>> _ 0 2
>>
>> _ _ 0
>>
>>
>> The initialization in rosetta version says there is a way back:
>>
>> y=:mx
>>
>> ((|i.@,~)#y)*1>.y->./(,y)-._
>>
>> 0 1 2
>>
>> 0 1 2
>>
>> 0 _ 2
>>
>>
>> NB. modify to return both next-hops and metrics:
>>
>> floydrecon=: verb define
>>
>> n=. ((|i.@,~)#y)*1>.y->./(,y)-._
>>
>> for_j. i.#y do.
>>
>> d=. y <. j ({"1 +/ {) y
>>
>> b=. y~:d
>>
>> y=. d
>>
>> n=. (n*-.b)+b * j{"1 n
>>
>> end.
>>
>> n;y
>>
>> )
>>
>>
>>
>>
>> Basically, _ should appear in the same places:
>>
>> floydrecon mx
>>
>> ┌─────┬─────┐
>>
>> │0 1 1│0 1 3│
>>
>> │0 1 2│_ 0 2│
>>
>> │0 _ 2│_ _ 0│
>>
>> └─────┴─────┘
>>
>>
>>
>>
>>
>> 2018-03-05 11:33 GMT+03:00 Danil Osipchuk<[email protected]>:
>>
>> Raul, thank you
>>> the rosseta version works faster than every thing I tried, not to say
>>> giving correct results
>>> Danil
>>>
>>> 2018-03-05 0:12 GMT+03:00 Raul Miller<[email protected]>:
>>>
>>> You might get some ideas from
>>>> https://rosettacode.org/wiki/Floyd-Warshall_algorithm#J
>>>>
>>>> Good luck,
>>>>
>>>> --
>>>> Raul
>>>>
>>>>
>>>> On Sun, Mar 4, 2018 at 4:09 PM, Danil Osipchuk<[email protected]
>>>> >
>>>> wrote:
>>>>
>>>>> Hi, all
>>>>>
>>>>> I'm toying with the Floyd–Warshall algo
>>>>> http://code.jsoftware.com/wiki/Essays/Floyd  trying to extend it along
>>>>>
>>>> the
>>>>
>>>>> lines ofhttps://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
>>>>>
>>>> to
>>>>
>>>>> get a next-hop table
>>>>>
>>>>> I'm doing something wrong since what I came with is ugly in the
>>>>>
>>>> beginning,
>>>>
>>>>> in the middle and in the end and I barely think it works for a simplest
>>>>> cases.
>>>>> I'm sure there is a better way from which I could learn something.
>>>>> regards,
>>>>>    Danil
>>>>>
>>>>>
>>>>> merge =: 1 : 0  NB. m is a bit mask, merge x with values of y where m
>>>>>
>>>> is 1,
>>>>
>>>>> preserve shape
>>>>> :
>>>>> ($m)$(,m)}(x ,:&:, y)
>>>>> )
>>>>>
>>>>> floyd=: 3 : 0
>>>>>   nh =. (($y)$#y) (y < _) merge (i."0 #~#y) NB. initialize next-hop
>>>>>
>>>> table,
>>>>
>>>>> #y means unreachable
>>>>>   for_k. i.#y do.
>>>>>     m =. y > [dk =. k ({"1 +/ {) y          NB. dk is distance through
>>>>>
>>>> k, m
>>>>
>>>>> is a mask were it is an improvement
>>>>>     y =. y m merge dk                       NB. update the distance
>>>>> table
>>>>>     nh=. nh m merge (|: ($y)$ k{"1 nh)      NB. set next-hop through k
>>>>>
>>>> where
>>>>
>>>>> there is an improvement
>>>>>   end.
>>>>>   nh;y
>>>>> )
>>>>> --- transcript ---
>>>>>
>>>>> [mx=: 3 3 $ 0 1 4 _ 0 2 _ _ 0
>>>>> 0 1 4
>>>>> _ 0 2
>>>>> _ _ 0
>>>>>
>>>>>     floyd mx
>>>>> ┌─────┬─────┐
>>>>> │0 1 1│0 1 3│
>>>>> │3 1 2│_ 0 2│
>>>>> │3 3 2│_ _ 0│
>>>>> └─────┴─────┘
>>>>> ----------------------------------------------------------------------
>>>>> For information about J forums seehttp://www.jsoftware.com/forums.htm
>>>>>
>>>> ----------------------------------------------------------------------
>>>> For information about J forums seehttp://www.jsoftware.com/forums.htm
>>>>
>>> ----------------------------------------------------------------------
>> For information about J forums seehttp://www.jsoftware.com/forums.htm
>>
>
>
>
> ---
> This email has been checked for viruses by Avast antivirus software.
> https://www.avast.com/antivirus
> ----------------------------------------------------------------------
> 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