From 3bccb5d1631d1e105ea786959131998b7bd57eb9 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 16 Jan 2006 04:58:43 +0000 Subject: [PATCH] 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 :) --- admin/judges_sa.php | 256 ++++++++++++++++++++++++++++++++------------ 1 file changed, 187 insertions(+), 69 deletions(-) diff --git a/admin/judges_sa.php b/admin/judges_sa.php index a5ad4d7..87b2978 100644 --- a/admin/judges_sa.php +++ b/admin/judges_sa.php @@ -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)
"); + TRACE("Random move: ($t1,$j1) ($t2,$j2)\n"); TRACE_R($team[$t1]['judges']); - TRACE("
T2:"); + TRACE("T2:\n"); TRACE_R($team[$t2]['judges']); - TRACE("
"); + 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
"); +// 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
"); +// TRACE("Judge $judge_id cp=$cpref, dp=$dpref\n"); $cost += 2 * (-$dpref + 2); $cost += 2 * (-$cpref + 2); } - TRACE("Team $team_id, cost is $cost
"); + 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
"); - TRACE("Team $tid2 cost {$t2['cost']} -> $c2
"); - TRACE("Delta = $cost
"); + 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("
T2:"); + TRACE("\nT2:"); TRACE_R($t2['judges']); - TRACE("
"); + 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"); + 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
"); + TRACE("Move accepted, cost=$current_cost\n"); } else { - TRACE("Move rejected
"); + TRACE("Move rejected\n"); } } - TRACE("Cost is $current_cost
"); + 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 "".i18n("Manage Judge Members")."" echo "
"; echo "
"; + +print("Project Timeslots:
\n"); +print(""); +for($x=0;$x<$max_ts;$x++) { + print(""); +} +print(""); +while(list($proj_id, $projinfo) = each( $data['projects'] )) { + print(""); + $last_slot = 1; + while(list($slot,$jteam) = each ($projinfo['timetable']) ) { + while($last_slot != $slot) { + print(""); + $last_slot++; + } + print(""); + $last_slot++; + } + print(""); +} +print("
Project IDSlot ".($x + 1)."
$proj_id ".($jteam+1)."
"); + + $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']} )
"); + "(cost:{$t['cost']} )
\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']}
"); + print("   {$judge['name']}
\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']}')"); }