Search code examples
phpalgorithmmathphp4

PHP Weight Algorithm


I'm wondering if this is a sufficient algorithm for finding the best value with a weighted system. Is there anything I could add to make it better?

in this example I would like the probability of $object->get() returning test4 to be 4 times greater than the probability of it returning test1.

class weightCalculator { 
    var $data = array();
    var $universe = 0; 

    function add( $data, $probability ){ 
        $this->data[ $x = sizeof( $this->data ) ] = new stdClass; 
        $this->data[ $x ]->value = $data; 
        $this->universe += $this->data[ $x ]->probability = abs( $probability ); 
    } 

    function get(){ 
        if( !$this->universe ){
            return null; 
        }
        $x = round( mt_rand( 0, $this->universe ) ); 
        $max = 0;
        $i = 0; 

        while( $x > $max ){
            $max += $this->data[ $i++ ]->probability;
        }
        $val=-1;
        if($this->universe==1){
            $val = $this->data[$i]->value;      
          } else {
            $val = $this->data[$i-1]->value;                
        }
        return $val;
    } 
}

$object = new weightCalculator; 
$object->add( 'test1', 10 );
$object->add( 'test2', 20 ); 
$object->add( 'test3', 30 ); 
$object->add( 'test4', 40 ); 

Solution

  • To elaborate on streetpc's answer; alongside your data array, use add() to maintain a same-sized keys array where you store the upper bound on your range; for your example, that array would look like {10, 30, 60, 100}. (Or, use one array containing objects or structs that contain both the data and the key.) Then, your get() method is simply searching a sorted list for the first element greater than $x; a binary search could do that in O(ln N), compared to O(N) for your method. You'll chew up a little extra memory -- but for most applications, it looks like a good tradeoff.