RE: Re: Intersection[...,SameTest->test] ?
- To: mathgroup at smc.vnet.net
- Subject: [mg33155] RE: [mg33093] Re: Intersection[...,SameTest->test] ?
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Wed, 6 Mar 2002 01:55:30 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
> -----Original Message----- > From: Konstantin L Kouptsov [mailto:klk206 at is5.nyu.edu] To: mathgroup at smc.vnet.net > Sent: Friday, March 01, 2002 12:52 PM > To: mathgroup at smc.vnet.net > Subject: [mg33155] [mg33093] Re: Intersection[...,SameTest->test] ? > > > > Thanks to all who answered. Indeed, in version 4 the > mentioned function works > without problems; with the answer being as much meaningful as > the "test" being the > "equivalence" predicate (well, sometimes it is just what one > needs). My examples > were run using version 3.0, in which the implementation of > Intersection[..., SameTest->test] is buggy. > > Konstantin. > Aside from this technical problem with Version 3, the question was on the operational semantics of Intersection (as implemented in Mathematica) > > Konstantin L Kouptsov wrote: > > ... > > > > It is not clear from the manual (book or help browser), what this command > > is supposed to return. > > ... > > > > What idea stands behind this function? what is it supposed to do? > > As to my observation Intersection[a, b, SameTest -> tst] is just the same as Select[Sort[a], Function[s1, Or @@ Function[s2, tst[s1, s2]] /@ b ]] except for possible side effects when applying tst. (* You also may account for that if you wish, using proper Catch-Throw constructs: compare Select[Sort[a], Function[s1, Catch[Scan[ Function[s2, If[(Print[s1, "~", s2]; s1 == 2 s2), Throw[True]]], b]] ]] with Intersection[a, b, SameTest ->((Print[#1,"~",#2];#1==2 #2)&)] *) Given a = {1, 6, 0, 0, 8}; b = {3, 8, 0, 0}; In[15]:= Intersection[a, b, SameTest -> (True &)] Out[15]= {0, 0, 1, 6, 8} In[23]:= Intersection[a, {}, SameTest -> (True &)] Out[23]= {} In[35]:= Intersection[a, b, SameTest -> (#1 == 2*#2 &)] Out[35]= {0, 0, 6} In[168]:= Intersection[a, b, SameTest -> (#1 == #2&)] Out[168]= {0, 0, 8} but: In[170]:= Intersection[a, b] Out[170]= {0, 8} (This is to model set intersection, but with any test function unifying would be too restrictive.) In[148]:= Select[Sort[a], Or @@ Function[e, True] /@ b &] Out[148]= {0, 0, 1, 6, 8} In[149]:= Select[Sort[a], Or @@ Function[e, True] /@ {} &] Out[149]= {} In[105]:= Select[Sort[a], Or @@ Function[e, # == 2 e] /@ b &] Out[105]= {0, 0, 6} In[169]:= Select[Sort[a], Or @@ Function[e, # == e] /@ b &] Out[169]= {0, 0, 8} This is what the function does. For what you use it, is quite a different matter. This also applies to the logical primitives (and we know how to deal with that), viz.: In[95]:= (True || Print["hello"]) Out[95]= True In[97]:= (False || Print["hello"]) // InputForm >From In[97]:= "hello" Out[97]//InputForm= Null Short cut evaluation and passing non-logical expressions makes this resemble an If-expression. The lists a and b need not be of the same type, see e.g. In[157]:= isColor[hue_, "red"] := hue < 1/6 || hue > 5/6; isColor[hue_, "green"] := 1/6 <= hue < 1/2; isColor[hue_, "blue"] := 1/2 <= hue < 7/6 In[154]:= hh = Table[Random[Real], {10}] Out[154]= {0.599664, 0.131625, 0.377189, 0.410453, 0.502879, 0.588352, 0.601769, 0.554794, 0.801087, 0.767142} In[161]:= Intersection[hh, {"red", "blue"}, SameTest -> isColor] Out[161]= {0.131625, 0.502879, 0.554794, 0.588352, 0.599664, 0.601769, 0.767142, 0.801087} In[162]:= Intersection[hh, {"green"}, SameTest -> isColor] Out[162]= {0.377189, 0.410453} On the other hand, to make the SameTest function be an equivalence function, is just not enough for intuitive expectation. See In[8]:= x_~r~y_ := MatchQ[y/x, _Rational | _Integer] In[12]:= Table[Sqrt[Random[Integer, {1, 5}]]Random[Integer, {1, 10}], {100}] Out[12]= \!\({3\ \@3, 4\ \@2, 5, 5, 3\ \@5, 8, 8\ \@5, 5\ \@3, 5, 14, 5\ \@5, 8, 7\ \@2, 8\ \@3, 4\ \@5, 10, 12, 1, 12, 5\ \@2, 9\ \@5, 5\ \@5, 2\ \@3, 4, 5\ \@5, 10, 9\ \@3, 14, 14, 9\ \@3, 9, 5\ \@2, 8, 4\ \@2, 18, \@5, 9\ \@5, \@3, 3\ \@2, 8, 5, 8\ \@2, 7\ \@5, 9\ \@2, 6, 10\ \@3, 10, 9\ \@3, 10\ \@3, 5\ \@3, 3, 3\ \@5, 4, 12, 18, 12, 8\ \@2, 8, 9\ \@2, 18, 10\ \@5, 4\ \@5, 16, 4\ \@2, 5\ \@5, 1, 5\ \@3, 2\ \@3, \@3, 5\ \@2, 7\ \@2, \@2, 2\ \@2, 3, 5\ \@3, \@2, 3\ \@2, 5\ \@5, 8\ \@3, 5\ \@3, 4\ \@2, 4, 9\ \@3, 10\ \@2, 5\ \@3, 3\ \@5, 6\ \@3, 10\ \@3, 9\ \@3, 7, 5\ \@5, 4\ \@3, 3, 7, 2, 2, 5, 14, 7\ \@2, 16}\) (* I did not convert this to InputForm, read "\@3" as Sqrt[3], 4\ \@2 as 4*Sqrt[2] *) In[13]:= Union[%, SameTest -> r] Out[13]= \!\({1, \@2, \@3, \@5}\) The equivalence classes. In[14]:= a = 3*{Sqrt[3], Sqrt[5]} Out[14]= \!\({3\ \@3, 3\ \@5}\) In[15]:= b = Table[Sqrt[Random[Integer, {1, 5}]]Random[Integer, {1, 10}], {10}] Out[15]= \!\({6, 5\ \@5, \@3, \@3, 5\ \@3, 9\ \@5, 4\ \@5, 7, 3, 2\ \@3}\) In[16]:= Intersection[a, b] Out[16]= {} In[17]:= Intersection[a, b, SameTest -> r] Out[17]= \!\({3\ \@3, 3\ \@5}\) Although the elements of a do not occur in b, each meets another member of its equivalence class, and such is part of the result. The representatives are not "normalized" though. In[18]:= bb = Union[b, b, SameTest -> r] Out[18]= \!\({3, \@3, 4\ \@5}\) In[19]:= Intersection[a, bb, SameTest -> r] Out[19]= \!\({3\ \@3, 3\ \@5}\) Same result as above, since we still have the same classes. In[20]:= Intersection[b, b, SameTest -> r] Out[20]= \!\({3, 6, 7, \@3, \@3, 2\ \@3, 5\ \@3, 4\ \@5, 5\ \@5, 9\ \@5}\) Obviously, the SameTest doesn't change anything here. The Mathematica function "Intersection" clearly is not symmetric: In[21]:= Intersection[bb, b, SameTest -> r] Out[21]= \!\({3, \@3, 4\ \@5}\) In[22]:= Intersection[b, bb, SameTest -> r] Out[22]= \!\({3, 6, 7, \@3, \@3, 2\ \@3, 5\ \@3, 4\ \@5, 5\ \@5, 9\ \@5}\) To conclude: the SameTest function for Intersection is of only limited help implementing set operations on equivalence classes. One at least should unify the first argument to Intersection, or better reduce each expression to normal form and then use normal set operations (without SameTest). The meaning of Intersection with SameTest is given by its operational semantics. It is an asymmetrical operation, and there is no need for SameTest to be symmetric, reflexive or transitive. Just consider it as an idiom for a special - and useful - Select operation. -- Hartmut Wolf