2011-05-06 7 views
1

Je possède une application dans laquelle je dois sélectionner un nombre parmi plusieurs nombres en fonction de leur poids. Chaque fois que je vais sélectionner, j'ai envoyé le résultat au flash. J'ai trouvé un algorithme en python. Je l'ai implémenté en php et testais ses résultats. Si je courais cet algo en python il donnait de bons résultats mais en php pas si bon. Ex. (1 => 30,2 => 40,3 => 30) Après avoir couru plusieurs fois, le probability of occurence premier nombre dans le tableau pondéré est toujours plus mais en python il est uniforme. J'ai attatched le code PHP.Séquencement du nombre aléatoire Générateur En PHP

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); 
} 

Voici le code Python. J'ai pris ce code sur ce forum. importation au hasard importation BiSect collections d'importation

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) 

problème est de mt_rand() qui ne soit pas uniforme. Le python random.rand() est très uniforme. Quelle fonction aléatoire devrais-je implémenter en php avec une valeur d'ensemencement appropriée à chaque fois qu'elle fonctionne? Je pensais utiliser Withcmann (utilisé par python random.random) mais comment vais-je fournir la graine.

Répondre

2

Les deux rand et mt_rand doivent tous les deux être plus qu'aléatoires pour votre tâche ici. Si vous aviez besoin de graine mt_rand, vous pouvez utiliser mt_srand, mais ce n'est pas nécessaire puisque PHP 4.2 est fait pour vous.

Je soupçonne que le problème provient de votre code, ce qui semble inutilement impliqué compte tenu de ce que je crois que vous essayez de faire, qui consiste simplement à choisir un nombre aléatoire avec des probabilités pondérées.

Cela peut aider: Generating random results by weight in PHP?

+1

Merci pour la réponse. Le lien est bon. J'ai résolu mon problème en utilisant Withmann et en l'ensemençant avec mt_rand(). Il sélectionne maintenant les nombres avec une probabilité uniforme. – cooldude

+0

Heureux d'avoir aidé! –