Correction de l'algo de recouvrement d'horaire.

This commit is contained in:
Francois Berube\frabe 2018-04-10 23:24:19 -04:00
parent 3ddd68afba
commit c1e82d2af0
5 changed files with 88 additions and 40 deletions

View file

@ -41,9 +41,11 @@ public class SchedulesArray {
}
protected boolean[][] getDeepCopyEmployeesSchedules(boolean[][] schedules) {
boolean[][] copySchedules = new boolean[schedules.length][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
for (int employee = 0; employee < schedules.length; employee++) {
int nbrEmployee = schedules.length;
int nbrWorkPeriod = schedules[0].length;
boolean[][] copySchedules = new boolean[nbrEmployee][nbrWorkPeriod];
for (int workPeriod = 0; workPeriod < nbrWorkPeriod; workPeriod++) {
for (int employee = 0; employee < nbrEmployee; employee++) {
copySchedules[employee][workPeriod] = schedules[employee][workPeriod];
}
}

View file

@ -29,64 +29,79 @@ public class RecoveredSchedulesArray extends SchedulesArray{
boolean[][] currentRecoveredScheduleOfPartTimeEmployees = this.getDeepCopyEmployeesSchedules(this.absenceSchedulesArray.partTimeSchedules);
boolean[][] currentRecoveredScheduleOfFullTimeEmployees = this.getDeepCopyEmployeesSchedules(this.absenceSchedulesArray.fullTimeSchedules);
boolean[][] alreadyRecoveredWorkPeriodByPartTimeEmployees = new boolean[this.getNumberPartTimeEmployee()][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
boolean[][] alreadyRecoveredWorkPeriodByFullTimeEmployees = new boolean[this.getNumberFullTimeEmployee()][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
int totalEmployeesCost = EmployeeCostCalculator.getFullScheduleCost(this.absenceSchedulesArray, myParametersInitialSchedules);
int bestScheduleCost = Integer.MAX_VALUE;
int remainingRecoveringAction = this.absenceSchedulesArray.numberOfRecoveringActionsToPerform;
int currentOptimisticTotalEmployeeCost = totalEmployeesCost + remainingRecoveringAction * myParametersInitialSchedules.getMinimumWorkingPeriodCost();
int optimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost;
boolean[][] alreadyRecoveredWorkPeriodByPartTimeEmployees = new boolean[this.getNumberPartTimeEmployee()][remainingRecoveringAction];
boolean[][] alreadyRecoveredWorkPeriodByFullTimeEmployees = new boolean[this.getNumberFullTimeEmployee()][remainingRecoveringAction];
for (int i = 0 ; i < this.getNumberPartTimeEmployee() ; i++) {
Arrays.fill(alreadyRecoveredWorkPeriodByPartTimeEmployees[i], Boolean.FALSE);
}
for (int i = 0 ; i < this.getNumberFullTimeEmployee() ; i++) {
Arrays.fill(alreadyRecoveredWorkPeriodByFullTimeEmployees[i], Boolean.FALSE);
}
int totalEmployeesCost = EmployeeCostCalculator.getFullScheduleCost(this.absenceSchedulesArray, myParametersInitialSchedules);
int bestScheduleCost = Integer.MAX_VALUE;
int remainingRecoveringAction = this.absenceSchedulesArray.numberOfRecoveringActionsToPerform;
int currentOptimisticTotalEmployeeCost = totalEmployeesCost + remainingRecoveringAction * myParametersInitialSchedules.getMinimumWorkingPeriodCost();
int optimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost;
ScheduleStateComparator quartetComparator = new ScheduleStateComparator();
RecoveringActionComparator recoveringActionCostComparator = new RecoveringActionComparator();
PriorityQueue< Quartet<boolean[][], boolean[][], Integer, Integer> > scheduleStatesOrderedByOptimisticCost = new PriorityQueue<>(quartetComparator);
ScheduleState currentScheduleState = new ScheduleState(currentRecoveredScheduleOfPartTimeEmployees, currentRecoveredScheduleOfFullTimeEmployees,
currentOptimisticTotalEmployeeCost, remainingRecoveringAction);
Stack< ScheduleState > scheduleStatesNodes = new Stack<>();
scheduleStatesNodes.push(currentScheduleState);
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.
int backtrack = 0;
// Fouilles en profondeur avec calcul de cout optimiste base sur le taux horaire regulier des employes a temps plein.
// On marque les noeuds dejà visites.
while ( bestScheduleCost > currentOptimisticTotalEmployeeCost ) {
PriorityQueue<RecoveringAction> recoveringActionsOrderedByCost =
getPossibleRecoveringActions(currentRecoveredScheduleOfPartTimeEmployees, currentRecoveredScheduleOfFullTimeEmployees,
alreadyRecoveredWorkPeriodByPartTimeEmployees, alreadyRecoveredWorkPeriodByFullTimeEmployees, recoveringActionCostComparator);
alreadyRecoveredWorkPeriodByPartTimeEmployees, alreadyRecoveredWorkPeriodByFullTimeEmployees, remainingRecoveringAction, recoveringActionCostComparator);
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;
alreadyRecoveredWorkPeriodByPartTimeEmployees[currentRecoveringAction.employee][remainingRecoveringAction-1] = true;
} else if (currentRecoveringAction.getClass().getName().equals("SchedulesRecovery.RecoveringActionFullTimeEmployee")) {
recoveredScheduleOfFullTimeEmployeesAfterAction[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
alreadyRecoveredWorkPeriodByFullTimeEmployees[currentRecoveringAction.employee][currentRecoveringAction.workPeriod] = true;
alreadyRecoveredWorkPeriodByPartTimeEmployees[currentRecoveringAction.employee][remainingRecoveringAction-1] = true;
}
optimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost - myParametersInitialSchedules.getMinimumWorkingPeriodCost() + currentRecoveringAction.recoveringActionCost;
Quartet<boolean[][], boolean[][], Integer, Integer> scheduleState = Quartet.with
(recoveredScheduleOfPartTimeEmployeesAfterAction, recoveredScheduleOfFullTimeEmployeesAfterAction, optimisticTotalEmployeeCost, remainingRecoveringAction - 1);
scheduleStatesOrderedByOptimisticCost.add(scheduleState);
ScheduleState scheduleState = new ScheduleState(recoveredScheduleOfPartTimeEmployeesAfterAction, recoveredScheduleOfFullTimeEmployeesAfterAction,
optimisticTotalEmployeeCost, remainingRecoveringAction - 1);
scheduleStatesNodes.push(scheduleState);
} else {
do{
scheduleStatesNodes.pop();
} while(scheduleStatesNodes.size() > 1);
}
if (remainingRecoveringAction - 1 == 0){
bestScheduleCost = Math.min(bestScheduleCost, optimisticTotalEmployeeCost);
}
if (scheduleStatesOrderedByOptimisticCost.size() > 0) {
Quartet<boolean[][], boolean[][], Integer, Integer> currentScheduleState = scheduleStatesOrderedByOptimisticCost.poll();
currentRecoveredScheduleOfPartTimeEmployees = currentScheduleState.getValue0();
currentRecoveredScheduleOfFullTimeEmployees = currentScheduleState.getValue1();
currentOptimisticTotalEmployeeCost = currentScheduleState.getValue2();
remainingRecoveringAction = currentScheduleState.getValue3();
if (scheduleStatesNodes.size() > 0) {
currentScheduleState = scheduleStatesNodes.peek();
currentRecoveredScheduleOfPartTimeEmployees = currentScheduleState.currentRecoveredScheduleOfPartTimeEmployees;
currentRecoveredScheduleOfFullTimeEmployees = currentScheduleState.currentRecoveredScheduleOfFullTimeEmployees;
currentOptimisticTotalEmployeeCost = currentScheduleState.currentOptimisticTotalEmployeeCost;
remainingRecoveringAction = currentScheduleState.remainingRecoveringAction;
} else {
isSolutionFound = false;
break;
}
}
if (isSolutionFound) {
this.fullTimeSchedules = currentRecoveredScheduleOfFullTimeEmployees;
this.partTimeSchedules = currentRecoveredScheduleOfPartTimeEmployees;
@ -94,19 +109,18 @@ public class RecoveredSchedulesArray extends SchedulesArray{
assert(this.totalScheduleCost == bestScheduleCost);
} else {
this.totalScheduleCost = Integer.MAX_VALUE;
System.out.println(" No Solution Found ");
}
}
private PriorityQueue<RecoveringAction> getPossibleRecoveringActions(boolean[][] currentPartTimeSchedule, boolean[][] currentFullTimeSchedule, boolean[][] alreadyRecoveredWorkPeriodByPartTimeEmployees, boolean[][] alreadyRecoveredWorkPeriodByFullTimeEmployees, Comparator recoveringActionCostComparator) {
PriorityQueue<RecoveringAction> recoveringActionsOrderedByCost = new PriorityQueue<>(recoveringActionCostComparator);
private PriorityQueue<RecoveringAction> getPossibleRecoveringActions(boolean[][] currentPartTimeSchedule, boolean[][] currentFullTimeSchedule,
boolean[][] alreadyRecoveredWorkPeriodByPartTimeEmployees, boolean[][] alreadyRecoveredWorkPeriodByFullTimeEmployees, int remainingRecoveringAction, Comparator recoveringActionCostComparator) {
PriorityQueue<RecoveringAction> recoveringActionsOrderedByCost = new PriorityQueue<RecoveringAction>(recoveringActionCostComparator);
int workPeriod = findEarlierWorkPeriodToRecover(currentPartTimeSchedule, currentFullTimeSchedule);
if (workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule()) {
for (int partTimeEmployee = 0 ; partTimeEmployee < this.getNumberPartTimeEmployee() ; partTimeEmployee++ ) {
if ( isPartTimeEmployeeAvailableForAbsenceRecovering(currentPartTimeSchedule, partTimeEmployee, workPeriod) && !alreadyRecoveredWorkPeriodByPartTimeEmployees[partTimeEmployee][workPeriod]){
if ( isPartTimeEmployeeAvailableForAbsenceRecovering(currentPartTimeSchedule, partTimeEmployee, workPeriod) && !alreadyRecoveredWorkPeriodByPartTimeEmployees[partTimeEmployee][remainingRecoveringAction-1]){
RecoveringActionPartTimeEmployee recoveringAction =
new RecoveringActionPartTimeEmployee(partTimeEmployee, workPeriod);
recoveringAction.calculateRecoveringActionCost (currentPartTimeSchedule, myParametersInitialSchedules);
@ -114,7 +128,7 @@ public class RecoveredSchedulesArray extends SchedulesArray{
}
}
for (int fullTimeEmployee = 0 ; fullTimeEmployee < this.getNumberFullTimeEmployee() ; fullTimeEmployee++ ) {
if ( isFullTimeEmployeeAvailableForAbsenceRecovering(currentFullTimeSchedule, fullTimeEmployee, workPeriod) && !alreadyRecoveredWorkPeriodByFullTimeEmployees[fullTimeEmployee][workPeriod] ){
if ( isFullTimeEmployeeAvailableForAbsenceRecovering(currentFullTimeSchedule, fullTimeEmployee, workPeriod) && !alreadyRecoveredWorkPeriodByFullTimeEmployees[fullTimeEmployee][remainingRecoveringAction-1] ){
RecoveringActionFullTimeEmployee recoveringAction =
new RecoveringActionFullTimeEmployee(fullTimeEmployee, workPeriod);
recoveringAction.calculateRecoveringActionCost (currentFullTimeSchedule, myParametersInitialSchedules);

View file

@ -17,7 +17,7 @@ public class RecoveringActionComparator implements Comparator< RecoveringAction
if (actionCostCmp !=0) {
return actionCostCmp;
}
int workPeriodCmp = Integer.compare(a1.workPeriod, a2.workPeriod);
int workPeriodCmp = Integer.compare(a1.employee, a2.employee);
return workPeriodCmp;
}

View file

@ -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 ScheduleState {
boolean[][] currentRecoveredScheduleOfPartTimeEmployees;
boolean[][] currentRecoveredScheduleOfFullTimeEmployees;
// boolean[][] currentAlreadyRecoveredWorkPeriodByPartTimeEmployees;
// boolean[][] currentAlreadyRecoveredWorkPeriodByFullTimeEmployees;
int currentOptimisticTotalEmployeeCost;
int remainingRecoveringAction;
public ScheduleState(boolean[][] currentRecoveredScheduleOfPartTimeEmployees, boolean[][] currentRecoveredScheduleOfFullTimeEmployees,
int currentOptimisticTotalEmployeeCost, int remainingRecoveringAction) {
this.currentRecoveredScheduleOfPartTimeEmployees = currentRecoveredScheduleOfPartTimeEmployees;
this.currentRecoveredScheduleOfFullTimeEmployees = currentRecoveredScheduleOfFullTimeEmployees;
// this.currentAlreadyRecoveredWorkPeriodByPartTimeEmployees = currentAlreadyRecoveredWorkPeriodByPartTimeEmployees;
// this.currentAlreadyRecoveredWorkPeriodByFullTimeEmployees = currentAlreadyRecoveredWorkPeriodByFullTimeEmployees;
this.currentOptimisticTotalEmployeeCost = currentOptimisticTotalEmployeeCost;
this.remainingRecoveringAction = remainingRecoveringAction;
}
}

View file

@ -6,19 +6,18 @@
package SchedulesRecovery;
import java.util.Comparator;
import org.javatuples.Quartet;
/**
*
* @author frabe
*/
public class ScheduleStateComparator implements Comparator< Quartet<boolean[][], boolean[][], Integer, Integer> > {
public int compare(Quartet<boolean[][], boolean[][], Integer, Integer> o1, Quartet<boolean[][], boolean[][], Integer, Integer> o2) {
int totalCostCmp = o1.getValue2().compareTo(o2.getValue2());
public class ScheduleStateComparator implements Comparator< ScheduleState > {
public int compare(ScheduleState o1, ScheduleState o2) {
int totalCostCmp = Integer.compare(o1.currentOptimisticTotalEmployeeCost,o2.currentOptimisticTotalEmployeeCost);
if (totalCostCmp !=0) {
return totalCostCmp;
}
int remainingActionsCmp = o2.getValue3().compareTo(o1.getValue3());
int remainingActionsCmp = Integer.compare(o1.remainingRecoveringAction,o2.remainingRecoveringAction);
return remainingActionsCmp;
}
}