Script for Sisyphus-I
void function main ()
{
check_if_already_placed_employees();
if (possible_to_place_the_group_head())
{ if (possible_to_place_the_secretaries())
{ if (possible_to_place_the_managers())
{ if (possible_to_place_the_heads_of_large_projects())
{ print; print "----- Placing simple researchers";
try_to_place_simple_researchers_by_pairs();
try_to_place_remaining_employees_alone();
}
}
}
}
}
void function check_if_already_placed_employees()
{
spec [Employee:?]->(In)->[Office] | set Placed_employees;
if ($Placed_employees)
{ print "Some employees are already placed in the given data set";
spec [Employee]->(In)->[Office]; //list the relevant CGs
}
spec Employee : ? | set The_employees;
subtract $The_employees $Placed_employees | set Employees_to_place;
}
/* ---------------- Functions for placing the group head ------------------ */
boolean function possible_to_place_the_group_head()
{
print; print "----- Placing the head of group";
spec Group_head : ? | set The_group_head;
spec "[Employee:$The_group_head]->(In)->[Office:?]" | set Office_of_group_head;
if ($Office_of_group_head == "")
{ if (! possible_to_place($The_group_head,Large_central_office))
{ if (! possible_to_place($The_group_head,Small_central_office))
{ if (! possible_to_place($The_group_head,Large_and_not_central_office))
{ if (! possible_to_place($The_group_head,Small_and_not_central_office))
{ print "$The_group_head cannot be placed: no office left";
return false;
}
}
}
}
spec "[Employee:$The_group_head]->(In)->[Office:?]" | set Office_of_group_head;
}
return true;
}
boolean function possible_to_place (employee, kind_of_office)
{
spec $kind_of_office : ? | set offices_of_this_kind;
for o in $offices_of_this_kind
{ spec "[Employee]->(In)->[Office:$o]" | set occupied_office;
if ($occupied_office == "") //$o is empty, the employee can be alone
{ place_employee_in($employee,$o); return true; }
}
return false;
}
void function place_employee_in (employee, office)
{
name "#$employee$office" "[Employee: $employee]->(In)->[Office: $office]";
print "$employee is placed in $office";
subtractFrom Employees_to_place $employee;
}
/* --------- Functions for placing the secretaries, the managers
and the head of large projects --------- */
boolean function possible_to_place_the_secretaries()
{
print; print "----- Placing the secretaries";
spec Secretary : ? | set The_secretaries;
for s in $The_secretaries
{ spec "[Employee:$s]->(In)->[Office]" | set office_of_this_employee;
if ($office_of_this_employee == "")
{ if (! possible_to_place_with_another_secretary($s))
{ if (! possible_to_place_nearest_group_head($s,Large_office))
{ if (! possible_to_place_nearest_group_head($s,Small_office))
{ print "The secretary $s cannot be placed close to
$Office_of_group_head, the office of head of group $The_group_head";
return false;
}
}
}
}
}
return true;
}
boolean function possible_to_place_the_managers()
{
print; print "----- Placing the managers";
spec Manager : ? | set the_managers;
for m in $the_managers
{ spec "[Employee:$m]->(In)->[Office]" | set office_of_this_employee;
if ($office_of_this_employee == "")
{ if (! possible_to_place_nearest_group_head($m,Small_central_office))
{ if (! possible_to_place_nearest_group_head($m,Small_and_not_central_office))
{ if (! possible_to_place_nearest_group_head($m,Large_central_office))
{ if (! possible_to_place_nearest_group_head($m,Large_and_not_central_office))
{ print "The manager $m cannot be placed close to
$Office_of_group_head, the office of head of group $The_group_head";
return false;
}
}
}
}
}
}
return true;
}
boolean function possible_to_place_the_heads_of_large_projects()
{
print; print "----- Placing the heads of large projects";
spec Large_project_head : ? | set the_heads_of_large_projects;
for h in $the_heads_of_large_projects
{ spec "[Employee:$h]->(In)->[Office]" | set office_of_this_employee;
if ($office_of_this_employee == "")
{ if (! possible_to_place_nearest_group_head($h,Small_office))
{ if (! possible_to_place_nearest_group_head($h,Large_office))
{ print "The head of large project $h cannot be placed close to
$Office_of_group_head, the office of head of group $The_group_head";
return false;
}
}
}
}
return true;
}
boolean function possible_to_place_with_another_secretary (employee)
{
for s2 in $The_secretaries
{ spec "[Employee:$s2]->(In)->[Office:?]" | set offices_with_a_secretary;
for o in $offices_with_a_secretary
{ if (office_not_fully_occupied($o))
{ place_employee_in($employee,$o); return true; }
}
}
return false;
}
boolean function office_not_fully_occupied (office)
{
spec "[Employee:?]->(In)->[Office:$office]" | count | set number_of_occupants;
if ($number_of_occupants == 0) { return true; }
? Large_office : $office | set office_is_large;
if ($office_is_large)
{ if ($number_of_occupants < 2) { return true; } }
return false;
}
boolean function possible_to_place_nearest_group_head (employee,kind_of_office)
{
set near_chain "->(Near)->"; //first, try very close offices
while (true) //the loop progressively increases $near_chain
{ spec "[Office:?]$near_chain[Office:$Office_of_group_head]"
| set offices_near_group_head;
if ($offices_near_group_head == "") { break; } //no more office at such distance
for o in $offices_near_group_head
{ ? $kind_of_office : $o | set office_is_suitable;
if ($office_is_suitable)
{ spec "[Employee]->(In)->[Office:$o]" | set occupied_office;
if ("$occupied_office" == "") //$o is empty
{ place_employee_in($employee,$o); return true; }
}
}
set near_chain "$near_chain[Office]->(Near)->";
}
return false;
}
/* ---------------- Functions for placing simple researchers ------------------ */
void function try_to_place_simple_researchers_by_pairs()
{
if ($Employees_to_place == "") { return; }
spec Large_office : ? | set large_offices;
spec [Employee]->(In)->[Office:?] | set occupied_offices;
subtract $large_offices $occupied_offices | set Unoccupied_large_offices;
spec [Simple_researcher:?]- { (Agent)<-[Smoke]; } | set smokers;
spec [Simple_researcher:?]- { (Agent)<-[Hack]; } | set hackers;
spec [Simple_researcher:?]- { (Agent)<-[Hack];
(Agent)<-[Smoke]; } | set hackers_smokers;
//echo "Smokers: $smokers."; echo "Hackers: $hackers.";
//echo "Hackers_smokers: $hackers_smokers.";
subtract "$smokers" "$hackers_smokers" | set smokers_non_hackers;
subtract "$hackers" "$hackers_smokers" | set hackers_non_smokers;
spec Simple_researcher : ? | set the_simple_researchers;
subtract "$the_simple_researchers" "$smokers" | set non_smokers;
subtract "$non_smokers" "$hackers_non_smokers" | set non_hackers_non_smokers;
//print " 1- hackers_smokers ---------------------------------------------";
if ($hackers_smokers) { try_to_place_pairs_of(hackers_smokers); }
//print " 2- smokers_non_hackers -----------------------------------------";
if ($Employees_to_place) { try_to_place_pairs_of(smokers_non_hackers); }
//print " 3- hackers_non_smokers -----------------------------------------";
if ($Employees_to_place) { try_to_place_pairs_of(hackers_non_smokers); }
//print " 4- non_hackers_non_smokers -------------------------------------";
if ($Employees_to_place) { try_to_place_pairs_of(non_hackers_non_smokers); }
//print " 5- smokers -----------------------------------------------------";
if ($Employees_to_place) { try_to_place_pairs_of(smokers); }
//print " 6- non_smokers -------------------------------------------------";
if ($Employees_to_place) { try_to_place_pairs_of(non_smokers); }
}
void function try_to_place_pairs_of (kind_of_employee)
{
set suitable_co-occupants $$kind_of_employee; //placed or not
countIn $suitable_co-occupants | set number_of_suitable_co-occupants;
if ($number_of_suitable_co-occupants < 2) { return; }
for e1 in $suitable_co-occupants
{ spec "[Employee:$e1]->(In)->[Office: ?]" | set o1;
if ($o1 == "") //$e1 not placed
{ spec "[Employee:$e1]->(Project)->[Project:?]" | set p1; //$p1: project of $e1
for e2 in $suitable_co-occupants
{ if ($e1 != $e2)
{ //echo " $e1 != $e2.";
spec "[Employee:$e2]->(Project)->[Project:?]" | set p2;
if ($p1 != $p2)
{ spec "[Employee:$e2]->(In)->[Office: ?]" | set o2;
if ($o2) //e2 is already placed
{ if (office_not_fully_occupied($o2))
{ place_employee_in($e1,$o2); break; }
}
else
{ subtractFirstFrom Unoccupied_large_offices | set o2;
if ($o2)
{ place_employee_in($e1,$o2); place_employee_in($e2,$o2);
print " Note: $e1 ($p1) and $e2 ($p2) are $kind_of_employee";
break;
}
}
}
}
}
}
}
if ($Employees_to_place == "") {return;}
//For non placed employees, idem without the constraint of a different project
for e1 in $suitable_co-occupants
{ spec "[Employee:$e1]->(In)->[Office: ?]" | set o1;
if ($o1 == "") //$e1 not placed
{ for e2 in $suitable_co-occupants
{ if ($e1 != $e2)
{ //echo " $e1 != $e2.";
spec "[Employee:$e2]->(In)->[Office: ?]" | set o2;
if ($o2) //e2 is already placed
{ if (office_not_fully_occupied($o2))
{ place_employee_in($e1,$o2); break; }
}
else
{ subtractFirstFrom Unoccupied_large_offices | set o2;
if ($o2)
{ place_employee_in($e1,$o2); place_employee_in($e2,$o2);
print " Note: $e1 ($p1) and $e2 ($p2) are $kind_of_employee";
break;
}
}
}
}
}
}
}
void function try_to_place_remaining_employees_alone()
{
spec Office : ? | set the_offices;
for e in $Employees_to_place
{ spec [Employee]->(In)->[Office:?] | set occupied_offices;
subtract $the_offices $occupied_offices | set unoccupied_offices;
if ($unoccupied_offices)
{ for o in $unoccupied_offices { place_employee_in($e,$o); } }
else
{ print "$e cannot be placed: no office left"; return; }
}
}
/* //place_pair_in ($e1,$p1, $e2,$p2, $kind_of_employee, office);
void function place_pair_in (empl1,proj1, empl2,proj2, kind_of_empl, office)
{
name "#$empl1$office" "[Employee: $empl1]->(In)->[Office: $office]";
name "#$empl2$office" "[Employee: $empl2]->(In)->[Office: $office]";
print "$empl1 and $empl2 are placed in $office";
print -n "They are $kind_of_empl, $empl1 is in the project $proj1";
print "$empl2 is in the project $proj2";
subtractFrom Employees_to_place $empl1;
subtractFrom Employees_to_place $empl2;
}
*/
main(); //run the program