13) ) continue; else { $bOperator = false; $buffer[$cBuff++] = $this_gene; continue; } } //find a gene which represents a number else { if ($this_gene > 9) continue; else { $bOperator = true; $buffer[$cBuff++] = $this_gene; continue; } } }//next gene // now we have to run through buffer to see if a possible divide by zero // is included and delete it. (ie a '/' followed by a '0'). We take an easy // way out here and just change the '/' to a '+'. This will not effect the // evolution of the solution for ($i=0; $i < $cBuff; $i++) { if (($buffer[$i] == 13) && ($buffer[$i + 1] == 0)) $buffer[$i] = 10; } return $cBuff; } function AssignFitness($bits, $target_value) { //holds decimal values of gene sequence $buffer = array((int)(CHROMO_LENGTH / GENE_LENGTH)); $num_elements = ParseBits($bits, $buffer); // ok, we have a buffer filled with valid values of: operator - number - operator - number.. // now we calculate what this represents. $result = 0.0; for ($i=0; $i < $num_elements-1; $i+=2) { switch ($buffer[$i]) { case 10: $result += $buffer[$i + 1]; break; case 11: $result -= $buffer[$i + 1]; break; case 12: $result *= $buffer[$i + 1]; break; case 13: $result /= $buffer[$i + 1]; break; }//end switch } // Now we calculate the fitness. First check to see if a solution has been found // and assign an arbitarily high fitness score if this is so. if ($result == (float)$target_value) return 999.0; else return 1/(float)abs((double)($target_value - $result)); // return result; } // chromosome Class class chromo { var $bits; var $fitness; function chromo($start_bits = "", $start_fitness = 0.0) { $this->bits = $start_bits; $this->fitness = $start_fitness; } function GetRandomBits() { // clear the bits $this->bits = ""; for($i = 0; $i < CHROMO_LENGTH; $i++) { $r = rand(0, RAND_MAX) / (RAND_MAX + 1); //echo $r."
"; if($r > 0.5) $this->bits .= "1"; else $this->bits .= "0"; } } function ToDec($start = 0, $stop = 0) { $val = 0; $value_to_add = 1; // convert the whole string if($start == $stop) { for ($i = strlen($this->bits); $i > 0; $i--) { if ($this->bits[($i - 1)] == '1') $val += $value_to_add; $value_to_add *= 2; } } else { $str = substr($this->bits, $start, $stop); for ($i = strlen($str); $i > 0; $i--) { if ($str[($i - 1)] == '1') $val += $value_to_add; $value_to_add *= 2; } } return $val; } function PrintChromo() { //holds decimal values of gene sequence $buffer = array((int)(CHROMO_LENGTH / GENE_LENGTH)); //parse the bit string $num_elements = ParseBits($this->bits, &$buffer); for ($i=0; $i < $num_elements; $i++) { PrintGeneSymbol($buffer[$i]); } return; } } // end class chromo function Mutate($bits = "") { for ($i=0; $i < strlen($bits); $i++) { if ((rand(0, RAND_MAX) / (RAND_MAX + 1)) < MUTATION_RATE) { if ($bits[$i] == '1') $bits[$i] = '0'; else $bits[$i] = '1'; } } return; } function Crossover(&$offspring1, &$offspring2) { //dependent on the crossover rate if ((rand(0, RAND_MAX) / (RAND_MAX + 1)) < CROSSOVER_RATE) { //create a random crossover point $crossover = (int) ((rand(0, RAND_MAX) / (RAND_MAX + 1)) * CHROMO_LENGTH); $t1 = substr($offspring1, 0, $crossover) . substr($offspring2, $crossover, CHROMO_LENGTH); $t2 = substr($offspring2, 0, $crossover) . substr($offspring1, $crossover, CHROMO_LENGTH); $offspring1 = $t1; $offspring2 = $t2; } } function Roulette($total_fitness, &$Population) { //generate a random number between 0 & total fitness count $Slice = (float)((rand(0, RAND_MAX) / (RAND_MAX + 1)) * $total_fitness); //go through the chromosones adding up the fitness so far $FitnessSoFar = 0.0; for ($i = 0; $i < POP_SIZE; $i++) { $FitnessSoFar += $Population[$i]->fitness; //if the fitness so far > random number return the chromo at this point if ($FitnessSoFar >= $Slice) return $Population[$i]->bits; } return ""; } function BinToDec($bits) { $val = 0; $value_to_add = 1; for ($i = strlen($bits); $i > 0; $i--) { if ($bits[($i - 1)] == '1') $val += $value_to_add; $value_to_add *= 2; } return $val; } function PrintGeneSymbol($val) { if ($val < 10 ) echo $val." "; else { switch ($val) { case 10: "+"; break; case 11: echo "-"; break; case 12: echo "*"; break; case 13: echo "/"; break; }//end switch echo " "; } return; } $Population = array(POP_SIZE); for ($i=0; $iGetRandomBits(); $Population[$i]->fitness = 0.0; } $GenerationsRequiredToFindASolution = 0; $bFound = false; while(!$bFound) { $TotalFitness = 0.0; for($i=0; $ifitness = AssignFitness($Population[$i]->bits, $Target); $TotalFitness += $Population[$i]->fitness; } // check to see if we have found any solutions (fitness will be 999) for ($i=0; $ifitness == 999.0) { echo "Solution found in ".$GenerationsRequiredToFindASolution." generations!
"; $Population[$i]->PrintChromo(); $bFound = true; break; } } $temp = array(POP_SIZE); for ($i=0; $iGetRandomBits(); $temp[$i]->fitness = 0.0; } $cPop = 0; //loop until we have created POP_SIZE new chromosomes while ($cPop < POP_SIZE) { // we are going to create the new population by grabbing members of the old population // two at a time via roulette wheel selection. $offspring1 = Roulette($TotalFitness, $Population); $offspring2 = Roulette($TotalFitness, $Population); //add crossover dependent on the crossover rate Crossover($offspring1, $offspring2); //now mutate dependent on the mutation rate Mutate($offspring1); Mutate($offspring2); //add these offspring to the new population. (assigning zero as their //fitness scores) $temp[$cPop++] = new chromo($offspring1, 0.0); $temp[$cPop++] = new chromo($offspring2, 0.0); }//end loop for ($i=0; $i MAX_ALLOWABLE_GENERATIONS) { echo "No solutions found this run!"; $bFound = true; } } ?>