From 186ae740e4c2eb0437d1038f4986b33d366e107d Mon Sep 17 00:00:00 2001 From: "Francois Berube\\frabe" Date: Fri, 6 Apr 2018 16:32:44 -0400 Subject: [PATCH] =?UTF-8?q?Ajout=20des=20co=C3=BBts=20fixes=20dans=20le=20?= =?UTF-8?q?solveur=20pour=20v=C3=A9rifier=20si=20on=20peut=20trouver=20une?= =?UTF-8?q?=20solution=20optimale.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbsenceSchedulesArray.java | 1 - .../ModelInitialSchedules.java | 197 +++++++++--------- Travail_de_session/MainClass.java | 10 +- .../ScheduleUtil/SchedulesArray.java | 2 + .../RecoveredSchedulesArray.java | 59 +++--- 5 files changed, 139 insertions(+), 130 deletions(-) diff --git a/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java b/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java index bd2dfa8..c7e64bc 100644 --- a/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java +++ b/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java @@ -14,7 +14,6 @@ public class AbsenceSchedulesArray extends SchedulesArray{ generateAbsenceSimulation(r); } - private void generateAbsenceSimulation(RandomEngine r) { for (int i = 0; i < getNumberPartTimeEmployee(); i++) { diff --git a/Travail_de_session/InitialSchedules/ModelInitialSchedules.java b/Travail_de_session/InitialSchedules/ModelInitialSchedules.java index 47317cf..6490fce 100644 --- a/Travail_de_session/InitialSchedules/ModelInitialSchedules.java +++ b/Travail_de_session/InitialSchedules/ModelInitialSchedules.java @@ -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(); } } diff --git a/Travail_de_session/MainClass.java b/Travail_de_session/MainClass.java index b55e5ad..de81a05 100644 --- a/Travail_de_session/MainClass.java +++ b/Travail_de_session/MainClass.java @@ -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 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. diff --git a/Travail_de_session/ScheduleUtil/SchedulesArray.java b/Travail_de_session/ScheduleUtil/SchedulesArray.java index 85e29b6..8c21dff 100644 --- a/Travail_de_session/ScheduleUtil/SchedulesArray.java +++ b/Travail_de_session/ScheduleUtil/SchedulesArray.java @@ -54,6 +54,8 @@ public class SchedulesArray { fullTimeEmployee++; } } + + // Faire un assert pour voir si le cout total equivaut a celui trouve par le solveur. } diff --git a/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java b/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java index 25d05dc..85db886 100644 --- a/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java +++ b/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java @@ -49,42 +49,53 @@ public class RecoveredSchedulesArray extends SchedulesArray{ PriorityQueue< Quartet > 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 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 scheduleState = Quartet.with + (recoveredScheduleOfPartTimeEmployeesAfterAction, recoveredScheduleOfFullTimeEmployeesAfterAction, optimisticTotalEmployeeCost, remainingRecoveringAction - 1); + scheduleStatesOrderedByOptimisticCost.add(scheduleState); } - - optimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost - myParametersInitialSchedules.getMinimumWorkingPeriodCost() + currentRecoveringAction.recoveringActionCost; - Quartet scheduleState = Quartet.with - (recoveredScheduleOfPartTimeEmployeesAfterAction, recoveredScheduleOfFullTimeEmployeesAfterAction, optimisticTotalEmployeeCost, remainingRecoveringAction - 1); - scheduleStatesOrderedByOptimisticCost.add(scheduleState); - if (remainingRecoveringAction - 1 == 0){ bestScheduleCost = Math.min(bestScheduleCost, optimisticTotalEmployeeCost); } - - Quartet currentScheduleState = scheduleStatesOrderedByOptimisticCost.poll(); - currentRecoveredScheduleOfPartTimeEmployees = currentScheduleState.getValue0(); - currentRecoveredScheduleOfFullTimeEmployees = currentScheduleState.getValue1(); - currentOptimisticTotalEmployeeCost = currentScheduleState.getValue2(); - remainingRecoveringAction = currentScheduleState.getValue3(); + if (scheduleStatesOrderedByOptimisticCost.size() > 0) { + Quartet 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); }