Ajout des coûts fixes dans le solveur pour vérifier si on peut trouver une solution optimale.

This commit is contained in:
Francois Berube\frabe 2018-04-06 16:32:44 -04:00
parent d51d7d4a35
commit 186ae740e4
5 changed files with 139 additions and 130 deletions

View file

@ -14,7 +14,6 @@ public class AbsenceSchedulesArray extends SchedulesArray{
generateAbsenceSimulation(r);
}
private void generateAbsenceSimulation(RandomEngine r) {
for (int i = 0; i < getNumberPartTimeEmployee(); i++) {

View file

@ -25,20 +25,14 @@ public class ModelInitialSchedules {
public BoolVar workPeriodsSchedulesOfFullTimeEmployees[][];
private BoolVar transposeWorkPeriodsSchedulesOfFullTimeEmployees[][];
private BoolVar workPeriodsOfPartTimeEmployees[][];
private BoolVar workPeriodsOfFullTimeEmployees[][];
private BoolVar allWorkPeriods[];
public BoolVar allWorkPeriods[];
public IntVar workingPeriodsPerPartTimeEmployees[];
public IntVar partTimeEmployeesPerWorkPeriods[];
public IntVar workingPeriodsPerFullTimeEmployees[];
public IntVar fullTimeEmployeesPerWorkPeriods[];
public IntVar employeesPerWorkPeriods[];
private IntVar partTimeEmployeesPerWorkPeriods[];
private IntVar fullTimeEmployeesPerWorkPeriods[];
private IntVar employeesPerWorkPeriods[];
public Model chocoModelInitialSchedules;
public IntVar TotalEmployeesSalary;
public IntVar scheduleProfit;
public IntVar totalEmployeesCost;
public ModelInitialSchedules(ParametersInitialSchedules myScheduleParameters) {
@ -87,10 +81,6 @@ public class ModelInitialSchedules {
}
}*/
// Variable pour faire le compte du nombre d'heures des employes
this.workingPeriodsPerPartTimeEmployees = chocoModelInitialSchedules.intVarArray(this.maxPartTimeEmployee, 0, this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
this.workingPeriodsPerFullTimeEmployees = chocoModelInitialSchedules.intVarArray(this.maxFullTimeEmployee, 0, this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
// Creer la transpose des horaires pour compter les elements des colonnes
this.transposeWorkPeriodsSchedulesOfPartTimeEmployees = chocoModelInitialSchedules.boolVarMatrix(this.myScheduleParameters.getWorkPeriodsPerSchedule(), this.maxPartTimeEmployee);
for (int workPeriod = 0; workPeriod < this.myScheduleParameters.getWorkPeriodsPerSchedule(); workPeriod++) {
@ -113,59 +103,20 @@ public class ModelInitialSchedules {
this.employeesPerWorkPeriods = chocoModelInitialSchedules.intVarArray(this.myScheduleParameters.getWorkPeriodsPerSchedule(),
0, this.maxPartTimeEmployee + this.maxFullTimeEmployee, true);
// Variable pour les périodes de travail par jour des travailleurs à temps partiel
/*this.workPeriodsOfPartTimeEmployees = chocoModelInitialSchedules.boolVarMatrix(this.maxPartTimeEmployee * this.myScheduleParameters.daysPerSchedule
, this.myScheduleParameters.workPeriodsPerDay);
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
for (int day = 0; day < this.myScheduleParameters.daysPerSchedule; day++) {
System.arraycopy(this.workPeriodsSchedulesOfPartTimeEmployees[employee],
day * this.myScheduleParameters.workPeriodsPerDay + 0,
this.workPeriodsOfPartTimeEmployees[employee * this.myScheduleParameters.daysPerSchedule + day],
0, this.myScheduleParameters.workPeriodsPerDay);
}
}*/
}
private void createModelConstraints() {
// Constrainte tableau pour choisir un type d'horaire dans les horaires possibles
// Constraintes tableau pour choisir un type d'horaire dans les horaires possibles
for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) {
chocoModelInitialSchedules.table(this.workPeriodsSchedulesOfFullTimeEmployees[employee],
this.myScheduleParameters.enumerationWorkPeriodsSchedulesOfFullTimeEmployees).post();
}
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
chocoModelInitialSchedules.table(this.workPeriodsSchedulesOfPartTimeEmployees[employee],
this.myScheduleParameters.enumerationWorkPeriodsSchedulesOfPartTimeEmployees).post();
}
// Constraintes pour compter le nombre d'heures travaillees par les differents employes
/*for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
chocoModelInitialSchedules.count(chocoModelInitialSchedules.intVar(1),
this.workPeriodsSchedulesOfPartTimeEmployees[employee],
this.workingPeriodsPerPartTimeEmployees[employee]).post();
}
for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) {
chocoModelInitialSchedules.count(chocoModelInitialSchedules.intVar(1),
this.workPeriodsSchedulesOfFullTimeEmployees[employee],
this.workingPeriodsPerFullTimeEmployees[employee]).post();
}*/
// Constraintes pour borner le nombre d'heures travaillees par les employes a temps partiel
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
BoolVar isWorkingEmployee = chocoModelInitialSchedules.arithm(
this.workingPeriodsPerPartTimeEmployees[employee], ">", 0).reify();
chocoModelInitialSchedules.ifThen(isWorkingEmployee,
chocoModelInitialSchedules.arithm(
this.workingPeriodsPerPartTimeEmployees[employee], ">=",
this.myScheduleParameters.getMinWorkingPeriodsOfPartTimeEmployeesPerSchedule()));
chocoModelInitialSchedules.arithm(this.workingPeriodsPerPartTimeEmployees[employee], "<=",
this.myScheduleParameters.getMaxWorkingPeriodsOfPartTimeEmployeesPerSchedule()).post();
}
// Constraintes pour compter le nombre d'employes par periode de travail et s'assurer qu'il
// satisfait la demande en employes
for (int workPeriod = 0; workPeriod < this.myScheduleParameters.getWorkPeriodsPerSchedule(); workPeriod++) {
@ -183,98 +134,144 @@ public class ModelInitialSchedules {
this.employeesPerWorkPeriods[workPeriod]).post();
}
// Contrainte pour forcer des heures consécutives par jour pour les employés à temps partiel
/*for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
for (int day = 0; day < this.myScheduleParameters.daysPerSchedule; day++) {
chocoModelInitialSchedules.table(
this.workPeriodsOfPartTimeEmployees[employee * this.myScheduleParameters.daysPerSchedule + day],
this.myScheduleParameters.ValidPartTimeEmployeeShiftTuples).post();
}
}*/
// Contrainte de bris de symétrie:
// chaque horaire d'employé est léxicographiquement inférieure à la suivante, par type d'employé
// Ne fonctionne pas avec l'heuristique par défaut
// for (int employee = 0; employee < (this.maxPartTimeEmployee-1); employee++){
// chocoModelInitialSchedules.lexLessEq(this.workPeriodsSchedulesOfPartTimeEmployees[employee],
// this.workPeriodsSchedulesOfPartTimeEmployees[employee+1]).post();
// }
// for (int employee = 0; employee < (this.maxFullTimeEmployee-1); employee++){
// chocoModelInitialSchedules.lexLessEq(this.workPeriodsSchedulesOfFullTimeEmployees[employee],
// this.workPeriodsSchedulesOfFullTimeEmployees[employee+1]).post();
// }
for (int employee = 0; employee < (this.maxPartTimeEmployee-1); employee++){
chocoModelInitialSchedules.lexLessEq(this.workPeriodsSchedulesOfPartTimeEmployees[employee],
this.workPeriodsSchedulesOfPartTimeEmployees[employee+1]).post();
}
for (int employee = 0; employee < (this.maxFullTimeEmployee-1); employee++){
chocoModelInitialSchedules.lexLessEq(this.workPeriodsSchedulesOfFullTimeEmployees[employee],
this.workPeriodsSchedulesOfFullTimeEmployees[employee+1]).post();
}
}
private void createModelObjectiveFunction() {
// Calcul du nombre de périodes travaillées par chaque type d'employés dans l'horaire
IntVar[] NumberOfPartTimeEmployeesPerPeriod =
IntVar[] numberOfPartTimeEmployeesPerPeriod =
chocoModelInitialSchedules.intVarArray(this.myScheduleParameters.getWorkPeriodsPerSchedule(),
0,
this.maxPartTimeEmployee, true);
IntVar[] NumberOfFullTimeEmployeesPerPeriod =
IntVar[] numberOfFullTimeEmployeesPerPeriod =
chocoModelInitialSchedules.intVarArray(this.myScheduleParameters.getWorkPeriodsPerSchedule(),
0,
this.maxFullTimeEmployee, true);
for (int workPeriod = 0; workPeriod < this.myScheduleParameters.getWorkPeriodsPerSchedule(); workPeriod++) {
chocoModelInitialSchedules.sum(transposeWorkPeriodsSchedulesOfPartTimeEmployees[workPeriod],
"=", NumberOfPartTimeEmployeesPerPeriod[workPeriod]).post();
"=", numberOfPartTimeEmployeesPerPeriod[workPeriod]).post();
chocoModelInitialSchedules.sum(transposeWorkPeriodsSchedulesOfFullTimeEmployees[workPeriod],
"=", NumberOfFullTimeEmployeesPerPeriod[workPeriod]).post();
"=", numberOfFullTimeEmployeesPerPeriod[workPeriod]).post();
}
IntVar NumberOfPartTimeEmployeesPeriods =
IntVar numberOfPartTimeEmployeesPeriods =
chocoModelInitialSchedules.intVar(
0, this.maxPartTimeEmployee * this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
IntVar NumberOfFullTimeEmployeesPeriods =
IntVar numberOfFullTimeEmployeesPeriods =
chocoModelInitialSchedules.intVar(
0, this.maxPartTimeEmployee * this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
chocoModelInitialSchedules.sum(NumberOfPartTimeEmployeesPerPeriod, "=", NumberOfPartTimeEmployeesPeriods).post();
chocoModelInitialSchedules.sum(NumberOfFullTimeEmployeesPerPeriod, "=", NumberOfFullTimeEmployeesPeriods).post();
chocoModelInitialSchedules.sum(numberOfPartTimeEmployeesPerPeriod, "=", numberOfPartTimeEmployeesPeriods).post();
chocoModelInitialSchedules.sum(numberOfFullTimeEmployeesPerPeriod, "=", numberOfFullTimeEmployeesPeriods).post();
// Calcul du salaire versé
IntVar PartTimeEmployeesSalary =
IntVar partTimeEmployeesSalary =
chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate(), true);
IntVar FullTimeEmployeesSalary =
IntVar fullTimeEmployeesSalary =
chocoModelInitialSchedules.intVar(0, this.maxFullTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate(), true);
this.TotalEmployeesSalary = chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate() +
this.maxFullTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate(), true);
IntVar workingPeriodCostOfPartTimeEmployees =
chocoModelInitialSchedules.intVar(this.myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate());
IntVar workingPeriodCostOfFullTimeEmployees =
chocoModelInitialSchedules.intVar(this.myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate());
chocoModelInitialSchedules.arithm(NumberOfPartTimeEmployeesPeriods, "*", workingPeriodCostOfPartTimeEmployees, "=", PartTimeEmployeesSalary).post();
chocoModelInitialSchedules.arithm(NumberOfFullTimeEmployeesPeriods, "*", workingPeriodCostOfFullTimeEmployees, "=", FullTimeEmployeesSalary).post();
chocoModelInitialSchedules.arithm(PartTimeEmployeesSalary, "+", FullTimeEmployeesSalary, "=", this.TotalEmployeesSalary).post();
chocoModelInitialSchedules.arithm(numberOfPartTimeEmployeesPeriods, "*", workingPeriodCostOfPartTimeEmployees, "=", partTimeEmployeesSalary).post();
chocoModelInitialSchedules.arithm(numberOfFullTimeEmployeesPeriods, "*", workingPeriodCostOfFullTimeEmployees, "=", fullTimeEmployeesSalary).post();
// Compter le nombre d'heures travaillees par les differents employes pour determiner les employes actifs
IntVar[] workingPeriodsPerPartTimeEmployees =
chocoModelInitialSchedules.intVarArray(this.maxPartTimeEmployee,0,this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
BoolVar[] isWorkingPartTimeEmployees =
chocoModelInitialSchedules.boolVarArray(this.maxPartTimeEmployee);
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
chocoModelInitialSchedules.sum(workPeriodsSchedulesOfPartTimeEmployees[employee],
"=", workingPeriodsPerPartTimeEmployees[employee]).post();
BoolVar isWorkingEmployee = chocoModelInitialSchedules.arithm(
workingPeriodsPerPartTimeEmployees[employee], ">", 0).reify();
chocoModelInitialSchedules.ifThen(isWorkingEmployee,
chocoModelInitialSchedules.arithm(isWorkingPartTimeEmployees[employee], "=", chocoModelInitialSchedules.boolVar(true)));
}
IntVar workingPartTimeEmployees = chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee);
chocoModelInitialSchedules.sum(isWorkingPartTimeEmployees, "=", workingPartTimeEmployees).post();
IntVar[] workingPeriodsPerFullTimeEmployees =
chocoModelInitialSchedules.intVarArray(this.maxFullTimeEmployee,0,this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
BoolVar[] isWorkingFullTimeEmployees =
chocoModelInitialSchedules.boolVarArray(this.maxFullTimeEmployee);
for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) {
chocoModelInitialSchedules.sum(workPeriodsSchedulesOfFullTimeEmployees[employee],
"=", workingPeriodsPerFullTimeEmployees[employee]).post();
BoolVar isWorkingEmployee = chocoModelInitialSchedules.arithm(
workingPeriodsPerFullTimeEmployees[employee], ">", 0).reify();
chocoModelInitialSchedules.ifThen(isWorkingEmployee,
chocoModelInitialSchedules.arithm(isWorkingFullTimeEmployees[employee], "=", chocoModelInitialSchedules.boolVar(true)));
}
IntVar workingFullTimeEmployees = chocoModelInitialSchedules.intVar(0, this.maxFullTimeEmployee);
chocoModelInitialSchedules.sum(isWorkingFullTimeEmployees, "=", workingFullTimeEmployees).post();
// Calcul des couts fixes
IntVar partTimeEmployeesFixedCost =
chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee *
this.myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule(), true);
IntVar fullTimeEmployeesFixedCost =
chocoModelInitialSchedules.intVar(0, this.maxFullTimeEmployee *
this.myScheduleParameters.getFixedCostOfFullTimeEmployeesPerSchedule(), true);
//TODO: Inclure les frais fixes par employé. Jai defini des accesseurs dans la classe ParametersInitialSchedules
chocoModelInitialSchedules.arithm(workingPartTimeEmployees, "*", chocoModelInitialSchedules.intVar(this.myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule()),
"=", partTimeEmployeesFixedCost).post();
chocoModelInitialSchedules.arithm(workingPartTimeEmployees, "*", chocoModelInitialSchedules.intVar(this.myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule()),
"=", partTimeEmployeesFixedCost).post();
// Calcul des couts totaux
IntVar partTimeEmployeesCost =
chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee *
this.myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule() +
this.maxPartTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate(), true);
IntVar fullTimeEmployeesCost =
chocoModelInitialSchedules.intVar(0, this.maxFullTimeEmployee *
this.myScheduleParameters.getFixedCostOfFullTimeEmployeesPerSchedule() +
this.maxFullTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate(), true);
chocoModelInitialSchedules.arithm(partTimeEmployeesFixedCost, "+", partTimeEmployeesSalary, "=", partTimeEmployeesCost).post();
chocoModelInitialSchedules.arithm(fullTimeEmployeesFixedCost, "+", fullTimeEmployeesSalary, "=", fullTimeEmployeesCost).post();
this.totalEmployeesCost = chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee *
this.myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule() +
this.maxPartTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate() +
this.maxFullTimeEmployee *
this.myScheduleParameters.getFixedCostOfFullTimeEmployeesPerSchedule() +
this.maxFullTimeEmployee *
this.myScheduleParameters.getWorkPeriodsPerSchedule() *
this.myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate(), true);
chocoModelInitialSchedules.arithm(partTimeEmployeesCost, "+", fullTimeEmployeesCost, "=", this.totalEmployeesCost).post();
// this.scheduleProfit = chocoModelInitialSchedules.intVar("TOTAL_COST", 0, 20 * N * p, true);
// chocoModelInitialSchedules.scalar(perte , coeffs , "=", this.scheduleProfit).post();
}
}

View file

@ -57,14 +57,14 @@ public class MainClass {
/*solverInitialSchedules.setSearch(Search.domOverWDegSearch(myModelInitialSchedules.allWorkPeriods));*/
// solverInitialSchedules.setRestartOnSolutions(); /*Sans restart, toutes les horaires sont identiques*/
solverInitialSchedules.limitSolution(1);
// solverInitialSchedules.limitSolution(5);
//solverInitialSchedules.limitTime(10000);
List<Solution> myInitialSchedulesSolutions;
/* myInitialSchedulesSolutions = solverInitialSchedules.findAllOptimalSolutions
(myModelInitialSchedules.TotalEmployeesSalary, Model.MINIMIZE);*/
myInitialSchedulesSolutions = solverInitialSchedules.findAllOptimalSolutions
(myModelInitialSchedules.totalEmployeesCost, myModelInitialSchedules.chocoModelInitialSchedules.MINIMIZE);
//solverInitialSchedules.findSolution();
myInitialSchedulesSolutions = solverInitialSchedules.findAllSolutions();
// solverInitialSchedules.findSolution();
// myInitialSchedulesSolutions = solverInitialSchedules.findAllSolutions();
solverInitialSchedules.printStatistics();
// Création de l'objet banque d'horaire, qui est une liste d'objets de type InitialSchedulesArray, qui contiennent chacun deux tableaux.

View file

@ -54,6 +54,8 @@ public class SchedulesArray {
fullTimeEmployee++;
}
}
// Faire un assert pour voir si le cout total equivaut a celui trouve par le solveur.
}

View file

@ -49,42 +49,53 @@ public class RecoveredSchedulesArray extends SchedulesArray{
PriorityQueue< Quartet<boolean[][], boolean[][], Integer, Integer> > scheduleStatesOrderedByOptimisticCost = new PriorityQueue<>(quartetComparator);
RecoveringAction currentRecoveringAction = null;
boolean isSolutionFound = true;
// Fouille en profondeur avec calcul de cout optimiste base sur le taux horaire regulier des employes a temps plein.
while ( bestScheduleCost > currentOptimisticTotalEmployeeCost ) {
PriorityQueue<RecoveringAction> recoveringActionsOrderedByCost =
getPossibleRecoveringActions(currentRecoveredScheduleOfPartTimeEmployees, currentRecoveredScheduleOfFullTimeEmployees,
alreadyRecoveredWorkPeriodByPartTimeEmployees, alreadyRecoveredWorkPeriodByFullTimeEmployees, recoveringActionCostComparator);
boolean[][] recoveredScheduleOfPartTimeEmployeesAfterAction = this.getDeepCopyEmployeesSchedules(currentRecoveredScheduleOfPartTimeEmployees);
boolean[][] recoveredScheduleOfFullTimeEmployeesAfterAction = this.getDeepCopyEmployeesSchedules(currentRecoveredScheduleOfFullTimeEmployees);
currentRecoveringAction = recoveringActionsOrderedByCost.poll();
if (currentRecoveringAction.getClass().getName().equals("SchedulesRecovery.RecoveringActionPartTimeEmployee")) {
recoveredScheduleOfPartTimeEmployeesAfterAction[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
alreadyRecoveredWorkPeriodByPartTimeEmployees[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
} else if (currentRecoveringAction.getClass().getName().equals("SchedulesRecovery.RecoveringActionFullTimeEmployee")) {
recoveredScheduleOfFullTimeEmployeesAfterAction[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
alreadyRecoveredWorkPeriodByFullTimeEmployees[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
if (recoveringActionsOrderedByCost.size() > 0){
boolean[][] recoveredScheduleOfPartTimeEmployeesAfterAction = this.getDeepCopyEmployeesSchedules(currentRecoveredScheduleOfPartTimeEmployees);
boolean[][] recoveredScheduleOfFullTimeEmployeesAfterAction = this.getDeepCopyEmployeesSchedules(currentRecoveredScheduleOfFullTimeEmployees);
currentRecoveringAction = recoveringActionsOrderedByCost.poll();
if (currentRecoveringAction.getClass().getName().equals("SchedulesRecovery.RecoveringActionPartTimeEmployee")) {
recoveredScheduleOfPartTimeEmployeesAfterAction[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
alreadyRecoveredWorkPeriodByPartTimeEmployees[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
} else if (currentRecoveringAction.getClass().getName().equals("SchedulesRecovery.RecoveringActionFullTimeEmployee")) {
recoveredScheduleOfFullTimeEmployeesAfterAction[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
alreadyRecoveredWorkPeriodByFullTimeEmployees[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
}
optimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost - myParametersInitialSchedules.getMinimumWorkingPeriodCost() + currentRecoveringAction.recoveringActionCost;
Quartet<boolean[][], boolean[][], Integer, Integer> scheduleState = Quartet.with
(recoveredScheduleOfPartTimeEmployeesAfterAction, recoveredScheduleOfFullTimeEmployeesAfterAction, optimisticTotalEmployeeCost, remainingRecoveringAction - 1);
scheduleStatesOrderedByOptimisticCost.add(scheduleState);
}
optimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost - myParametersInitialSchedules.getMinimumWorkingPeriodCost() + currentRecoveringAction.recoveringActionCost;
Quartet<boolean[][], boolean[][], Integer, Integer> scheduleState = Quartet.with
(recoveredScheduleOfPartTimeEmployeesAfterAction, recoveredScheduleOfFullTimeEmployeesAfterAction, optimisticTotalEmployeeCost, remainingRecoveringAction - 1);
scheduleStatesOrderedByOptimisticCost.add(scheduleState);
if (remainingRecoveringAction - 1 == 0){
bestScheduleCost = Math.min(bestScheduleCost, optimisticTotalEmployeeCost);
}
Quartet<boolean[][], boolean[][], Integer, Integer> currentScheduleState = scheduleStatesOrderedByOptimisticCost.poll();
currentRecoveredScheduleOfPartTimeEmployees = currentScheduleState.getValue0();
currentRecoveredScheduleOfFullTimeEmployees = currentScheduleState.getValue1();
currentOptimisticTotalEmployeeCost = currentScheduleState.getValue2();
remainingRecoveringAction = currentScheduleState.getValue3();
if (scheduleStatesOrderedByOptimisticCost.size() > 0) {
Quartet<boolean[][], boolean[][], Integer, Integer> currentScheduleState = scheduleStatesOrderedByOptimisticCost.poll();
currentRecoveredScheduleOfPartTimeEmployees = currentScheduleState.getValue0();
currentRecoveredScheduleOfFullTimeEmployees = currentScheduleState.getValue1();
currentOptimisticTotalEmployeeCost = currentScheduleState.getValue2();
remainingRecoveringAction = currentScheduleState.getValue3();
} else {
isSolutionFound = false;
break;
}
}
this.fullTimeSchedules = currentRecoveredScheduleOfFullTimeEmployees;
this.partTimeSchedules = currentRecoveredScheduleOfPartTimeEmployees;
if (isSolutionFound) {
this.fullTimeSchedules = currentRecoveredScheduleOfFullTimeEmployees;
this.partTimeSchedules = currentRecoveredScheduleOfPartTimeEmployees;
assert(EmployeeCostCalculator.getFullScheduleCost(this, myParametersInitialSchedules) == bestScheduleCost);
System.out.println(" Solution Found ");
} else {
System.out.println(" No Solution Found ");
}
assert(EmployeeCostCalculator.getFullScheduleCost(this, myParametersInitialSchedules) == bestScheduleCost);
}