A 500 error has occurred - Executing long loop within PHP - php

A 500 error has occurred - executing long loop with PHP.
I am currently working on a scheduling system to schedule nurses on a hospital ward, I am using a genetic algorithm to carry this out.
so I randomly allocate each nurses to a shift.
and then work out how fit they are for the shift.
I then kill off any allocation which do not meet my fitness level.
I then randomly allocate a new timetable.
Assess that for fitness
kill off any allocation which do not meet my fitness level.
Merge the two timetables, keeping the fitness allocations
I loop through generating random timetable, accessing its fitness and merging the timetables
This works fine while looping through 30 - 100 times
Once I go past the 100 mark it sometimes fails - a 500 error has occurred
This always occurs when it takes over 2:30mins to complete the script
So I'm making the assumption at some point my server times out for taking too long?
I have added <?php set_time_limit(3600);
This is at the top of my file, not inside the constructor, or the class. Is it in the right place?
it still times out at 2 and a half minute,
Here is my code, the loop is the 200 loop
Still need to refractor my code so don't be too judgmental
<?php
set_time_limit(3600);
* Description of scheduler
*
* #author Dela
*/
include ("randomTtAllocation.php");
include ("fittness.php");
class scheduler {
private $randomTimetable;
private $timetable;
private $weight;
private $newTimetable ;
private $newWeight;
function __construct($labs,$students) {
echo "helloworld";
// create random timetable and print it
$r = new randomTtAllocation();
$this->randomTimetable = $r->__randomAllocation($labs, $students);
//echo "<br>" . " ............initial Time Table............." . "<br>" ;
echo "<br>";
echo "<br>";
echo "<br>";
$this->__printTt($this->randomTimetable, $this->randomTimetable);
// work out fittness for the timetable, return fit results and print
$fit = new fittness( $this->randomTimetable, $labs, $students , $r->__getNumOfSessions());
$this->newWeight = $fit->__getnewWeight();
$this->newTimetable = $fit->__getnewTimetable();;
//echo "<br>" . " ............newTimetable.........newWeight...." . "<br>" ;
//$this->__printTt($this->newTimetable, $this->newWeight );
// sort
$this->__sortTtByWeight();
$this->timetable = $this->newTimetable;
$this->weight = $this->newWeight;
for ($i = 0; $i < 200; $i++) {
// create second time table
$this->randomTimetable = $r->__randomAllocation($labs, $students);
// echo "<br>" . " ............initial Time Table............." . "<br>" ;
// $this->__printTt($this->randomTimetable, $this->randomTimetable);
// work out fittness for the timetable, return fit results and print
$fit = new fittness( $this->randomTimetable, $labs, $students , $r->__getNumOfSessions());
$this->newWeight = $fit->__getnewWeight();
$this->newTimetable = $fit->__getnewTimetable();
//echo "<br>" . " ............tempTimetable.........tempWeight...." . "<br>" ;
//$this->__printTt($this->newTimetable, $this->timetable );
$this->__sortTtByWeight();
// merge timetables
echo "<br>" . " ......old...........new." . "<br>" ;
$this->__printTt($this->timetable,$this->newTimetable );
$this->__mergeTimetables($this->newTimetable, $this->newWeight );
//echo "<br>" . " ........... mergedTimetable.........newWeight...." . "<br>" ;
//$this->__printTt($this->timetable,$this->weight );
// fittness of new timetable
$fit = new fittness( $this->timetable, $labs, $students , $r->__getNumOfSessions());
echo "<br>" . " ......merged.......kulled" . "<br>" ;
$this->__printTt($this->timetable,$fit->__getnewTimetable() );
$this->weight = $fit->__getnewWeight();
$this->timetable = $fit->__getnewTimetable();
$c[$i] = $this->__countSlotsAllocated();
echo "<br> ". $i;
}
print_r($c);
}
// sorts the re allocated time table by weight
function __sortTtByWeight() {
// for each slot
foreach($this->newTimetable as $l => $i_value) {
$size = 0;
// see how many sessions they are taking
while ($this->newTimetable[$l][$size] != "null") {
if ($this->newTimetable[$l][$size] == "0") {
break;
}
$size++;
}
for ($i = 1; $i < $size; $i++) {
$key = $this->newWeight[$l][$i];
$key1 = $this->newTimetable[$l][$i];
$k = $i - 1;
while ($k >= 0 && $this->newWeight[$l][$k] < $key) {
$this->newWeight[$l][$k + 1] = $this->newWeight[$l][$k];
$this->newTimetable[$l][$k + 1] = $this->newTimetable[$l][$k];
$k--;
}
$this->newTimetable[$l][$k + 1] = $key1;
$this->newWeight[$l][$k + 1] = $key;
}
}
}
function __countSlotsAllocated() {
$count = 0;
foreach($this->timetable as $i => $x_value) {
$j = 0;
while (($this->timetable[$i][$j] != "null") && ($this->timetable[$i][$j] != "0")){
$count++;
$j++;
}
}
echo "count " . $count;
return $count;
}
function __mergeTimetables($tempTimeTable,$tempWeight) {
// for each session
foreach($this->newTimetable as $i => $i_value) {
$j = 0;
$k = 0;
// while there are still students
while (($tempTimeTable[$i][$j] != "null") && ($tempTimeTable[$i][$j] != "0")) {
//echo $tempTimeTable[$i][$j];
// System.out.println(timeTable[i][k]);
// see if there is a free gap
while ($this->timetable[$i][$k] != "null") {
// if student is already taking that session
if ($tempTimeTable[$i][$j] == $this->timetable[$i][$k]) {
break;
}
if ($this->timetable[$i][$k] == "0") {
$this->timetable[$i][$k] = $tempTimeTable[$i][$j];
$this->weight[$i][$k] = $tempWeight[$i][$j];
break;
}
$k++;
}
if ($this->timetable[$i][$k] == "null") {
if ($tempWeight[$i][$j] < $this->weight[$i][0]) {
$this->timetable[$i][0] = $tempTimeTable[$i][$j];
$this->weight[$i][0] = $tempWeight[$i][$j];
}
}
$j++;
}
}
}
function __returnTimetable() {
return $this->timetable;
}
function __printTt($timetable, $weight) {
foreach($timetable as $x => $x_value) {
for ($i = 0; $i < 5; $i++) {
echo $timetable[$x][$i] . " ";
}
echo " . . . . .";
for ($i = 0; $i < 5; $i++) {
echo $weight[$x][$i] . " ";
}
echo "<br>";
}
}
}

Normally you shouldn't do all this work within the http request. Instead you should start a background task and have the web page show progress on the job.
The php configuration has a time limit per request which you can adjust, but it's not expected by users to take so long.

Related

PHP - Finding consecutive values in multidimensional associative arrays for seat reservation program

I'm working on a program to reserve seats for a show. I have a multidimensional array that is created using $row and $column variables. After making a few initial reservations, I need to pass integers into a function/some code to make further reservations.
I've tried looping through the array to find consecutive available seats (value "avail") but it ignores reserved seats or skips over them. I'll need to later use manhattan distance to reserve the best seats (from row 1, seat 6) first.
function to create the array:
//function to create seating chart data structure
function createChart($row, $column){
//create array for row values
$row_chart = array();
for($r=0; $r < $row; $r++){
$row_number = $r + 1;
$row_chart[$row_number] = array(); // array of cells for row $r
}
//create array for column values
$column_chart = array();
for($c=0; $c < $column; $c++){
$column_number = $c + 1;
//$location = $c_num;
$status = "avail";
foreach($row_chart as $key => $value){
$column_chart[$column_number] = $status; //add arrays of "seats" for each row
}
}
//nest the column array into the row array
foreach($row_chart as $key => $value){
foreach($column_chart as $k => $v){
$seating_chart[$key][$k] = $status;
}
}
//$seating_chart = array_combine($row_chart, $column_chart);
return $seating_chart;
}
function to make initial reservations:
$initial_reservation = "R1C4 R1C6 R2C3 R2C7 R3C9 R3C10";
$initial_reservation = explode(" ", $initial_reservation);
echo "<br> <br>";
print_r($initial_reservation);
$initial_res_length = count($initial_reservation);
echo "<br> <br>";
//echo $initial_res_length;
//split each seat up into integers to mark it reserved in the array
//issue for flexibility: find way to break up string by letters and numbers for larger charts
for($a = 0; $a < $initial_res_length; $a++){
$reso_row = substr($initial_reservation[$a], 1, 1);
//echo $reso_row . "<br>";
$reso_column = substr($initial_reservation[$a], 3, 2);
//echo $reso_column . "<br>";
$working_chart[$reso_row][$reso_column] = "reserved";
}
//echo "<br> <br>";
//echo "<pre>" . print_r($working_chart, 1) . "</pre>";
what I have so far in attempt to make further reservations:
//write some code to find consecutive seats
$seats_needed = 4;
$outer_array_length = count($working_chart);
//echo $outer_array_length;
for($d = 1; $d < $outer_array_length + 1; $d++){
for($e = 1; $e < $seats_needed + 1; $e++){
//issue: run through $seats_needed amount of times and executes the code block
//needed: check if $seats_needed amount of seats in available first then run reservation code
if($working_chart[$d][$e] === "avail"){
$working_chart[$d][$e] = "new reservation";
}
else{
echo "Sorry, not possible.";
}
}
break;
}
echo "<br> <br>";
echo "<pre>" . print_r($working_chart, 1) . "</pre>";
I'd like to be able to find a number of available seats ($seats_needed) first, and then loop through to reserve them.
I have initialized the $working_chart with :
$working_chart = createChart(10, 11);
I have written the attempt to make further reservations :
foreach(array_keys($working_chart) as $d ){
$maxColumn = count($working_chart[$d]) - $seats_needed + 1;
for($e = 1; $e <= $maxColumn ; $e++){
if(["avail"] === array_unique(array_slice($working_chart[$d], $e - 1 , $seats_needed))){
$working_chart[$d] = array_replace($working_chart[$d], array_fill($e, $seats_needed, "new reservation"));
break 2;
}
else{
echo "Sorry, not possible.";
}
}
}
I hope it can help you...

How to find multiple points within a polygon

I am using the following code to test if a point is in a polygon, however I would like to make it work for multipliable points, but when I run it though a loop it fails to run correctly.
Polygon array = (52.62806176021313, 1.0546875),(52.435920583590125, 0.82672119140625),(52.26479561297205, 0.78277587890625),(52.24966453484505, 1.0986328125),(52.37224556866933, 1.34857177734375),(52.63973017532399, 1.46392822265625),(52.73795463681313, 1.25518798828125)
I split it up before hand.
Without Loop
$Latx = 52.5; //Y Point to test if inside
$LonX = 1.1; //X Point to test if inside
$VTX = $LON; //X array of polygon
$VTY = $LAT; //Y array of polygon
$POINTS = count($VTX) - 1; //number of polygon sides
//=====================================================
if (is_in_polygon($POINTS, $VTX, $VTY, $LonX, $LatY)){
echo "Is in polygon ($LatY,$LonX)";
echo "<br>";
}
else {
echo "Is not in polygon ($LatY,$LonX)";
}
echo "<br>"
function is_in_polygon($POINTS, $VTX, $VTY, $LonX, $LatY)
{
$i = $j = $c = 0;
for ($i = 0, $j = $POINTS ; $i < $POINTS; $j = $i++) {
if ((($VTY[$i] > $LatY != ($VTY[$j] > $LatY)) &&
($LonX < ($VTX[$j] - $VTX[$i]) * ($LatY - $VTY[$i]) /
($VTY[$j] - $VTY[$i]) + $VTX[$i]) ) )
$c = !$c;
}
return $c;
}
Trying with a Loop
for ($x=0; $x<=1000; $x++) {
$QU="SELECT lat,lon FROM DBTable LIMIT $x,1";
$RT=mysql_query($QU,$db);
if (!$RT) {
die("Invalid query: " . mysql_error());
}
while ($row = mysql_fetch_assoc($RT)){
$LonX[$x]=$row["lat"];
$LatY[$x]=$row["lon"];
if (is_in_polygon($POINTS, $VTX, $VTY, $LonX[$x], $LatY{$x])){
echo "Is in polygon ($LatY[$x],$LonX[$x])";
echo "<br>";
}
else echo "Is not in polygon ($LatY[$x],$LonX[$x])";
echo "<br>"
}
}

Fetching Data from XML through PHP

I have a huge amount of data in an XML file, however while fetching the data through my PHP code, the webpage goes into processing and then hangs. There are more than 17,000 records in the XML (the data related to a city name). I have received a few suggestions that I should filter the data by state, but am unable to implement that suggestion.
<?php
$q = $_GET["q"];
$xmlDoc = new DOMDocument();
$xmlDoc->load('http://aayam.co/wp-content/themes/squirreltheme/ifsc/cd_catalog.xml');
$x = $xmlDoc->getElementsByTagName('CITY');
for ($i = 0; $i <= $x->length - 1; $i++) {
// Process only element nodes
if ($x->item($i)->nodeType == 1) {
if ($x->item($i)->childNodes->item(0)->nodeValue == $q) {
$y = ($x->item($i)->parentNode);
}
}
}
$cd = ($y->childNodes);
for ($i = 0; $i < $cd->length; $i++) {
// Process only element nodes
if ($cd->item($i)->nodeType == 1) {
echo "<b style='color:green;'>" . $cd->item($i)->nodeName . ":</b> ";
echo "<div style='color:green;'>" . $cd->item($i)->childNodes->item(0)->nodeValue . " </div>";
echo "<br>";
}
}

How to reliably find similar strings to that typed in

I have an interface where a user will enter the name of a company. It then compares what they typed to current entries in the database, and if something similar is found it presents them with options (in case they misspelled) or they can click a button which confirms what they typed is definitely new and unique.
The problem I am having is that it is not very accurate and often brings up dozens of "similar" matches that aren't that similar at all!
Here is what I have now, the first large function I didn't make and I am not clear on what exactly it does. Is there are much simpler way to acheive what I want?
// Compares strings and determines how similar they are based on a nth letter split comparison.
function cmp_by_optionNumber($b, $a) {
if ($a["score"] == $b["score"]) return 0;
if ($a["score"] > $b["score"]) return 1;
return -1;
}
function string_compare($str_a, $str_b)
{
$length = strlen($str_a);
$length_b = strlen($str_b);
$i = 0;
$segmentcount = 0;
$segmentsinfo = array();
$segment = '';
while ($i < $length)
{
$char = substr($str_a, $i, 1);
if (strpos($str_b, $char) !== FALSE)
{
$segment = $segment.$char;
if (strpos($str_b, $segment) !== FALSE)
{
$segmentpos_a = $i - strlen($segment) + 1;
$segmentpos_b = strpos($str_b, $segment);
$positiondiff = abs($segmentpos_a - $segmentpos_b);
$posfactor = ($length - $positiondiff) / $length_b; // <-- ?
$lengthfactor = strlen($segment)/$length;
$segmentsinfo[$segmentcount] = array( 'segment' => $segment, 'score' => ($posfactor * $lengthfactor));
}
else
{
$segment = '';
$i--;
$segmentcount++;
}
}
else
{
$segment = '';
$segmentcount++;
}
$i++;
}
// PHP 5.3 lambda in array_map
$totalscore = array_sum(array_map(function($v) { return $v['score']; }, $segmentsinfo));
return $totalscore;
}
$q = $_POST['stringA'] ;
$qLengthMin = strlen($q) - 5 ; // Part of search calibration. Smaller number = stricter.
$qLengthMax = strlen($q) + 2 ; // not in use.
$main = array() ;
include("pdoconnect.php") ;
$result = $dbh->query("SELECT id, name FROM entity_details WHERE
name LIKE '{$q[0]}%'
AND CHAR_LENGTH(name) >= '$qLengthMin'
#LIMIT 50") ; // The first letter MUST be correct. This assumption makes checker faster and reduces irrelivant results.
$x = 0 ;
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
$percent = string_compare(strtolower($q), strtolower(rawurldecode($row['name']))) ;
if($percent == 1) {
//echo 1 ;// 1 signifies an exact match on a company already in our DB.
echo $row['id'] ;
exit() ;
}
elseif($percent >= 0.6) { // Part of search calibration. Higher deci number = stricter.
$x++ ;
$main[$x]['name'] = rawurldecode($row['name']) ;
$main[$x]['score'] = round($percent, 2) * 100;
//array_push($overs, urldecode($row['name']) . " ($percent)<br />") ;
}
}
usort($main, "cmp_by_optionNumber") ;
$z = 0 ;
echo '<div style="overflow-y:scroll;height:175px;width:460px;">' ;
foreach($main as $c) {
if($c['score'] > 100) $c['score'] = 100 ;
if(count($main) > 1) {
echo '<div id="anysuggested' . $z . '" class="hoverdiv" onclick="selectAuto(' . "'score$z'" . ');">' ;
}
else echo '<div id="anysuggested' . $z . '" class="hoverdiv" style="color:#009444;" onclick="selectAuto(' . "'score$z'" . ');">' ;
echo '<span id="autoscore' . $z . '">' . $c['name'] . '</span></div>' ;
$z++ ;
}
echo '</div>' ;
Comparing strings is a huge topic and there are many ways to do it. One very common algorithm is called the Levenshtein difference. This is a native implementation in PHP but none in MySQL. There is however an implementation here that you could use.
You need aproximate/fuzzy string matching.
Read more about
http://php.net/manual/en/function.levenshtein.php, http://www.slideshare.net/kyleburton/fuzzy-string-matching
The best way would be to use some index based search engine like SOLR http://lucene.apache.org/solr/.

PHP equation from JavaScript

I have this JavaScript equation which I'm now trying to transform to PHP.
JavaScript:
LVL=new Array();
LVL[1]=128;
LVL[0]=128;
m=.05;
for (i=1;i<101;i++) {
if (i>1) {
LVL[i]=Math.floor(LVL[i-1]+(LVL[i-1]*m));
m=m+.0015;
}
}
then it's a bunch of document.writes of a table and a for loop.
Here's what I have so far (which is NOT working):
<?php
$n = 1; // level
$m = .05; // exp modifier
$exp = floor($n*1+($n-1)*$m);
echo "Level " . $n . ", exp needed: " . $exp; // 128 exp
?>
The PHP output is: Level 1, exp needed: 1 and that's WRONG.
It SHOULD say: Level 1, exp needed: 128
What am I doing wrong?
A direct transcription:
$LVL = array();
$LVL[1] = 128;
$LVL[0] = 128;
$m = .05;
for ($i = 1; $i < 101; $i++)
{
if ($i > 1)
{
$LVL[$i] = floor($LVL[$i-1] + $LVL[$i-1]*$m);
$m = $m + .0015
}
}
You need to build the array as its built bottom-up
You do a couple of errors:
you use the index (the level) as it is the amount of the experience points needed to
reach the level.
you forgot the for (if you are testing the formula it is ok)
the code so far:
$lvl = array(128,128);
$modifier=.05;
for ($i=1;$i<101;i++) {
$lvl[$i]=floor($lvl[$i-1]*(1+$modifier));
$modifier+=0.0015;
}
foreach ($lvl as $level=>$points) {
echo "Level " . $level . ", exp needed: " . $points ."\n<br />"; // 128 exp
}

Categories