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