1

I m having a application in which i have to select a number out of many numbers according to their weights. Every time I will select , I have send the result to flash.I have found a algorithm in python. I have implemented it in php and was testing for its results. If i was running that algo in python it was giving good results but in php not so good. Ex. (1=>30,2=>40,3=>30) After running many times , the probablity of occurence first number in weighted array is always more but in python it is uniform. I have attatched the PHP code.

define("MAX",100000);
$reelfrequencies=array(30,40,30);
echo weightedselect($reelfrequencies);
/*function weightedselect($frequency)
{ 
  $arr=cumWghtArray($frequency);//array(35,96,100);
  print_r($arr);
  $len=sizeof($frequency);
  $count=array();
  echo $r=mt_rand(0,$arr[$len-1]);
  $index=binarysearch($arr,$r,0,$len-1);
  return $index;
}*/
function cumWghtArray($arr)
{
  $cumArr=array();
  $cum=0;
  $size=sizeof($arr);
  for($i=0;$i<$size;$i++)
  {
    $cum+=$arr[$i];
    array_push($cumArr,$cum);
  }
  return $cumArr;
}

function weightedselect($frequency)
{
  $arr=cumWghtArray($frequency);//array(35,96,100);
  $len=sizeof($frequency);
  $count=array();
  $count[0]=$count[1]=$count[2]=0;
  for($i=0;$i<MAX;$i++)
  {
    $r=mt_rand(0,$arr[$len-1]);
    $index=binarysearch($arr,$r,0,$len-1);
    $count[$index]++;
  }
  for($i=0;$i<3;$i++)
  {
    $count[$i]/=MAX;
    echo $i." ".$count[$i]."\n";
  }
}
function binarySearch($ar,$value,$first,$last)
{
  if($last<$first)
    return -1;
  $mid=intVal(($first+$last)/2);
  $a=$ar[$mid];
  if($a===$value)
    return $mid;
  if($a>$value&&(($mid-1>=0&&$ar[$mid-1]<$value)||$mid==0))
    return $mid;
  else if($a>$value)
    $last=$mid-1;
  else if($a<$value)
    $first=$mid+1;
  return binarySearch($ar,$value,$first,$last);
}

Here is the Python Code. I have taken this code from this forum . import random import bisect import collections

def cdf(weights):
    total=sum(weights)
    result=[]
    cumsum=0
    for w in weights:
        cumsum+=w
        result.append(cumsum/total)
    return result

def choice(population,weights):
    assert len(population) == len(weights)
    cdf_vals=cdf(weights)
    x=random.random()
    idx=bisect.bisect(cdf_vals,x)
    return population[idx]

weights=[0.30,0.40,0.30]
population="ABC"
counts={"A":0.0,"B":0.0,"C":0.0}
max=10000
for i in range(max):
    c=choice(population,weights)
    counts[c]=counts[c]+1
print(counts)
for k, v in counts.iteritems():
    counts[k]=v/max
print(counts)

Problem is of mt_rand() function which is not uniform. The python random.rand() is very much uniform. Which random function should i implement in php with a proper seeding value every time it runs. I was thinking of using Withcmann (used by python random.random) but how will i provide the seed.

cooldude
  • 935
  • 2
  • 9
  • 18

1 Answers1

2

Both rand and mt_rand should both be more than sufficiently random for your task here. If you needed to seed mt_rand you could use mt_srand, but there's no need since PHP 4.2 as this is done for you.

I suspect the issue is with your code, which seems unnecessarily involved given what I believe you're trying to do, which is just pick a random number with weighted probabilities.

This may help: Generating random results by weight in PHP?

Community
  • 1
  • 1
Oliver Emberton
  • 951
  • 4
  • 14
  • 1
    Thanks for the reply. The link is good. I have solved my problem by using Withmann and seeding it with mt_rand(). It is now selecting the numbers with uniform probability. – cooldude May 06 '11 at 19:33