[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [FWP] Weighted sampling



abigail@foad.org writes:

> On Mon, Mar 19, 2001 at 03:31:13PM -0500, Bernie Cosell wrote:
> > This is probably pretty trivial stuff, but I was surprised at how easy it 
> > turned out to be [and the 'surprise' counted as fun for me].
> > 
> > The problem: I have a weighted distribution that I need to sample from.  
> > I have an array of the 'weights' associated with each sample.  So I did:
> > 
> > my @dist ;
> > foreach my $i (0 .. $#weights)
> > {   push @dist, ($i) x $weights[$i] ; }
> > 
> > sub sample
> > {   return $dist[rand(@dist)] ; }
> 
> 
> That wouldn't work if @weights contains non-integers, or when the
> sum of the weights is huge.
> 
>     sub sample {
>         my ($count, $sample);
>         for (my $i  = 0; $i < @weights; $i ++) {
>             $count += $weights [$i];
>             $sample = $i if rand $count < $weights [$i];
>         }
>         $sample;
>     }
> 
> 
> This uses O (1) additional memory, and only requires @weights to contain
> non-negative numbers.
> 
> 
> 
> Abigail
> 
> ==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
> ==== Send email to <fwp-request@technofile.org> with message _body_
> ====   unsubscribe

Ah, the perils of coding straight into an email...I should know better
than that.  Stray $i in previous code.

My apologies to anyone who pushed that snippet into production. ;-)

#!/usr/bin/perl

@weights = (1,0,2);
@cweight = map { $sums += $_ } @weights;

print &sample;

sub sample {  
  $rand = rand $cweight[-1];  
  for (0..$#cweight) {    
     return $_ if $rand < $cweight[$_];  
  }
}


==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
==== Send email to <fwp-request@technofile.org> with message _body_
====   unsubscribe