Commit all of daves changes to the annealer - it is DEFINITELY NOT COMPLETE YET! DO NOT ATTEMPT TO USE IT YET! EXCEPT OF COURSE FOR TESTING PURPOSES :)

This commit is contained in:
james 2006-01-16 04:58:43 +00:00
parent d763cd1636
commit 3bccb5d163

View File

@ -28,6 +28,7 @@
function TRACE()
{
}
//function TRACE($str) { print($str); }
function TRACE_R()
{
}
@ -57,11 +58,11 @@ function pick_random_move(&$team)
}
TRACE("Random move: ($t1,$j1) ($t2,$j2)<br>");
TRACE("Random move: ($t1,$j1) ($t2,$j2)\n");
TRACE_R($team[$t1]['judges']);
TRACE("<br>T2:");
TRACE("T2:\n");
TRACE_R($team[$t2]['judges']);
TRACE("<br>");
TRACE("\n");
/* The move is team1,judge1 <==> team2,judge2 */
return array($t1, $j1, $t2, $j2);
}
@ -95,7 +96,7 @@ function compute_team_cost(&$teams, &$judges, $team_id)
$cost += $min * 20;
$cost += $max * 10;
// TRACE("Under min=$min, over max=$max<br>");
// TRACE("Under min=$min, over max=$max\n");
/* For each judge on the team, score their preferences */
reset($t['judges']);
@ -107,13 +108,13 @@ function compute_team_cost(&$teams, &$judges, $team_id)
$dpref = $j['divprefs'][$t['division']];
$cpref = $j['catprefs'][$t['category']];
// TRACE("Judge $judge_id cp=$cpref, dp=$dpref<br>");
// TRACE("Judge $judge_id cp=$cpref, dp=$dpref\n");
$cost += 2 * (-$dpref + 2);
$cost += 2 * (-$cpref + 2);
}
TRACE("Team $team_id, cost is $cost<br>");
TRACE("Team $team_id, cost is $cost\n");
return $cost;
}
@ -179,9 +180,9 @@ function compute_delta_cost(&$teams, &$judges, $move)
$c2 = compute_team_cost($teams, $judges, $tid2);
$cost += $c1 + $c2;
TRACE("Team $tid1 cost {$t1['cost']} -> $c1<br>");
TRACE("Team $tid2 cost {$t2['cost']} -> $c2<br>");
TRACE("Delta = $cost<br>");
TRACE("Team $tid1 cost {$t1['cost']} -> $c1\n");
TRACE("Team $tid2 cost {$t2['cost']} -> $c2\n");
TRACE("Delta = $cost\n");
$t1['judges'] = $ja1;
$t2['judges'] = $ja2;
@ -206,9 +207,9 @@ function record_move(&$teams, $move, $movedata)
TRACE("T1:");
TRACE_R($t1['judges']);
TRACE("<br>T2:");
TRACE("\nT2:");
TRACE_R($t2['judges']);
TRACE("<br>");
TRACE("\n");
// TRACE_R($t1);
// TRACE_R($t2);
@ -223,30 +224,15 @@ function record_move(&$teams, $move, $movedata)
*
* - judges
*/
function judges_assign_anneal($divisions, $categories, $judges, $data)
function judges_assign_anneal($divisions, $categories, $languages, $judges, &$team, $data)
{
/* Create an array to hold the team data */
$team = array();
$t=0;
reset($data['teams']);
while( list($div, $c) = each($data['teams']) ){
reset($c);
while( list($cat, $num) = each($c) ) {
for($x=0; $x<$num; $x++) {
$team[$t]['division'] = $div;
$team[$t]['category'] = $cat;
$team[$t]['min'] = $data['min_judges_per_team'];
$team[$t]['max'] = $data['max_judges_per_team'];
$team[$t]['judges'] = array();
$t++;
}
}
}
$num_teams = $t;
$num_teams = count($team);
$x=0;
TRACE("Input: $num_teams juding teams \n");
if($num_teams <= 0) return;
/* Inital assignment of judges to teams */
reset($judges);
while( list($j, $ji) = each($judges)) {
@ -257,7 +243,7 @@ function judges_assign_anneal($divisions, $categories, $judges, $data)
/* Compute inital costs */
$current_cost = 0;
// reset($team);
for($x=0; $x<count($team); $x++) {
for($x=0; $x<$num_teams; $x++) {
$t =& $team[$x];
$t['cost'] = compute_team_cost($team, $judges, $x);
$current_cost += $t['cost'];
@ -268,7 +254,7 @@ function judges_assign_anneal($divisions, $categories, $judges, $data)
/* Anneal */
$temperature = 25.0;
while(1) {
$moves = 1000;
$moves = 500;
for($m = 0; $m<$moves; $m++) {
/* Pick 2 moves at random */
$move = pick_random_move($team);
@ -280,7 +266,7 @@ function judges_assign_anneal($divisions, $categories, $judges, $data)
$r = floatval(rand()) / floatval(getrandmax());
/* Decide if we want to keep it */
$e = exp(-$delta_c / $temperature);
TRACE("r=$r, exp=$e<br>");
TRACE("r=$r, exp=$e\n");
if($r < exp(-$delta_c / $temperature)) {
/* Yes, we do, record the move */
record_move($team, $move, $movedata);
@ -288,21 +274,18 @@ function judges_assign_anneal($divisions, $categories, $judges, $data)
$n_accepted++;
if($current_cost < $best_cost)
$best_cost = $current_cost;
TRACE("Move accepted, cost=$current_cost<br>");
TRACE("Move accepted, cost=$current_cost\n");
} else {
TRACE("Move rejected<br>");
TRACE("Move rejected\n");
}
}
TRACE("Cost is $current_cost<br>");
TRACE("Cost is $current_cost\n");
$temperature *= 0.9;
if($temperature <= 0.05) break;
}
return $team;
}
@ -314,6 +297,11 @@ $q=mysql_query("SELECT * FROM projectcategories WHERE year='".$config['FAIRYEAR'
while($r=mysql_fetch_object($q))
$cat[$r->id]=$r->category;
$langr = array();
$q=mysql_query("SELECT * FROM languages WHERE active='Y'");
while($r=mysql_fetch_object($q))
$langr[] = $r->lang;
$configq=mysql_query("SELECT * FROM judges_schedulerconfig WHERE year='".$config['FAIRYEAR']."'");
$data=array();
@ -321,39 +309,145 @@ while($configr=mysql_fetch_object($configq))
$data[$configr->var]=$configr->val;
$data['teams'] = array();
$data['projects'] = array();
$jdivisions = array();
/* Load a list of all projects, and build an array of projects in each
* category */
// print_r($langr);
$q=mysql_query("SELECT * FROM projects WHERE year='".$config['FAIRYEAR']."'");
while($r=mysql_fetch_object($q)) {
$d_id = $r->projectdivisions_id;
$c_id = $r->projectcategories_id;
$l_id = $r->language;
$data['projects'][$r->id]['timetable'] = array();
if(!in_array($l_id, $langr)) $l_id = 'en';
$jdivisions[$d_id][$c_id][$l_id][] = $r->id;
TRACE("Found project id {$r->id} in $d_id, $c_id, $l_id\n\n");
}
$t=0;
$max_ts = 0;
foreach($div AS $d_id=>$d_val)
{
foreach($cat AS $c_id=>$c_val)
{
$numq=mysql_query("SELECT COUNT(id) AS num FROM projects WHERE projectcategories_id='$c_id' AND projectdivisions_id='$d_id'");
$numr=mysql_fetch_object($numq);
$numteams=ceil($numr->num/$data['max_projects_per_team']*$data['num_times_judged']);
$data['teams'][$d_id][$c_id]=$numteams;
foreach($langr AS $l_id) {
$num = count($jdivisions[$d_id][$c_id][$l_id]);
if($num <= 0) continue;
$numteams=ceil($num/$data['max_projects_per_team']*$data['num_times_judged']);
if($numteams < $data['num_times_judged'])
$numteams = $data['num_times_judged'];
TRACE("Judging teams for $d_id, $c_id, $l_id is $numteams\n\n");
$start_t = $t;
for($x=0; $x<$numteams; $x++) {
$team[$t]['division'] = $d_id;
$team[$t]['category'] = $c_id;
$team[$t]['language'] = $l_id;
$team[$t]['min'] = $data['min_judges_per_team'];
$team[$t]['max'] = $data['max_judges_per_team'];
$team[$t]['judges'] = array();
$t++;
}
TRACE("Created judging teams $start_t -> ".($t - 1)."\n\n");
TRACE("Need to assign these teams to $num projects: ");
// print_r($jdivisions[$d_id][$c_id][$l_id]);
TRACE("\n\n");
/* We just created teams $start_t -> $t-1, now we can assign which projects
* they judge in different timeslots */
/* Each project must be judged $data['num_times_judged'], and each team is
* allowed to judge $data['num_times_judged'] projects */
$x=0; /* Cycles over 0 -> $num */
$ts=1; /* Current timeslot , increment when all judging teams are assinged */
$j=0; /* Cycles over o0 -> $numteams */
$teams_at_this_ts = array();
$num_done = 0;
while(1) {
TRACE("x=$x ");
if($x == $num) $x=0;
/* Get the project id we want to look at */
$p = $jdivisions[$d_id][$c_id][$l_id][$x];
TRACE(" project=$p \n\n");
TRACE("This projects has ".(count($data['projects'][$p]['timetable']))." judging teams\n");
/* See if this project needs more judges */
if(count($data['projects'][$p]['timetable']) == $data['num_times_judged']) {
/* No, this project doesn't need any more judging teams */
TRACE(" This project doesn't need more teams, skipping\n\n");
// print_r($data['projects'][$p]['timetable']);
TRACE("\n\n");
if($data['projects'][$p]['timetable_done'] != 1) {
$data['projects'][$p]['timetable_done'] = 1;
$num_done++;
if($num_done == $num) break;
}
$x++;
continue;
}
/* Find a judging team to assign */
TRACE("Starting at team=$j\n\n");
while(1) {
TRACE("j=$j");
if($j == $numteams) $j = 0;
$jteam = $j + $start_t;
TRACE(" team=$jteam\n\n");
if(in_array($jteam, $teams_at_this_ts)) {
$j++;
continue;
}
if(!in_array($jteam, $data['projects'][$p]['timetable'])) {
/* Add this juding team to the timetable */
TRACE("Project $p, timeslot $ts = judging team $jteam\n\n");
$data['projects'][$p]['timetable'][$ts] = $jteam;
$teams_at_this_ts[] = $jteam;
$j++;
break;
}
$j++;
if($j==$numteams) $j=0;
}
$x++;
if(count($teams_at_this_ts) == $numteams) {
$ts++;
$teams_at_this_ts = array();
if($ts > $max_ts) $max_ts = $ts;
}
}
}
}
}
/*
$data = array( 'min_per_team' => 2,
'max_per_team' => 4,
'teams' => array() );
$data['teams']['S']['LS'] = 4;
$data['teams']['S']['PS'] = 4;
$data['teams']['S']['Case'] = 3;
$data['teams']['S']['CS'] = 2;
$data['teams']['I']['LS'] = 3;
$data['teams']['I']['PS'] = 3;
$data['teams']['I']['Case'] = 2;
$data['teams']['I']['CS'] = 1;
$data['teams']['J']['LS'] = 2;
$data['teams']['J']['PS'] = 2;
$data['teams']['J']['Case'] = 1;
$data['teams']['J']['CS'] = 4;
*/
//print_r($data['projects']);
TRACE("Teams: ".count($team)."\n");
//print_r($team);
$q=mysql_query("SELECT * FROM judges WHERE complete='yes' AND judges_years.year='{$config['FAIRYEAR']}' AND judges_years.judges_id=judges.id");
TRACE("\n");
$q=mysql_query("SELECT judges.* FROM judges,judges_years WHERE complete='yes' AND judges_years.year='{$config['FAIRYEAR']}' AND judges_years.judges_id=judges.id");
$judges=array();
while($r=mysql_fetch_object($q))
{
unset($divprefs);
@ -384,11 +478,12 @@ while($r=mysql_fetch_object($q))
);
}
//print_r($judges);
//echo nl2br(TRACE_R($judges, true));
$teams = judges_assign_anneal($div,$cat, $judges, $data);
judges_assign_anneal($div,$cat, $langr, $judges, $team, $data);
//TRACE_R( $teams);
//print_r( $team);
$teamnums=array();
send_header("Judging teams automatic scheduler");
@ -401,13 +496,36 @@ echo "<a href=\"judges_teams_members.php\">".i18n("Manage Judge Members")."</a>"
echo "<br />";
echo "<br />";
print("Project Timeslots:<br>\n");
print("<table border=1><tr><td>Project ID</td>");
for($x=0;$x<$max_ts;$x++) {
print("<td>Slot ".($x + 1)."</td>");
}
print("</tr>");
while(list($proj_id, $projinfo) = each( $data['projects'] )) {
print("<tr><td>$proj_id</td>");
$last_slot = 1;
while(list($slot,$jteam) = each ($projinfo['timetable']) ) {
while($last_slot != $slot) {
print("<td>&nbsp;</td>");
$last_slot++;
}
print("<td>".($jteam+1)."</td>");
$last_slot++;
}
print("</tr>");
}
print("</table>");
$totalcost=0;
while(list($tn, $t) = each($teams)) {
while(list($tn, $t) = each($team)) {
//team numbers start with 0 in the annealer, but we want them to start at 1, so just tn++ here.
$tn++;
print("Team $tn: ({$div[$t['division']]}({$t['division']}),{$cat[$t['category']]}({$t['category']})) ".
"(cost:{$t['cost']} )<br>");
"(cost:{$t['cost']} )<br>\n");
$totalcost+=$t['cost'];
if(!$teamnums[$t['division']][$t['category']]) $teamnums[$t['division']][$t['category']]=1;
@ -418,7 +536,7 @@ while(list($tn, $t) = each($teams)) {
while(list($key, $j) = each($t['judges']) ) {
$judge = $judges[$j];
print("&nbsp;&nbsp;&nbsp;{$judge['name']}<br>");
print("&nbsp;&nbsp;&nbsp;{$judge['name']}<br>\n");
mysql_query("INSERT INTO judges_teams_link (judges_id,judges_teams_id,captain,year) VALUES ('{$judge['judges_id']}','$team_id','{$judge['willing_chair']}','{$config['FAIRYEAR']}')");
}