Ah, excellent.

require'stats'

parRDM=:4 :0
  x (1+y-x) P y
)

combine=:1 :0
:
  q=.(#;{.x)=#@>y
  if.1 e.,q do.
    b=. ,(<./@>x)<:/ q <./@;@#"1 y
    b # ,/  x ([,] ({L:0 ,) (i.m)-.S:0 [)"0 1/  y
  else.
    ,/ x ([,] ({L:0 ,) (i.m)-.S:0 [)"0 1/  y
  end.
)


P=:1 :0
:
  NB. x: number of partitions
  NB. m: maximum allowed partition size
  NB. y: number of items to distribute across partitions
  if. y>x*m do.return. end.
  if. (0=m)+.y<x do.return.end.
  if.1=x do. ,.<"1 m comb y return.end.
  r=.i.0 0
  for_n. 1+i.m do.
    t=.(x-1) (m<.(y-n)<.n) P y-n
    if. 0=#t do. continue. end.
    c=.<"1 n comb y
    r=.r, c y combine t
  end.r
)

parELMDE=: 4 : 0
  a =. ~. i.~"1 iy #: i. */ iy =. (1+i.x),(y-x)$x
  a =. a#~ x = #@~."1 a
  sort a </."1 i. y
)

timerat=:4 :0"0
  try.
    elmde=.6!:2 'vE=. x parELMDE y'
    rdm=.6!:2 'vR=. x par y'
    r=. rdm%elmde
  catch.
    vR=.vE=.0
    r=. _
  end.
  assert. vR -:&(/:~)&:(/:~"1)&:(/:~&.>) vE
  r
)

For the simple (and fast) cases, parELMDE tends to be significantly
faster than my parRDM. Low complexity pays off:

   3 timerat 4
2.59375

However, for other cases, it tends to be significantly slower. Here,
low complexity does not pay off enough to amortize big-O issues:

   6 timerat 8
0.067733

Or, a slightly better overview (better viewed with fixed width font or
run it yourself):

   9!:11]3 NB. reduce display precision, for email line widths

   (1+i.10) timerat table 1+i.10
┌───────┬─────────────────────────────────────────────────────────────┐
│timerat│   1    2    3    4    5     6      7      8       9       10│
├───────┼─────────────────────────────────────────────────────────────┤
│ 1     │1.03 1.38 1.67 1.82  2.3   2.5    2.9    3.1     3.4      3.7│
│ 2     │   _ 5.43 3.28 5.13  3.6  3.95   2.36   2.37    1.52     1.58│
│ 3     │   _    _ 5.46 3.24 3.24  2.27   1.46   1.43    0.83    0.763│
│ 4     │   _    _    _ 2.94 1.74  1.44  0.961  0.668   0.599    0.621│
│ 5     │   _    _    _    _ 2.08 0.514  0.374  0.325   0.315    0.311│
│ 6     │   _    _    _    _    _ 0.566 0.0929 0.0876  0.0951    0.124│
│ 7     │   _    _    _    _    _     _ 0.0936 0.0156  0.0177   0.0323│
│ 8     │   _    _    _    _    _     _      _ 0.0117 0.00192  0.00209│
│ 9     │   _    _    _    _    _     _      _      _ 0.00256 0.000176│
│10     │   _    _    _    _    _     _      _      _       _  0.00019│
└───────┴─────────────────────────────────────────────────────────────┘

Thanks,

-- 
Raul

On Sun, Oct 29, 2017 at 7:38 AM, Erling Hellenäs
<[email protected]> wrote:
> Hi all!
>
> Here Mike Days modification of Esa Lippu algorithm with a fix to generate
> less combinations.
> Faster and uses less memory.
>
>
> parELMDE=: 4 : 0
>
> a =. ~. i.~"1 iy #: i. */ iy =. (1+i.x),(y-x)$x
>
> a =. a#~ x = #@~."1 a
>
> sort a </."1 i. y
>
> )
>
>
>     ts'x parELMDE y'
>
> 0.000135765 61440
>
> ts'x parMD y'
>
> 0.000311426 224640
>
>
>
> Cheers,
>
> Erling Hellenäs
>
>
>
>
>
> On 2017-10-29 02:16, Raul Miller wrote:
>>
>> Here's a debugged version of par that seems to have reasonable
>> performance (and good big-O structure):
>>
>> require'stats'
>>
>> par=:4 :0
>>    x (1+y-x) P y
>> )
>>
>> combine=:1 :0
>> :
>>    q=.(#;{.x)=#@>y
>>    if.1 e.,q do.
>>      b=. ,(<./@>x)<:/ q <./@;@#"1 y
>>      b # ,/  x ([,] ({L:0 ,) (i.m)-.S:0 [)"0 1/  y
>>    else.
>>      ,/ x ([,] ({L:0 ,) (i.m)-.S:0 [)"0 1/  y
>>    end.
>> )
>>
>>
>> P=:1 :0
>> :
>>    NB. x: number of partitions
>>    NB. m: maximum allowed partition size
>>    NB. y: number of items to distribute across partitions
>>    if. y>x*m do.return. end.
>>    if. (0=m)+.y<x do.return.end.
>>    if.1=x do. ,.<"1 m comb y return.end.
>>    r=.i.0 0
>>    for_n. 1+i.m do.
>>      t=.(x-1) (m<.(y-n)<.n) P y-n
>>      if. 0=#t do. continue. end.
>>      c=.<"1 n comb y
>>      r=.r, c y combine t
>>    end.r
>> )
>>
>> This could obviously be made a bit more concise,
>>
>> I haven't really been tracking this thread to figure out which are the
>> good performing (and, working properly) variants to test against, if
>> performance is an issue. I have, however, tested it a bit for
>> correctness. Here's the "test suite":
>>
>> NB. borrowed from Lippu Esa
>> nparts=: 4 : 0
>>    a=.(y#x) #: i. x^y
>>    sort ~.((x=#@~."1 a)#a) </."1 i.y
>> )
>>
>> chk=:2 :0
>> :
>>    try.
>>      assert x (u -:&(/:~)&:(/:~"1)&:(/:~&.>) v) y
>>    catch.
>>      echo (":x),' par ',(":y),' NB. failed'
>>      throw.
>>    end.
>> )
>>
>> check=:par chk nparts
>>
>> 1 check 1
>> 1 check 2
>> 2 check 2
>> 1 check 3
>> 2 check 3
>> 3 check 3
>> 1 check 4
>> 2 check 4
>> 3 check 4
>> 4 check 4
>> 1 check 5
>> 2 check 5
>> 3 check 5
>> 4 check 5
>> 5 check 5
>> 1 check 6
>> 2 check 6
>> 3 check 6
>> 4 check 6
>> 5 check 6
>> 6 check 6
>>
>> 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