forked from science-ation/science-ation
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:
parent
d763cd1636
commit
3bccb5d163
@ -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> </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(" {$judge['name']}<br>");
|
||||
print(" {$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']}')");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user