RE: Re: "misbehaving" Union function
- To: mathgroup at smc.vnet.net
- Subject: [mg24124] RE: [mg24096] Re: [mg24075] "misbehaving" Union function
- From: Wolf Hartmut <hwolf at debis.com>
- Date: Wed, 28 Jun 2000 02:11:44 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
a note below > -----Original Message----- > From: Andrzej Kozlowski [SMTP:andrzej at tuins.ac.jp] To: mathgroup at smc.vnet.net > Sent: Tuesday, June 27, 2000 6:52 AM > To: mathgroup at smc.vnet.net > Subject: [mg24096] Re: [mg24075] "misbehaving" Union function > > I have to send a correction to this posting. What I wrote was correct, and > the solution given works, but the reason for the problem was not correctly > identified. I looked at your example carefully and now I can see that when > union is applied with the default setting the two elements that look the > same are indeed sorted so as to be adjacent to each other. The problem is, > however, that that are close enough tobe considered Equal but not to be > considered SameQ. (You can see that by applying FullForm to your original > answer). That's why the setting SameTest->Equal will remove the apparent > duplicates while SameTest->Automatic (default) and SameTest->SameQ will > not. > > Andrzej > on 00.6.23 11:04 PM, Andrzej Kozlowski at andrzej at tuins.ac.jp wrote: > > > The explanation is as follows. Union admits one option: SameTest. This > comes > > with the default setting of Automatic. With this default setting the > > elements of the list to which Union is being applied are first sorted in > > canonical order and then only the adjacent elements are compared. This > has > > the advantage of speed. However, when working with approximate numbers, > two > > numbers (or list of numbers in your case) which are close enough to be > > considered equal may not end up as being adjacent after sorting. When > that > > happens both may be kept. So the solution is to use an explicit setting > for > > SameTest: SameTest->Equal. If you use Union[...,SameTest->Equal] instead > of > > Union[...] in your example you will get the output: > > > > Out[26]= > > {{0, 0.}, {6, 2.}, {14, 6.}, {15, 7.}, {25, 11.}, {26, 12.}} > > > > Andrzej Kozlowski > > > > > > -- > > Andrzej Kozlowski > > Toyama International University, JAPAN > > > > For Mathematica related links and resources try: > > <http://www.sstreams.com/Mathematica/> > > > > > > > > on 6/23/00 3:26 PM, Felix Farkas at farkas at ica.epfl.ch wrote: > > > >> Hi, > >> i am trying to build up a list of points. The input is, > >> a list of events. I use the Union function in order to > >> avoid duplicate points. however i do not have the expected result. > >> i really don't know where the error is coming from. > >> Could somebody, please, tell me where is the fault? > >> I would greatly appreciate any suggestions. > >> > >> Many thanks in advance. > >> Regards, > >> Felix > >> > >> Here is the function: > >> > >> In[1]:= Genpoints[events_] := > >> Module[ > >> {ev = events, rate, > >> duration, time, burst, bytes = 0, points = {}}, > >> rate := ee[[3]]; > >> duration := ee[[2]]; > >> time := ee[[1]]; > >> burst := ee[[4]]; > >> While[Length[ev] != 0, > >> ee = First[ev]; > >> ev = Rest[ev]; > >> points = Union[points, > >> If[rate == -1, > >> (*then*) > >> bytes += burst; {{time, > >> bytes - burst}, {time, bytes}}, > >> (*else*) > >> bytes += rate*duration; > >> Print[{{time, bytes - rate*duration}, {time + duration, > >> bytes}}]; > >> {{time, bytes - > >> rate*duration}, {time + duration, bytes}}] > >> ] > >> ]; > >> points > >> ] > >> > >> The output generated is: > >> > >> In[2]:= aa = {{0, 6, 0.3333333, 2, 2, 1}, > >> {6, 8, 0.5, 4, 2, 1}, {14, 1, 1, 1, 2, 1}, > >> {15, 10, 0.4, 4, 2, 1}, {25, 1, 1, 1, 2, 1}}; > >> In[3]:= po2 = Genpoints[aa] > >> Out[3]= {{0, 0.}, {6, 2.}, {6, 2.}, {14, 6.}, > >> {15, 7.}, {25, 11.}, {26, 12.}} > >> > >> > >> > >> > -------------------------------------------------------------------------- > --- > >> Felix Farkas > >> EPFL-DSC-ICA > >> IN-Ecublens > >> CH-1015 Lausanne > >> Switzerland > >> > >> tel: 0041 21 693 6601 > >> fax: 0041 21 693 6610 > >> email: felix.farkas at epfl.ch > >> > >> > >> > > > > -- > Andrzej Kozlowski > Toyama International University > JAPAN > > http://platon.c.u-tokyo.ac.jp/andrzej/ > http://sigma.tuins.ac.jp/ > [Wolf Hartmut] Dear Felix, Andrzej's explanation is correct, I just want to show how you would have avoided the problems in first place. Essentially this is because after bytes += rate*duration; bytes - rate*duration you don't get the old value for bytes, since the numerics isn't accurate. You just have to avoid this operation of "looking back". For a short fix, you can accumulate bytes only where it is needed, so Genpoints2[events_] := Module[{ev = events, rate, duration, time, burst, bytes = 0, points = {}}, rate := ee[[3]]; duration := ee[[2]]; time := ee[[1]]; burst := ee[[4]]; While[Length[ev] != 0, ee = First[ev]; ev = Rest[ev]; points = Union[points, If[rate == -1,(*then*) {{time, bytes}, {time, bytes += burst}}, (*else*) Print[{{time, bytes}, {time + duration, bytes + rate*duration}}]; {{time, bytes}, {time + duration, bytes += rate*duration}}]]]; points] will not disturb you. However this programm makes very inefficient use of Union, furthermore you make multiple access to the components of the event, so I might propose you an alternative Genpoints3[events_] := Union @@ Block[{time, duration, rate, burst, scrap1, scrap2, bytes = 0}, Function[ee, {time, duration, rate, burst, scrap1, scrap2} = ee; If[rate == -1,(*then*) {{time, bytes}, {time, bytes += burst}}, (*else*) Print[{{time, bytes}, {time + duration, bytes + rate*duration}}]; {{time, bytes}, {time + duration, bytes += rate*duration}}]] /@ events] Kind regards, Hartmut