diff --git a/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java b/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java index 3e1f5f6..55aa0ab 100644 --- a/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java +++ b/Travail_de_session/AbsenceSchedules/AbsenceSchedulesArray.java @@ -11,22 +11,37 @@ public class AbsenceSchedulesArray extends SchedulesArray{ super(myScheduleArray); } - public void generateAbsences(RandomEngine r) { - for (int i = 0; i < this.maxPartTimeEmployee; i++) { - int[] a = new AbsencesVector(this.workPeriodsPerSchedule, r).getAbsencesVector(); - for (int j = 0; j < this.workPeriodsPerSchedule; j++) { - this.PartTimeSchedules[i][j] = this.PartTimeSchedules[i][j] * a[j]; - } - } - for (int i = 0; i < this.maxFullTimeEmployee; i++) { - int[] a = new AbsencesVector(this.workPeriodsPerSchedule, r).getAbsencesVector(); - for (int j = 0; j < this.workPeriodsPerSchedule; j++) { - this.FullTimeSchedules[i][j] = this.FullTimeSchedules[i][j] * a[j]; - } - } - updateEmployeesPerWorkPeriod(); - updateWorkingPeriodsPerPartTimeEmployees(); - updateWorkingPeriodsPerFullTimeEmployees(); + public AbsenceSchedulesArray(AbsenceSchedulesArray myAbsenceScheduleArray) { + super(myAbsenceScheduleArray); } - + + public void generateAbsences(RandomEngine r) { + + for (int i = 0; i < this.maxPartTimeEmployee; i++) { + boolean[] a = new AbsencesVector(this.workPeriodsPerSchedule, r).getAbsencesVector(); + for (int j = 0; j < this.workPeriodsPerSchedule; j++) { + this.partTimeSchedules[i][j] = this.initialPartTimeSchedules[i][j] && a[j]; + } + } + + for (int i = 0; i < this.maxFullTimeEmployee; i++) { + boolean[] a = new AbsencesVector(this.workPeriodsPerSchedule, r).getAbsencesVector(); + for (int j = 0; j < this.workPeriodsPerSchedule; j++) { + this.fullTimeSchedules[i][j] = this.fullTimeSchedules[i][j] && a[j]; + } + } + updateAllEmployeesPerWorkPeriod(); + updateAllWorkingPeriodsPerPartTimeEmployees(); + updateAllWorkingPeriodsPerFullTimeEmployees(); + } + + + protected boolean isPartTimeEmployeeAbsent(int employee, int workPeriod) { + return this.partTimeSchedules[employee][workPeriod] != this.initialPartTimeSchedules[employee][workPeriod]; + } + + protected boolean isFullTimeEmployeeAbsent(int employee, int workPeriod) { + return this.fullTimeSchedules[employee][workPeriod] != this.initialFullTimeSchedules[employee][workPeriod]; + } + } \ No newline at end of file diff --git a/Travail_de_session/AbsenceSchedules/AbsencesVector.java b/Travail_de_session/AbsenceSchedules/AbsencesVector.java index e285198..cf09152 100644 --- a/Travail_de_session/AbsenceSchedules/AbsencesVector.java +++ b/Travail_de_session/AbsenceSchedules/AbsencesVector.java @@ -4,30 +4,30 @@ import jdistlib.Binomial; import jdistlib.rng.RandomEngine; public class AbsencesVector { - private int[] AbsencesVector; - private double probAbsence = 0.02; - private double probReturn = 0.80; + private boolean[] AbsencesVector; + private double probPresence = 0.80; + private double probReturn = 0.50; public AbsencesVector(int length, RandomEngine r) { int current = 1; - AbsencesVector = new int[length]; - Binomial b1 = new Binomial(1, probAbsence); + AbsencesVector = new boolean[length]; + Binomial b1 = new Binomial(1, probPresence); b1.setRandomEngine(r); Binomial b2 = new Binomial(1, probReturn); b2.setRandomEngine(r); for (int i = 0; i < length; i++) { if (current == 1) { current = (int) b1.random(); - AbsencesVector[i] = current; + AbsencesVector[i] = current == 1; } else { current = (int) b2.random(); - AbsencesVector[i] = current; + AbsencesVector[i] = current == 1; } } } - public int[] getAbsencesVector() { + public boolean[] getAbsencesVector() { return AbsencesVector; } } diff --git a/Travail_de_session/InitialSchedules/ModelInitialSchedules.java b/Travail_de_session/InitialSchedules/ModelInitialSchedules.java index 4e22544..e9f1dea 100644 --- a/Travail_de_session/InitialSchedules/ModelInitialSchedules.java +++ b/Travail_de_session/InitialSchedules/ModelInitialSchedules.java @@ -58,9 +58,9 @@ public class ModelInitialSchedules { private void createEmployeesVariables() { this.maxPartTimeEmployee = (int) Math.ceil((double) myScheduleParameters.totalWorkedPeriodsInSchedule - / myScheduleParameters.minWorkingPeriodsOfPartTimeEmployeesPerSchedule); + / myScheduleParameters.getMinWorkingPeriodsOfPartTimeEmployeesPerSchedule()); this.maxFullTimeEmployee = (int) Math.ceil((double) myScheduleParameters.totalWorkedPeriodsInSchedule - / myScheduleParameters.workingPeriodsOfFullTimeEmployeesPerSchedule); + / myScheduleParameters.getWorkingPeriodsOfFullTimeEmployeesPerSchedule()); } @@ -161,9 +161,9 @@ public class ModelInitialSchedules { chocoModelInitialSchedules.ifThen(isWorkingEmployee, chocoModelInitialSchedules.arithm( this.workingPeriodsPerPartTimeEmployees[employee], ">=", - this.myScheduleParameters.minWorkingPeriodsOfPartTimeEmployeesPerSchedule)); + this.myScheduleParameters.getMinWorkingPeriodsOfPartTimeEmployeesPerSchedule())); chocoModelInitialSchedules.arithm(this.workingPeriodsPerPartTimeEmployees[employee], "<=", - this.myScheduleParameters.maxWorkingPeriodsOfPartTimeEmployeesPerSchedule).post(); + this.myScheduleParameters.getMaxWorkingPeriodsOfPartTimeEmployeesPerSchedule()).post(); } // Constraintes pour compter le nombre d'employes par periode de travail et s'assurer qu'il @@ -243,7 +243,7 @@ public class ModelInitialSchedules { IntVar PartTimeEmployeesSalary = chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee * this.myScheduleParameters.workPeriodsPerSchedule * - this.myScheduleParameters.hourlyRateOfPartTimeEmployees, true); + this.myScheduleParameters.regularHourlyRateOfPartTimeEmployees, true); IntVar FullTimeEmployeesSalary = chocoModelInitialSchedules.intVar(0, this.maxFullTimeEmployee * @@ -252,13 +252,13 @@ public class ModelInitialSchedules { this.TotalEmployeesSalary = chocoModelInitialSchedules.intVar(0, this.maxPartTimeEmployee * this.myScheduleParameters.workPeriodsPerSchedule * - this.myScheduleParameters.hourlyRateOfPartTimeEmployees + + this.myScheduleParameters.regularHourlyRateOfPartTimeEmployees + this.maxFullTimeEmployee * this.myScheduleParameters.workPeriodsPerSchedule * this.myScheduleParameters.regularHourlyRateOfFullTimeEmployees, true); IntVar HourlyRateOfPartTimeEmployees = - chocoModelInitialSchedules.intVar(this.myScheduleParameters.hourlyRateOfPartTimeEmployees); + chocoModelInitialSchedules.intVar(this.myScheduleParameters.regularHourlyRateOfPartTimeEmployees); IntVar regularHourlyRateOfFullTimeEmployees = chocoModelInitialSchedules.intVar(this.myScheduleParameters.regularHourlyRateOfFullTimeEmployees); diff --git a/Travail_de_session/InitialSchedules/ParametersInitialSchedules.java b/Travail_de_session/InitialSchedules/ParametersInitialSchedules.java index a021b37..e763f6a 100644 --- a/Travail_de_session/InitialSchedules/ParametersInitialSchedules.java +++ b/Travail_de_session/InitialSchedules/ParametersInitialSchedules.java @@ -6,33 +6,42 @@ public class ParametersInitialSchedules { public int workPeriodsPerDay; int NbFullTimeSolutions; + int NbPartTimeSolutions; + int shiftWorkPerDay; public int daysPerSchedule; public int workPeriodsPerSchedule; int totalWorkedPeriodsInSchedule; - int NbPartTimeSolutions; - Tuples enumerationWorkPeriodsSchedulesOfPartTimeEmployees; + int hoursPerWorkPeriod; int hourlyRateOfPartTimeEmployees; - private int shiftWorkPerDay; - private int hoursPerWorkPeriod; - int minWorkingPeriodsOfPartTimeEmployeesPerSchedule; - int maxWorkingPeriodsOfPartTimeEmployeesPerSchedule; - int fixedCostOfFullTimeEmployeesPerSchedule; - int regularHourlyRateOfFullTimeEmployees; - int overtimeHourlyRateOfFullTimeEmployees; - int workingHoursOfFullTimeEmployeesPerSchedule; + public int fixedCostOfPartTimeEmployeesPerSchedule; + public int regularHourlyRateOfPartTimeEmployees; + public int overtimeHourlyRateOfPartTimeEmployees; + int minWorkingHoursOfPartTimeEmployeesPerSchedule; + int maxWorkingHoursOfPartTimeEmployeesPerSchedule; + int maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork; + int minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees; + + public int fixedCostOfFullTimeEmployeesPerSchedule; + public int regularHourlyRateOfFullTimeEmployees; + public int overtimeHourlyRateOfFullTimeEmployees; int maxWorkingHoursOfFullTimeEmployeesPerSchedule; - int workingPeriodsOfFullTimeEmployeesPerSchedule; - int maxWorkingPeriodsOfFullTimeEmployeesPerSchedule; + int minWorkingHoursOfPartTimeEmployeesPerSchedule + int maxWorkingHoursOfPartTimeEmployeesPerSchedule; + int workingHoursOfFullTimeEmployeesPerSchedule; + + int maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork; + int minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees; int workingHoursPaidAtRegularHourlyRatePerSchedule; + int workingHoursPaidAtRegularHourlyRatePerShiftWork; + private int fixedCostOfPartTimeEmployeesPerSchedule; - private int minWorkingHoursOfPartTimeEmployeesPerSchedule; public int[] requiredWorkforce; Tuples enumerationWorkPeriodsSchedulesOfFullTimeEmployees; - private int maxWorkingHoursOfPartTimeEmployeesPerSchedule; - private Tuples ValidPartTimeEmployeeShiftTuples; + Tuples enumerationWorkPeriodsSchedulesOfPartTimeEmployees; + Tuples ValidPartTimeEmployeeShiftTuples; public ParametersInitialSchedules() { @@ -52,39 +61,35 @@ public class ParametersInitialSchedules { this.daysPerSchedule = 14; this.hoursPerWorkPeriod = 24 / this.workPeriodsPerDay; this.workPeriodsPerSchedule = this.workPeriodsPerDay * this.daysPerSchedule; + this.workingHoursPaidAtRegularHourlyRatePerSchedule = 80; + this.workingHoursPaidAtRegularHourlyRatePerShiftWork = 8; } private void setPartTimeEmployeesParameters() { this.fixedCostOfPartTimeEmployeesPerSchedule = 50; - this.hourlyRateOfPartTimeEmployees = 12; // To simulate lower productivity + this.regularHourlyRateOfPartTimeEmployees = 12; // To simulate lower productivity + this.overtimeHourlyRateOfPartTimeEmployees = 17; // To simulate lower productivity this.minWorkingHoursOfPartTimeEmployeesPerSchedule = 32; this.maxWorkingHoursOfPartTimeEmployeesPerSchedule = 64; - this.minWorkingPeriodsOfPartTimeEmployeesPerSchedule - = (int) (this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); - this.maxWorkingPeriodsOfPartTimeEmployeesPerSchedule - = (int) (this.maxWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); + this.maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork = 12; + this.minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees = 12; } private void setFullTimeEmployeesParameters() { this.fixedCostOfFullTimeEmployeesPerSchedule = 50; this.regularHourlyRateOfFullTimeEmployees = 10; this.overtimeHourlyRateOfFullTimeEmployees = 15; - this.workingHoursOfFullTimeEmployeesPerSchedule = 80; this.maxWorkingHoursOfFullTimeEmployeesPerSchedule = 120; - this.workingPeriodsOfFullTimeEmployeesPerSchedule - = (int) (this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); - this.maxWorkingPeriodsOfFullTimeEmployeesPerSchedule - = (int) (this.maxWorkingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); - - this.workingHoursPaidAtRegularHourlyRatePerSchedule = 80; + this.maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork = 12; + this.minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees = 12; } private void setRequiredWorkforce() { this.requiredWorkforce = new int[this.daysPerSchedule * this.workPeriodsPerDay]; this.totalWorkedPeriodsInSchedule = 0; - int[] dailyRequiredWorkforce = new int[]{2, 2, 3, 3, 1, 1}; + int[] dailyRequiredWorkforce = new int[]{2, 2, 4, 4, 3, 3}; for (int day = 0; day < this.daysPerSchedule; day++) { for(int shift = 0; shift < this.workPeriodsPerDay; shift++) { this.requiredWorkforce[day * this.workPeriodsPerDay + shift] = dailyRequiredWorkforce[shift]; @@ -278,6 +283,63 @@ public class ParametersInitialSchedules { this.ValidPartTimeEmployeeShiftTuples = new ValidPartTimeEmployeeShift().makeTuples(); } + public int getWorkingPeriodsPaidAtRegularHourlyRatePerSchedule () { + return (int) (workingHoursPaidAtRegularHourlyRatePerSchedule / this.hoursPerWorkPeriod); + } + + public int getWorkingPeriodsPaidAtRegularHourlyRatePerShiftWork () { + return (int) (workingHoursPaidAtRegularHourlyRatePerShiftWork / this.hoursPerWorkPeriod); + } + + public int getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate () { + return (int) (regularHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod); + } + + public int getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate () { + return (int) (regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod); + } + + public int getWorkingPeriodCostOfPartTimeEmployeesPaidAtOvertimeHourlyRate () { + return (int) (overtimeHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod); + } + + public int getWorkingPeriodCostOfFullTimeEmployeesPaidAtOvertimeHourlyRate () { + return (int) (overtimeHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod); + } + + public int getMaxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork () { + return (int) (maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod); + } + + public int getMaxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork () { + return (int) (maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod); + } + + public int getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees () { + return (int) (minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees / this.hoursPerWorkPeriod); + } + + public int getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees () { + return (int) (minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees / this.hoursPerWorkPeriod); + } + + public int getMaxWorkingPeriodsOfPartTimeEmployeesPerSchedule () { + return (int) (this.maxWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); + } + + public int getMaxWorkingPeriodsOfFullTimeEmployeesPerSchedule () { + return (int) (this.maxWorkingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); + } + + public int getMinWorkingPeriodsOfPartTimeEmployeesPerSchedule () { + return (int) (this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); + + } + + public int getWorkingPeriodsOfFullTimeEmployeesPerSchedule () { + return (int) (this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod); + } + // A implementer plus tard si l'on veut travailler avec des fichiers texte public ParametersInitialSchedules(String fileName) { diff --git a/Travail_de_session/MainClass.java b/Travail_de_session/MainClass.java index 2926276..09fae77 100644 --- a/Travail_de_session/MainClass.java +++ b/Travail_de_session/MainClass.java @@ -23,7 +23,7 @@ public class MainClass { List absenceSchedulesArrayList = GenerateAbsencesSchedules(initialSchedulesArrayList); - List recoveredSchedulesArrayList = GenerateRecoveredSchedules(absenceSchedulesArrayList); + List recoveredSchedulesArrayList = GenerateOptimalRecoveredSchedules(absenceSchedulesArrayList); // Algo de recouvrement d'absences. Faire un nouveau package de fonctions. // Trouver meilleure solution et l'afficher. } @@ -90,11 +90,11 @@ public class MainClass { return absenceSchedulesArrayList; } - private static List GenerateRecoveredSchedules(List absenceSchedulesArrayList) { + private static List GenerateOptimalRecoveredSchedules(List absenceSchedulesArrayList) { List recoveredSchedulesArrayList = new ArrayList<>(); for (SchedulesArray absenceSchedule : absenceSchedulesArrayList) { - RecoveredSchedulesArray recoveredSchedule = new RecoveredSchedulesArray(absenceSchedule); + RecoveredSchedulesArray recoveredSchedule = new RecoveredSchedulesArray((AbsenceSchedulesArray) absenceSchedule); recoveredSchedule.recoverAbsenceScheduleOptimally(); recoveredSchedulesArrayList.add(recoveredSchedule); } diff --git a/Travail_de_session/ScheduleUtil/EmployeeCostCalculator.java b/Travail_de_session/ScheduleUtil/EmployeeCostCalculator.java new file mode 100644 index 0000000..fdc0c92 --- /dev/null +++ b/Travail_de_session/ScheduleUtil/EmployeeCostCalculator.java @@ -0,0 +1,89 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package ScheduleUtil; + +import InitialSchedules.ParametersInitialSchedules; +import SchedulesRecovery.*; +/** + * + * @author frabe + */ +public class EmployeeCostCalculator { + + public static int getFullScheduleCost( boolean[][] partTimeEmployeesSchedule , boolean[][] fullTimeEmployeesSchedule, ParametersInitialSchedules myScheduleParameters) { + return 0; + } + + public static int getRecoveringActionCost (RecoveringAction action, ParametersInitialSchedules myScheduleParameters) { + int actionCost = 0; + if (action.getClass().getName() == "RecoveringActionPartTimeEmployee") { + actionCost = getPartTimeEmployeeCost(action.employeeScheduleAfterRecoveringAction, myScheduleParameters) - + getPartTimeEmployeeCost(action.employeeScheduleBeforeRecoveringAction, myScheduleParameters); + } else if (action.getClass().getName() == "RecoveringActionFullTimeEmployee") { + actionCost = getFullTimeEmployeeCost(action.employeeScheduleAfterRecoveringAction, myScheduleParameters) - + getFullTimeEmployeeCost(action.employeeScheduleBeforeRecoveringAction, myScheduleParameters); + } + return actionCost; + } + + public static int getPartTimeEmployeeCost( boolean[] employeeSchedule, ParametersInitialSchedules myScheduleParameters) { + + int consecutiveWorkingPeriods = 0; + int overtimeWorkingPeriods = 0; + int totalWorkingPeriods = 0; + for (int workPeriod = 0; workPeriod < employeeSchedule.length ; workPeriod++) { + if (employeeSchedule[workPeriod]) { + totalWorkingPeriods += 1; + consecutiveWorkingPeriods += 1; + if (consecutiveWorkingPeriods > myScheduleParameters.getWorkingPeriodsPaidAtRegularHourlyRatePerShiftWork()) { + overtimeWorkingPeriods += 1; + } + } else { + consecutiveWorkingPeriods = 0; + } + } + + int additionalOvertimeWorkingPeriods = totalWorkingPeriods - myScheduleParameters.getWorkingPeriodsPaidAtRegularHourlyRatePerSchedule(); + if ( additionalOvertimeWorkingPeriods > 0 ){ + overtimeWorkingPeriods += additionalOvertimeWorkingPeriods; + } + + int employeeCost = myScheduleParameters.fixedCostOfPartTimeEmployeesPerSchedule + + overtimeWorkingPeriods * myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtOvertimeHourlyRate() + + (totalWorkingPeriods - overtimeWorkingPeriods) * myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate(); + + return employeeCost; + } + + public static int getFullTimeEmployeeCost( boolean[] employeeSchedule, ParametersInitialSchedules myScheduleParameters) { + + int consecutiveWorkingPeriods = 0; + int overtimeWorkingPeriods = 0; + int totalWorkingPeriods = 0; + for (int workPeriod = 0; workPeriod < employeeSchedule.length ; workPeriod++) { + if (employeeSchedule[workPeriod]) { + totalWorkingPeriods += 1; + consecutiveWorkingPeriods += 1; + if (consecutiveWorkingPeriods > myScheduleParameters.getWorkingPeriodsPaidAtRegularHourlyRatePerShiftWork()) { + overtimeWorkingPeriods += 1; + } + } else { + consecutiveWorkingPeriods = 0; + } + } + + int additionalOvertimeWorkingPeriods = totalWorkingPeriods - myScheduleParameters.getWorkingPeriodsPaidAtRegularHourlyRatePerSchedule(); + if ( additionalOvertimeWorkingPeriods > 0 ){ + overtimeWorkingPeriods += additionalOvertimeWorkingPeriods; + } + + int employeeCost = myScheduleParameters.fixedCostOfFullTimeEmployeesPerSchedule + + overtimeWorkingPeriods * myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtOvertimeHourlyRate() + + (totalWorkingPeriods - overtimeWorkingPeriods) * myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate(); + + return employeeCost; + } +} diff --git a/Travail_de_session/ScheduleUtil/SchedulesArray.java b/Travail_de_session/ScheduleUtil/SchedulesArray.java index f62217a..666f53a 100644 --- a/Travail_de_session/ScheduleUtil/SchedulesArray.java +++ b/Travail_de_session/ScheduleUtil/SchedulesArray.java @@ -17,11 +17,15 @@ import org.chocosolver.solver.Solution; */ public class SchedulesArray { - protected int[][] PartTimeSchedules; - protected int[][] FullTimeSchedules; + protected boolean[][] initialPartTimeSchedules; + protected boolean[][] initialFullTimeSchedules; + protected boolean[][] partTimeSchedules; + protected boolean[][] fullTimeSchedules; protected int[] employeesPerWorkPeriod; protected int[] workingPeriodsPerPartTimeEmployees; protected int[] workingPeriodsPerFullTimeEmployees; + protected boolean[] isPartTimeEmployeeActive; + protected boolean[] isFullTimeEmployeeActive; protected int maxPartTimeEmployee; protected int maxFullTimeEmployee; protected int workPeriodsPerSchedule; @@ -43,30 +47,51 @@ public class SchedulesArray { this.daysPerSchedule = myScheduleArray.daysPerSchedule; this.myModelInitialSchedules = myScheduleArray.myModelInitialSchedules; - this.PartTimeSchedules = new int[this.maxPartTimeEmployee][this.workPeriodsPerSchedule]; - this.FullTimeSchedules = new int[this.maxFullTimeEmployee][this.workPeriodsPerSchedule]; - for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { - for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { - this.PartTimeSchedules[employee][workPeriod] = myScheduleArray.PartTimeSchedules[employee][workPeriod]; - } + this.isPartTimeEmployeeActive = new boolean[this.maxPartTimeEmployee]; + for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { + this.isPartTimeEmployeeActive[employee] = myScheduleArray.isPartTimeEmployeeActive[employee]; } - - for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { - for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { - this.FullTimeSchedules[employee][workPeriod] = myScheduleArray.FullTimeSchedules[employee][workPeriod]; - } + + this.isFullTimeEmployeeActive = new boolean[this.maxFullTimeEmployee]; + for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { + this.isFullTimeEmployeeActive[employee] = myScheduleArray.isFullTimeEmployeeActive[employee]; } + this.partTimeSchedules = deepCopyPartTimeEmployeesSchedule(myScheduleArray.partTimeSchedules); + this.initialPartTimeSchedules = deepCopyPartTimeEmployeesSchedule(myScheduleArray.initialPartTimeSchedules); + this.fullTimeSchedules = deepCopyFullTimeEmployeesSchedule(myScheduleArray.fullTimeSchedules); + this.initialFullTimeSchedules = deepCopyFullTimeEmployeesSchedule(myScheduleArray.initialFullTimeSchedules); + this.employeesPerWorkPeriod = new int[this.workPeriodsPerSchedule]; this.workingPeriodsPerPartTimeEmployees = new int[this.maxPartTimeEmployee]; this.workingPeriodsPerFullTimeEmployees = new int[this.maxFullTimeEmployee]; - updateEmployeesPerWorkPeriod(); - updateWorkingPeriodsPerPartTimeEmployees(); - updateWorkingPeriodsPerFullTimeEmployees(); + updateAllEmployeesPerWorkPeriod(); + updateAllWorkingPeriodsPerPartTimeEmployees(); + updateAllWorkingPeriodsPerFullTimeEmployees(); } + protected boolean[][] deepCopyPartTimeEmployeesSchedule(boolean[][] partTimeSchedules) { + boolean[][] copyPartTimeSchedules = new boolean[this.maxPartTimeEmployee][this.workPeriodsPerSchedule]; + for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { + for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { + copyPartTimeSchedules[employee][workPeriod] = partTimeSchedules[employee][workPeriod]; + } + } + return copyPartTimeSchedules; + } + + protected boolean[][] deepCopyFullTimeEmployeesSchedule(boolean[][] fullTimeSchedules) { + boolean[][] copyFullTimeSchedules = new boolean[this.maxFullTimeEmployee][this.workPeriodsPerSchedule]; + for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { + for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { + copyFullTimeSchedules[employee][workPeriod] = fullTimeSchedules[employee][workPeriod]; + } + } + return copyFullTimeSchedules; + } + public SchedulesArray(ModelInitialSchedules m, Solution s) { this.myModelInitialSchedules = m; Solution mySolution = s; @@ -76,17 +101,35 @@ public class SchedulesArray { this.workPeriodsPerDay = myModelInitialSchedules.myScheduleParameters.workPeriodsPerDay; this.daysPerSchedule = myModelInitialSchedules.myScheduleParameters.daysPerSchedule; - this.PartTimeSchedules = new int[this.maxPartTimeEmployee][this.workPeriodsPerSchedule]; - this.FullTimeSchedules = new int[this.maxFullTimeEmployee][this.workPeriodsPerSchedule]; + this.isPartTimeEmployeeActive = new boolean[this.maxPartTimeEmployee]; + for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { + if (mySolution.getIntVal(myModelInitialSchedules.workingPeriodsPerPartTimeEmployees[employee]) > 0){ + this.isPartTimeEmployeeActive[employee] = true; + } + } + + this.isFullTimeEmployeeActive = new boolean[this.maxFullTimeEmployee]; + for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { + if (mySolution.getIntVal(myModelInitialSchedules.workingPeriodsPerFullTimeEmployees[employee]) > 0){ + this.isFullTimeEmployeeActive[employee] = true; + } + } + + this.partTimeSchedules = new boolean[this.maxPartTimeEmployee][this.workPeriodsPerSchedule]; + this.fullTimeSchedules = new boolean[this.maxFullTimeEmployee][this.workPeriodsPerSchedule]; + this.initialPartTimeSchedules = new boolean[this.maxPartTimeEmployee][this.workPeriodsPerSchedule]; + this.initialFullTimeSchedules = new boolean[this.maxFullTimeEmployee][this.workPeriodsPerSchedule]; for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { - this.PartTimeSchedules[employee][workPeriod] = mySolution.getIntVal(myModelInitialSchedules.workPeriodsSchedulesOfPartTimeEmployees[employee][workPeriod]); + this.partTimeSchedules[employee][workPeriod] = mySolution.getIntVal(myModelInitialSchedules.workPeriodsSchedulesOfPartTimeEmployees[employee][workPeriod]) == 1; + this.initialPartTimeSchedules[employee][workPeriod] = mySolution.getIntVal(myModelInitialSchedules.workPeriodsSchedulesOfPartTimeEmployees[employee][workPeriod]) == 1; } } for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { - this.FullTimeSchedules[employee][workPeriod] = mySolution.getIntVal(myModelInitialSchedules.workPeriodsSchedulesOfFullTimeEmployees[employee][workPeriod]); + this.fullTimeSchedules[employee][workPeriod] = mySolution.getIntVal(myModelInitialSchedules.workPeriodsSchedulesOfFullTimeEmployees[employee][workPeriod]) == 1; + this.initialFullTimeSchedules[employee][workPeriod] = mySolution.getIntVal(myModelInitialSchedules.workPeriodsSchedulesOfFullTimeEmployees[employee][workPeriod]) == 1; } } @@ -94,42 +137,52 @@ public class SchedulesArray { this.workingPeriodsPerPartTimeEmployees = new int[this.maxPartTimeEmployee]; this.workingPeriodsPerFullTimeEmployees = new int[this.maxFullTimeEmployee]; - updateEmployeesPerWorkPeriod(); - updateWorkingPeriodsPerPartTimeEmployees(); - updateWorkingPeriodsPerFullTimeEmployees(); + updateAllEmployeesPerWorkPeriod(); + updateAllWorkingPeriodsPerPartTimeEmployees(); + updateAllWorkingPeriodsPerFullTimeEmployees(); } - protected void updateEmployeesPerWorkPeriod() { + protected void updateAllEmployeesPerWorkPeriod() { for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { - this.employeesPerWorkPeriod[workPeriod] = 0; - for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { - this.employeesPerWorkPeriod[workPeriod] += this.PartTimeSchedules[employee][workPeriod]; - } - for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { - this.employeesPerWorkPeriod[workPeriod] += this.FullTimeSchedules[employee][workPeriod]; - } + updateEmployeesPerWorkPeriod(workPeriod); } } - protected void updateWorkingPeriodsPerPartTimeEmployees() { - + protected void updateEmployeesPerWorkPeriod(int workPeriod) { + this.employeesPerWorkPeriod[workPeriod] = 0; for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { - this.workingPeriodsPerPartTimeEmployees[employee] = 0; - for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { - this.workingPeriodsPerPartTimeEmployees[employee] += this.PartTimeSchedules[employee][workPeriod]; - } + if (this.partTimeSchedules[employee][workPeriod]) {this.employeesPerWorkPeriod[workPeriod] += 1;} + } + for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { + if (this.fullTimeSchedules[employee][workPeriod]) {this.employeesPerWorkPeriod[workPeriod] += 1;} } } - protected void updateWorkingPeriodsPerFullTimeEmployees() { - + protected void updateAllWorkingPeriodsPerPartTimeEmployees() { + for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) { + updateWorkingPeriodsPerPartTimeEmployees(employee); + } + } + + protected void updateWorkingPeriodsPerPartTimeEmployees(int employee) { + this.workingPeriodsPerPartTimeEmployees[employee] = 0; + for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { + if (this.partTimeSchedules[employee][workPeriod]) {this.workingPeriodsPerPartTimeEmployees[employee] += 1;} + } + } + + protected void updateAllWorkingPeriodsPerFullTimeEmployees() { for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) { - this.workingPeriodsPerFullTimeEmployees[employee] = 0; - for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { - this.workingPeriodsPerFullTimeEmployees[employee] += this.FullTimeSchedules[employee][workPeriod]; - } + updateWorkingPeriodsPerFullTimeEmployees(employee); + } + } + + protected void updateWorkingPeriodsPerFullTimeEmployees(int employee) { + this.workingPeriodsPerFullTimeEmployees[employee] = 0; + for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) { + if (this.fullTimeSchedules[employee][workPeriod]) {this.workingPeriodsPerFullTimeEmployees[employee] += 1;} } } @@ -153,20 +206,28 @@ public class SchedulesArray { return workPeriodsPerDay; } - public int[][] getFullTimeSchedules() { - return FullTimeSchedules; + public boolean[][] getFullTimeSchedules() { + return fullTimeSchedules; } - public int[][] getPartTimeSchedules() { - return PartTimeSchedules; + public boolean[][] getPartTimeSchedules() { + return partTimeSchedules; } public boolean isPartTimeEmployeeWorking(int employee, int workPeriod) { - return PartTimeSchedules[employee][workPeriod] == 1; + return partTimeSchedules[employee][workPeriod] == true; } public boolean isFullTimeEmployeeWorking(int employee, int workPeriod) { - return FullTimeSchedules[employee][workPeriod] == 1; + return fullTimeSchedules[employee][workPeriod] == true; + } + + public boolean isPartTimeEmployeeActive(int employee) { + return isPartTimeEmployeeActive[employee] == true; + } + + public boolean isFullTimeEmployeeActive(int employee) { + return isFullTimeEmployeeActive[employee] == true; } public int getRequiredWorkForce(int workPeriod) { diff --git a/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java b/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java index 916137d..2ea3241 100644 --- a/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java +++ b/Travail_de_session/SchedulesRecovery/RecoveredSchedulesArray.java @@ -6,7 +6,9 @@ package SchedulesRecovery; import AbsenceSchedules.AbsenceSchedulesArray; -import ScheduleUtil.SchedulesArray; +import java.util.*; +import org.javatuples.Triplet; +import ScheduleUtil.*; /** * @@ -14,11 +16,248 @@ import ScheduleUtil.SchedulesArray; */ public class RecoveredSchedulesArray extends AbsenceSchedulesArray{ - public RecoveredSchedulesArray(SchedulesArray myScheduleArray){ - super(myScheduleArray); + public RecoveredSchedulesArray(AbsenceSchedulesArray myAbsenceScheduleArray){ + super(myAbsenceScheduleArray); } +// public void oldRecoverAbsenceScheduleOptimally() { +// for ( int workPeriod = 0 ; workPeriod < this.workPeriodsPerSchedule ; workPeriod++ ) { +// boolean noEmployeeAvailable = false; +// while (!noEmployeeAvailable && getEmployeesPerWorkPeriod(workPeriod) < getRequiredWorkForce(workPeriod)) { +// boolean absenceRecoveryDone = false; +// int employee = 0; +// while (!absenceRecoveryDone && employee < this.maxFullTimeEmployee) { +// if ( isFullTimeEmployeeAvailableForAbsenceRecovering(employee, workPeriod) ){ +// fullTimeSchedules[employee][workPeriod] = true; +// updateEmployeesPerWorkPeriod(workPeriod); +// updateWorkingPeriodsPerFullTimeEmployees(employee); +// absenceRecoveryDone = true; +// } +// employee++; +// } +// employee = 0; +// while (!absenceRecoveryDone && employee < this.maxPartTimeEmployee) { +// if (isPartTimeEmployeeAvailableForAbsenceRecovering(employee, workPeriod) ){ +// partTimeSchedules[employee][workPeriod] = true; +// updateEmployeesPerWorkPeriod(workPeriod); +// updateWorkingPeriodsPerPartTimeEmployees(employee); +// absenceRecoveryDone = true; +// } +// employee++; +// } +// if (!absenceRecoveryDone) { +// noEmployeeAvailable = true; +// } +// } +// } +// +// } + public void recoverAbsenceScheduleOptimally() { + int workPeriod = 0; + boolean[][] currentRecoveredScheduleOfPartTimeEmployees = deepCopyPartTimeEmployeesSchedule(partTimeSchedules); + boolean[][] currentRecoveredScheduleOfFullTimeEmployees = deepCopyFullTimeEmployeesSchedule(fullTimeSchedules); + int totalEmployeesCost = EmployeeCostCalculator.getFullScheduleCost(currentRecoveredScheduleOfPartTimeEmployees, currentRecoveredScheduleOfFullTimeEmployees, this.myModelInitialSchedules.myScheduleParameters); + int currentTotalEmployeesCost = totalEmployeesCost; + ScheduleStateComparator totalCostComparator = new ScheduleStateComparator(); + // mettre les Schedules dans les Tuples currentRecoveredScheduleOfPartTimeEmployees et currentRecoveredScheduleOfFullTimeEmployees au lieu de previousActions + PriorityQueue< Triplet > priorityQueueScheduleStatesOrderedByTotalCost = new PriorityQueue<>(totalCostComparator); + List< Triplet > listVisitedScheduleStates = new ArrayList<>(); + RecoveringAction currentRecoveringAction = null; + RecoveringAction previousRecoveringAction = null; + while ( workPeriod < this.workPeriodsPerSchedule ) { + + Stack stackRecoveringActionsOfPartTimeEmployee = + getPossibleActionOfPartTimeEmployees(workPeriod, currentRecoveredScheduleOfPartTimeEmployees); + Stack stackRecoveringActionsOfFullTimeEmployees = + getPossibleActionOfFullTimeEmployees(workPeriod, currentRecoveredScheduleOfFullTimeEmployees); + while ( !stackRecoveringActionsOfPartTimeEmployee.isEmpty() && !stackRecoveringActionsOfFullTimeEmployees.isEmpty() ) { + if (stackRecoveringActionsOfPartTimeEmployee.isEmpty()) { + currentRecoveringAction = stackRecoveringActionsOfFullTimeEmployees.pop(); + } else { + currentRecoveringAction = stackRecoveringActionsOfPartTimeEmployee.pop(); + } + + // On pourrait comparer currentRecoveredScheduleOfPartTimeEmployees pour voir si on ne l'a pas deja visite avec un coût plus faible. Dans ce cas, on ne pousse pas l'etat dans la liste. + int actionCost = EmployeeCostCalculator.getRecoveringActionCost( currentRecoveringAction, this.myModelInitialSchedules.myScheduleParameters ); + totalEmployeesCost = currentTotalEmployeesCost + actionCost; + Triplet scheduleState = Triplet.with(previousRecoveringAction, currentRecoveringAction, totalEmployeesCost); + priorityQueueScheduleStatesOrderedByTotalCost.add(scheduleState); + listVisitedScheduleStates.add(scheduleState); + } + + Triplet currentScheduleState = priorityQueueScheduleStatesOrderedByTotalCost.poll(); + currentTotalEmployeesCost = currentScheduleState.getValue2(); + previousRecoveringAction = currentScheduleState.getValue1(); + + //recalculer les currentRecoveredScheduleOfPartTimeEmployees et ajuster la workPeriod + //en trouvent la workPeriod la plus petite avec une demande incomplète. + //workPeriod++; + } + + } + + private Stack getPossibleActionOfPartTimeEmployees(int workPeriod, boolean[][] currentRecoveredSchedule) { + // inclure un attribut pour dire si la requiredWorkForce est satifaite avec l'action. + Stack stackRecoveringActionsOfPartTimeEmployee = new Stack<>(); + for (int employee = 0 ; employee < this.maxPartTimeEmployee ; employee++) { + boolean[] currentEmployeeSchedule = currentRecoveredSchedule[employee]; + if ( isPartTimeEmployeeActive(employee) && isPartTimeEmployeeAvailableForAbsenceRecovering(employee, workPeriod, currentEmployeeSchedule) ){ + RecoveringActionPartTimeEmployee recoveringAction = + new RecoveringActionPartTimeEmployee(employee, workPeriod, currentEmployeeSchedule); + stackRecoveringActionsOfPartTimeEmployee.push(recoveringAction); + } + } + return stackRecoveringActionsOfPartTimeEmployee; + } + + private Stack getPossibleActionOfFullTimeEmployees(int workPeriod, boolean[][] currentRecoveredSchedule) { + + Stack stackRecoveringActionsOfFullTimeEmployees = new Stack<>(); + for (int employee = 0 ; employee < this.maxFullTimeEmployee ; employee++) { + boolean[] currentEmployeeSchedule = currentRecoveredSchedule[employee]; + if ( isFullTimeEmployeeActive(employee) && isFullTimeEmployeeAvailableForAbsenceRecovering(employee, workPeriod, currentEmployeeSchedule) ){ + RecoveringActionFullTimeEmployee recoveringAction = + new RecoveringActionFullTimeEmployee(employee, workPeriod, currentEmployeeSchedule); + stackRecoveringActionsOfFullTimeEmployees.push(recoveringAction); + } + } + return stackRecoveringActionsOfFullTimeEmployees; + } + + private boolean isPartTimeEmployeeAvailableForAbsenceRecovering(int employee, int workPeriod, boolean[] currentEmployeeSchedule){ + return !currentEmployeeSchedule[workPeriod] && !isPartTimeEmployeeAbsent(employee, workPeriod) && isValidPartTimeEmployeeWorkPeriod(currentEmployeeSchedule, workPeriod); + } + + private boolean isValidPartTimeEmployeeWorkPeriod(boolean[] currentEmployeeSchedule, int workPeriod){ + return isValidWorkingPeriodsOfPartTimeEmployeePerSchedule(currentEmployeeSchedule) && + isValidConsecutiveWorkingPeriodsOfPartTimeEmployee(currentEmployeeSchedule, workPeriod) && + isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployee(currentEmployeeSchedule, workPeriod); + } + + private boolean isValidWorkingPeriodsOfPartTimeEmployeePerSchedule(boolean[] currentEmployeeSchedule){ + int employeeWorkingPeriods = 0; + for ( int workPeriod = 0 ; workPeriod < this.workPeriodsPerSchedule ; workPeriod++ ) { + if (currentEmployeeSchedule[workPeriod]){ + employeeWorkingPeriods +=1 ; + } + } + return employeeWorkingPeriods < myModelInitialSchedules.myScheduleParameters.getMaxWorkingPeriodsOfPartTimeEmployeesPerSchedule(); + } + + private boolean isValidConsecutiveWorkingPeriodsOfPartTimeEmployee(boolean[] currentEmployeeSchedule, int workPeriod){ + int consecutiveWorkingPeriods = 1; + int compteurWorkPeriod = workPeriod - 1; + while ( compteurWorkPeriod >= 0 && currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutiveWorkingPeriods += 1; + compteurWorkPeriod--; + } + compteurWorkPeriod = workPeriod + 1; + while ( compteurWorkPeriod < this.workPeriodsPerSchedule && currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutiveWorkingPeriods += 1; + compteurWorkPeriod++; + } + return consecutiveWorkingPeriods <= myModelInitialSchedules.myScheduleParameters.getMaxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork(); + } + + private boolean isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployee(boolean[] currentEmployeeSchedule, int workPeriod){ + int consecutivePreviousNonWorkingPeriods = 0; + int compteurWorkPeriod = workPeriod - 1; + while ( compteurWorkPeriod >= 0 && !currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutivePreviousNonWorkingPeriods += 1; + compteurWorkPeriod--; + } + boolean validConsecutivePreviousNonWorkingPeriods = false; + if (compteurWorkPeriod == -1) { + validConsecutivePreviousNonWorkingPeriods = true; + } else if (consecutivePreviousNonWorkingPeriods == 0) { + validConsecutivePreviousNonWorkingPeriods = true; + } else if (consecutivePreviousNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees()) { + validConsecutivePreviousNonWorkingPeriods = true; + } + int consecutiveNextNonWorkingPeriods = 0; + compteurWorkPeriod = workPeriod + 1; + while ( compteurWorkPeriod < this.workPeriodsPerSchedule && !currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutiveNextNonWorkingPeriods += 1; + compteurWorkPeriod++; + } + boolean validConsecutiveNextNonWorkingPeriods = false; + if (compteurWorkPeriod == workPeriodsPerSchedule) { + validConsecutiveNextNonWorkingPeriods = true; + } else if (consecutiveNextNonWorkingPeriods == 0) { + validConsecutiveNextNonWorkingPeriods = true; + } else if (consecutiveNextNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees()) { + validConsecutiveNextNonWorkingPeriods = true; + } + return validConsecutivePreviousNonWorkingPeriods && validConsecutiveNextNonWorkingPeriods; + } + + private boolean isFullTimeEmployeeAvailableForAbsenceRecovering(int employee, int workPeriod, boolean[] currentEmployeeSchedule){ + return !currentEmployeeSchedule[workPeriod] && !isFullTimeEmployeeAbsent(employee, workPeriod) && isValidFullTimeEmployeeWorkPeriod(currentEmployeeSchedule, workPeriod); + } + + private boolean isValidFullTimeEmployeeWorkPeriod(boolean[] currentEmployeeSchedule, int workPeriod){ + return isValidWorkingPeriodsOfFullTimeEmployeePerSchedule(currentEmployeeSchedule) && + isValidConsecutiveWorkingPeriodsOfFullTimeEmployee(currentEmployeeSchedule, workPeriod) && + isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployee(currentEmployeeSchedule, workPeriod); + } + + private boolean isValidWorkingPeriodsOfFullTimeEmployeePerSchedule(boolean[] currentEmployeeSchedule){ + int employeeWorkingPeriods = 0; + for ( int workPeriod = 0 ; workPeriod < this.workPeriodsPerSchedule ; workPeriod++ ) { + if (currentEmployeeSchedule[workPeriod]){ + employeeWorkingPeriods +=1 ; + } + } + return employeeWorkingPeriods < myModelInitialSchedules.myScheduleParameters.getMaxWorkingPeriodsOfFullTimeEmployeesPerSchedule(); + } + + + private boolean isValidConsecutiveWorkingPeriodsOfFullTimeEmployee(boolean[] currentEmployeeSchedule, int workPeriod){ + int consecutiveWorkingPeriods = 1; + int compteurWorkPeriod = workPeriod - 1; + while ( compteurWorkPeriod >= 0 && currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutiveWorkingPeriods += 1; + compteurWorkPeriod--; + } + compteurWorkPeriod = workPeriod + 1; + while ( compteurWorkPeriod < this.workPeriodsPerSchedule && currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutiveWorkingPeriods += 1; + compteurWorkPeriod++; + } + return consecutiveWorkingPeriods <= myModelInitialSchedules.myScheduleParameters.getMaxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork(); + } + + private boolean isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployee(boolean[] currentEmployeeSchedule, int workPeriod){ + int consecutivePreviousNonWorkingPeriods = 0; + int compteurWorkPeriod = workPeriod - 1; + while ( compteurWorkPeriod >= 0 && !currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutivePreviousNonWorkingPeriods += 1; + compteurWorkPeriod--; + } + boolean validConsecutivePreviousNonWorkingPeriods = false; + if (compteurWorkPeriod == -1) { + validConsecutivePreviousNonWorkingPeriods = true; + } else if (consecutivePreviousNonWorkingPeriods == 0) { + validConsecutivePreviousNonWorkingPeriods = true; + } else if (consecutivePreviousNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees()) { + validConsecutivePreviousNonWorkingPeriods = true; + } + int consecutiveNextNonWorkingPeriods = 0; + compteurWorkPeriod = workPeriod + 1; + while ( compteurWorkPeriod < this.workPeriodsPerSchedule && !currentEmployeeSchedule[compteurWorkPeriod] ){ + consecutiveNextNonWorkingPeriods += 1; + compteurWorkPeriod++; + } + boolean validConsecutiveNextNonWorkingPeriods = false; + if (compteurWorkPeriod == workPeriodsPerSchedule) { + validConsecutiveNextNonWorkingPeriods = true; + } else if (consecutiveNextNonWorkingPeriods == 0) { + validConsecutiveNextNonWorkingPeriods = true; + } else if (consecutiveNextNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees()) { + validConsecutiveNextNonWorkingPeriods = true; + } + return validConsecutivePreviousNonWorkingPeriods && validConsecutiveNextNonWorkingPeriods; } } diff --git a/Travail_de_session/SchedulesRecovery/RecoveringAction.java b/Travail_de_session/SchedulesRecovery/RecoveringAction.java new file mode 100644 index 0000000..48ff6c9 --- /dev/null +++ b/Travail_de_session/SchedulesRecovery/RecoveringAction.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package SchedulesRecovery; + +/** + * + * @author frabe + */ +public class RecoveringAction { + public int employee; + public int workPeriod; + public boolean[] employeeScheduleBeforeRecoveringAction; + public boolean[] employeeScheduleAfterRecoveringAction; + + public RecoveringAction( int employee, int workPeriod, boolean[] employeeSchedule){ + this.employee = employee; + this.workPeriod = workPeriod; + this.employeeScheduleBeforeRecoveringAction = new boolean[employeeSchedule.length]; + this.employeeScheduleAfterRecoveringAction = new boolean[employeeSchedule.length]; + for (int i = 0 ; i < employeeSchedule.length ; i++) { + this.employeeScheduleBeforeRecoveringAction[i] = employeeSchedule[i]; + if (i == workPeriod) { + this.employeeScheduleAfterRecoveringAction[i] = true; + } else { + this.employeeScheduleAfterRecoveringAction[i] = employeeSchedule[i]; + } + } + } + +} diff --git a/Travail_de_session/SchedulesRecovery/RecoveringActionFullTimeEmployee.java b/Travail_de_session/SchedulesRecovery/RecoveringActionFullTimeEmployee.java new file mode 100644 index 0000000..5a4ac25 --- /dev/null +++ b/Travail_de_session/SchedulesRecovery/RecoveringActionFullTimeEmployee.java @@ -0,0 +1,18 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package SchedulesRecovery; + +/** + * + * @author frabe + */ +public class RecoveringActionFullTimeEmployee extends RecoveringAction{ + + public RecoveringActionFullTimeEmployee( int employee, int workPeriod, boolean[] employeeSchedule){ + super(employee, workPeriod, employeeSchedule); + } + +} diff --git a/Travail_de_session/SchedulesRecovery/RecoveringActionPartTimeEmployee.java b/Travail_de_session/SchedulesRecovery/RecoveringActionPartTimeEmployee.java new file mode 100644 index 0000000..4411ee8 --- /dev/null +++ b/Travail_de_session/SchedulesRecovery/RecoveringActionPartTimeEmployee.java @@ -0,0 +1,19 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package SchedulesRecovery; + +/** + * + * @author frabe + */ +public class RecoveringActionPartTimeEmployee extends RecoveringAction{ + + public RecoveringActionPartTimeEmployee( int employee, int workPeriod, boolean[] employeeSchedule){ + super(employee, workPeriod, employeeSchedule); + } + +} + diff --git a/Travail_de_session/SchedulesRecovery/ScheduleStateComparator.java b/Travail_de_session/SchedulesRecovery/ScheduleStateComparator.java new file mode 100644 index 0000000..a8c81e3 --- /dev/null +++ b/Travail_de_session/SchedulesRecovery/ScheduleStateComparator.java @@ -0,0 +1,19 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package SchedulesRecovery; + +import java.util.Comparator; +import org.javatuples.Triplet; + +/** + * + * @author frabe + */ +public class ScheduleStateComparator implements Comparator< Triplet > { + public int compare(Triplet o1, Triplet o2) { + return o1.getValue2().compareTo(o2.getValue2()); + } +} diff --git a/Travail_de_session/javatuples-1.2.jar b/Travail_de_session/javatuples-1.2.jar new file mode 100644 index 0000000..8944308 Binary files /dev/null and b/Travail_de_session/javatuples-1.2.jar differ