I had a look at using my earlier offerings, ix and u, which I'd
observed to be non-commutative in my note of around 25 October.
The best derivations I found were
ixcom =: ix #/@:|:@:(<./"3)@:((~. ,.~ #/.~)@:/:~&>)@:; ix~
ucom =: u #/@:|:@:(>./"3) @:((~.,.~#/.~)@:/:~ every )@:; u~
which display as pretty verbose if one applies "f. "
They produce the same sorted results as IS_reb and UN_reb, and
are probably a bit slower; "timer" just looks at elapsed time:
timer'#a (ixcom -: /:~@: IS_reb) a + 49999'
+-----+-+
|4.945|1|
+-----+-+
timer'#a (ucom -: /:~@: UN_reb) a + 49999'
+-----+-+
|5.339|1|
+-----+-+
No improvement so far.
So it occurred to me to see if there was anything relevant in Dyalog
APL's "dfns" workspace, a compendium of many interesting and often useful
examples of John Scholes' "dynamic functions" (hence "dfns"). Roger has
had a hand in later developments, I believe.
Indeed, there's a new (to me) function, "bags" which packages anumber
of "multiset" or "bag" operations, including union and intersection.
I'll list the whole thing below, but just show a few example J
verbs/adverbs
and leave the rest as an exercise!?
The key to the approach is called "progressive dyadic", which involves a
ranking a concatenation of both arrays, which perhaps goes some way to
explaining its pedestrian performance.
NB. Progressive dyadic - attributed to Bob Smith in Dyalog DFNS workspace
pd0 =: /:^:2 @ (i.~ ,&'')~
pd =: 1 : 0
:
((#x){. x pd0 x,y) u (#y){. x pd0 y,x
)
pde =: e. pd
pdi =: i. pd
mad =: [#~ -.@:pde
ubag =: [, mad~ NB. union
ixbag =: [#~ pde NB. intersection
e_bag =: pde NB. progressive membership
i_bag =: pdi NB. progessive index
Using Dyalog's example,
A =: 2 1 2 1 3 2 5
B =: 3 4 2 1 2 3
A ixbag B
2 1 2 3
A ubag B
2 1 2 1 3 2 5 4 3
A i_bag B
4 7 0 1 2 7
A e_bag B
1 1 1 0 1 0 0
... and as I warned, the time-performance is poor:
timer'#a (ixbag -: /:~@: IS_reb) a + 49999'
+------+-+
|13.202|1|
+------+-+
timer'#a (ubag -: /:~@: UN_reb) a + 49999'
+------+-+
|13.583|1|
+------+-+
I expect the performance can be improved a bit, but
probably not so much as to compete with the _reb verbs.
Here's an attempt at displaying the "bags" operator,
commented with J's NB.'s :
NB. ∇bags←{ ⍝ Multisets / bags.
NB. [1] pd_←{ ⍝ "progressive dyadic
..." (Bob Smith).
NB. [2] r←(⍴⍵)⍴⍋⍋(⍺,⍬)⍳⍵,⍺
NB. [3] l←(⍴⍺)⍴⍋⍋(⍺,⍬)⍳⍺,⍵
NB. [4] l ⍺⍺ r
NB. [5] }
NB. [6] pde←∊pd_ ⍝ progressive dyadic epsilon.
NB. [7] pdi←⍳pd_ ⍝ progressive dyadic iota.
NB. [8] mad←{(~⍺ pde ⍵)/⍺} ⍝ multiset asymmetric
difference.
NB. [9]
NB. [10] aa←⍺⍺ ⋄ fn←⍬⍴⎕CR'aa' ⍝ '~', '∪', etc.
NB. [11]
NB. [12] 0::⎕SIGNAL ⎕EN ⍝ signal any error to caller.
NB. [13]
NB. [14] 0=⎕NC'⍺':{ ⍝ monadic call.
NB. [15] '∪'≡fn:⍵,⍬ ⍝ unique (noop for vector).
NB. [16] ⎕SIGNAL 16 ⍝ unexpected operand:
nonce error.
NB. [17] }⍵
NB. [18]
NB. [19] '≡'≡fn:((⍴⍺)≡⍴⍵)>0∊⍺ pde ⍵ ⍝ match.
NB. [20] '≢'≡fn:((⍴⍺)≡⍴⍵)≤0∊⍺ pde ⍵ ⍝ natch.
NB. [21] '~'≡fn:⍺ mad ⍵ ⍝
without. ⍺~⍵
NB. [22] '∪'≡fn:⍺,⍵ mad ⍺ ⍝
union. ⍺,⍵~⍺
NB. [23] '∩'≡fn:((⍺ pde ⍵)/⍺) ⍝ intersection.
NB. [24] '∊'≡fn:⍺ pde ⍵ ⍝ progressive membership.
NB. [25] '⍳'≡fn:⍺ pdi ⍵ ⍝ progressive dyadic iota.
NB. [26] 3=⎕NC'⍺⍺':⎕SIGNAL 16 ⍝ unexpected operand:
nonce error.
NB. [27] '§'≡⍺⍺:(⍺ mad ⍵),⍵ mad ⍺ ⍝ multiset symmetric
difference (msd).
NB. [28] ⎕SIGNAL 16 ⍝ unexpected operand:
nonce error.
NB. [29] }
NB. ∇
Might be useful for developing J ideas,
Mike
On 30/10/2018 09:46, R.E. Boss wrote:
IMO we should interpret the intersection and the union of two (multi)sets (sets X with
X >:&# ~.X) in the same way as is done by the GCD and the LCM of two numbers.
So for two numbers N and M with (multi)sets of primefactors A and B, we should
have (N +. M) = */(A IS B) and (N *. M) = */ (A UN B), with IS=intersection and
UN = union of the (multi)sets A and B.
Obviously we require (A IS B) =&(/:~) B IS A and also (A UN B) =&(/:~) B UN A
for all (multi)sets A and B.
E.g.
1 2 3 3 3 IS 3 3 3 3 3 4 5 6
3 3 3
1 2 3 3 3 UN 3 3 3 3 3 4 5 6
1 2 3 3 3 3 3 4 5 6
What are elegant and efficient J-definitions for IS and UN?
I have constructed
UN_reb=: ([:(~.@{.#~ {. >.//.{:) |:@,&(({.,#)/.~))
and
IS_reb=: ([:(~.@{.#~ {. <.//.{:) ([|:@, ],~ 0,.~ -.~&:({."1),
-.&:({."1))&(({. , #)/.~))
1 2 3 3 3 UN_reb 3 3 3 3 3 4 5 6
1 2 3 3 3 3 3 4 5 6
1 2 3 3 3 IS_reb 3 3 3 3 3 4 5 6
3 3 3
1 2 3 3 3 UN_reb~ 3 3 3 3 3 4 5 6
3 3 3 3 3 4 5 6 1 2
1 2 3 3 3 IS_reb~ 3 3 3 3 3 4 5 6
3 3 3
a=: 1e7?.@#1e6
ts'a UN_reb a+499999'
0.76631908 4.6996013e8
#a UN_reb a+49999
12186812
ts'a IS_reb a+499999'
0.76073743 3.3554592e8
#a IS_reb a+49999
7813188
R.E. Boss
----------------------------------------------------------------------
For information about J forums see http://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