Creation des bases de l'algorithmes de recouvrement des horaires avec absences.

TODO : Il reste a trouver le recouvrement qui minimise le cout des employes. Cela nécessite de trouver le coût de l'horaire optimal.
This commit is contained in:
Francois Berube\frabe 2018-04-02 22:51:19 -04:00
parent fb03247b26
commit 466ccdd681
6 changed files with 318 additions and 70 deletions

View file

@ -6,27 +6,57 @@ import jdistlib.rng.RandomEngine;
import org.chocosolver.solver.Solution;
public class AbsenceSchedulesArray extends SchedulesArray{
protected boolean[][] partTimeEmployeeUnavailabilitySchedules;
protected boolean[][] fullTimeEmployeeUnavailabilitySchedules;
public AbsenceSchedulesArray(SchedulesArray myScheduleArray) {
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];
public AbsenceSchedulesArray(AbsenceSchedulesArray myAbsenceScheduleArray) {
super(myAbsenceScheduleArray);
this.partTimeEmployeeUnavailabilitySchedules = new boolean[this.maxPartTimeEmployee][this.workPeriodsPerSchedule];
for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) {
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
this.partTimeEmployeeUnavailabilitySchedules[employee][workPeriod] = myAbsenceScheduleArray.partTimeEmployeeUnavailabilitySchedules[employee][workPeriod];
}
}
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];
this.fullTimeEmployeeUnavailabilitySchedules = new boolean[this.maxFullTimeEmployee][this.workPeriodsPerSchedule];
for (int workPeriod = 0; workPeriod < this.workPeriodsPerSchedule; workPeriod++) {
for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) {
this.fullTimeEmployeeUnavailabilitySchedules[employee][workPeriod] = myAbsenceScheduleArray.fullTimeEmployeeUnavailabilitySchedules[employee][workPeriod];
}
}
updateEmployeesPerWorkPeriod();
updateWorkingPeriodsPerPartTimeEmployees();
updateWorkingPeriodsPerFullTimeEmployees();
}
public void generateAbsences(RandomEngine r) {
this.partTimeEmployeeUnavailabilitySchedules = new boolean[this.maxPartTimeEmployee][this.workPeriodsPerSchedule];
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];
}
}
this.fullTimeEmployeeUnavailabilitySchedules = new boolean[this.maxFullTimeEmployee][this.workPeriodsPerSchedule];
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];
}
}

View file

@ -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.90;
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;
}
}

View file

@ -16,7 +16,9 @@ public class ParametersInitialSchedules {
int minWorkingHoursOfPartTimeEmployeesPerSchedule;
int maxWorkingHoursOfPartTimeEmployeesPerSchedule;
int minWorkingPeriodsOfPartTimeEmployeesPerSchedule;
int maxWorkingPeriodsOfPartTimeEmployeesPerSchedule;
public int maxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork;
public int minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees;
public int maxWorkingPeriodsOfPartTimeEmployeesPerSchedule;
int fixedCostOfFullTimeEmployeesPerSchedule;
int regularHourlyRateOfFullTimeEmployees;
@ -24,7 +26,9 @@ public class ParametersInitialSchedules {
int workingHoursOfFullTimeEmployeesPerSchedule;
int maxWorkingHoursOfFullTimeEmployeesPerSchedule;
int workingPeriodsOfFullTimeEmployeesPerSchedule;
int maxWorkingPeriodsOfFullTimeEmployeesPerSchedule;
public int maxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork;
public int minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees;
public int maxWorkingPeriodsOfFullTimeEmployeesPerSchedule;
int workingHoursPaidAtRegularHourlyRatePerSchedule;
@ -57,6 +61,12 @@ public class ParametersInitialSchedules {
this.hourlyRateOfPartTimeEmployees = 12; // To simulate lower productivity
this.minWorkingHoursOfPartTimeEmployeesPerSchedule = 32;
this.maxWorkingHoursOfPartTimeEmployeesPerSchedule = 64;
int maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork = 12;
this.maxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork
= (int) (maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod);
int minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees = 12;
this.minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees
= (int) (minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees / this.hoursPerWorkPeriod);
this.minWorkingPeriodsOfPartTimeEmployeesPerSchedule
= (int) (this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
this.maxWorkingPeriodsOfPartTimeEmployeesPerSchedule
@ -70,6 +80,12 @@ public class ParametersInitialSchedules {
this.workingHoursOfFullTimeEmployeesPerSchedule = 80;
this.maxWorkingHoursOfFullTimeEmployeesPerSchedule = 120;
int maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork = 12;
this.maxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork
= (int) (maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod);
int minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees = 12;
this.minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees
= (int) (minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees / this.hoursPerWorkPeriod);
this.workingPeriodsOfFullTimeEmployeesPerSchedule
= (int) (this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
this.maxWorkingPeriodsOfFullTimeEmployeesPerSchedule

View file

@ -94,7 +94,7 @@ public class MainClass {
List<SchedulesArray> recoveredSchedulesArrayList = new ArrayList<>();
for (SchedulesArray absenceSchedule : absenceSchedulesArrayList) {
RecoveredSchedulesArray recoveredSchedule = new RecoveredSchedulesArray(absenceSchedule);
RecoveredSchedulesArray recoveredSchedule = new RecoveredSchedulesArray((AbsenceSchedulesArray) absenceSchedule);
recoveredSchedule.recoverAbsenceScheduleOptimally();
recoveredSchedulesArrayList.add(recoveredSchedule);
}

View file

@ -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,17 +47,31 @@ 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];
this.isPartTimeEmployeeActive = new boolean[this.maxPartTimeEmployee];
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
this.isPartTimeEmployeeActive[employee] = myScheduleArray.isPartTimeEmployeeActive[employee];
}
this.isFullTimeEmployeeActive = new boolean[this.maxFullTimeEmployee];
for (int employee = 0; employee < this.maxFullTimeEmployee; employee++) {
this.isFullTimeEmployeeActive[employee] = myScheduleArray.isFullTimeEmployeeActive[employee];
}
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] = myScheduleArray.PartTimeSchedules[employee][workPeriod];
this.partTimeSchedules[employee][workPeriod] = myScheduleArray.partTimeSchedules[employee][workPeriod];
this.initialPartTimeSchedules[employee][workPeriod] = myScheduleArray.initialPartTimeSchedules[employee][workPeriod];
}
}
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.fullTimeSchedules[employee][workPeriod] = myScheduleArray.fullTimeSchedules[employee][workPeriod];
this.initialFullTimeSchedules[employee][workPeriod] = myScheduleArray.initialFullTimeSchedules[employee][workPeriod];
}
}
@ -61,9 +79,9 @@ public class SchedulesArray {
this.workingPeriodsPerPartTimeEmployees = new int[this.maxPartTimeEmployee];
this.workingPeriodsPerFullTimeEmployees = new int[this.maxFullTimeEmployee];
updateEmployeesPerWorkPeriod();
updateWorkingPeriodsPerPartTimeEmployees();
updateWorkingPeriodsPerFullTimeEmployees();
updateAllEmployeesPerWorkPeriod();
updateAllWorkingPeriodsPerPartTimeEmployees();
updateAllWorkingPeriodsPerFullTimeEmployees();
}
@ -76,17 +94,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 +130,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 +199,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) {

View file

@ -6,7 +6,7 @@
package SchedulesRecovery;
import AbsenceSchedules.AbsenceSchedulesArray;
import ScheduleUtil.SchedulesArray;
/**
*
@ -14,11 +14,159 @@ import ScheduleUtil.SchedulesArray;
*/
public class RecoveredSchedulesArray extends AbsenceSchedulesArray{
public RecoveredSchedulesArray(SchedulesArray myScheduleArray){
super(myScheduleArray);
protected boolean[][] partTimeEmployeeAbsenceRecoveringAvailabilitySchedules;
protected boolean[][] fullTimeEmployeeAbsenceRecoveringAvailabilitySchedules;
public RecoveredSchedulesArray(AbsenceSchedulesArray myAbsenceScheduleArray){
super(myAbsenceScheduleArray);
}
public void recoverAbsenceScheduleOptimally() {
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) && !isFullTimeEmployeeWorking(employee, workPeriod)){
fullTimeSchedules[employee][workPeriod] = true;
updateEmployeesPerWorkPeriod(workPeriod);
updateWorkingPeriodsPerFullTimeEmployees(employee);
absenceRecoveryDone = true;
}
employee++;
}
employee = 0;
while (!absenceRecoveryDone && employee < this.maxPartTimeEmployee) {
if (isPartTimeEmployeeAvailableForAbsenceRecovering(employee, workPeriod) && !isPartTimeEmployeeWorking(employee, workPeriod)){
partTimeSchedules[employee][workPeriod] = true;
updateEmployeesPerWorkPeriod(workPeriod);
updateWorkingPeriodsPerPartTimeEmployees(employee);
absenceRecoveryDone = true;
}
employee++;
}
if (!absenceRecoveryDone) {
noEmployeeAvailable = true;
}
}
}
}
private boolean isPartTimeEmployeeAvailableForAbsenceRecovering(int employee, int workPeriod){
return isPartTimeEmployeeActive(employee) && !isPartTimeEmployeeAbsent(employee, workPeriod) && isValidPartTimeEmployeeWorkPeriod(employee,workPeriod);
}
private boolean isValidPartTimeEmployeeWorkPeriod(int employee, int workPeriod){
return isValidWorkingPeriodsOfPartTimeEmployee(employee) &&
isValidConsecutiveWorkingPeriodsOfPartTimeEmployee(employee, workPeriod) &&
isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployee(employee, workPeriod);
}
private boolean isValidWorkingPeriodsOfPartTimeEmployee(int employee){
return this.workingPeriodsPerPartTimeEmployees[employee] < myModelInitialSchedules.myScheduleParameters.maxWorkingPeriodsOfPartTimeEmployeesPerSchedule;
}
private boolean isValidConsecutiveWorkingPeriodsOfPartTimeEmployee(int employee, int workPeriod){
int consecutiveWorkingPeriods = 1;
int compteurWorkPeriod = workPeriod - 1;
while ( compteurWorkPeriod >= 0 && isPartTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutiveWorkingPeriods += 1;
compteurWorkPeriod--;
}
compteurWorkPeriod = workPeriod + 1;
while ( compteurWorkPeriod < this.workPeriodsPerSchedule && isPartTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutiveWorkingPeriods += 1;
compteurWorkPeriod++;
}
return consecutiveWorkingPeriods <= myModelInitialSchedules.myScheduleParameters.maxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork;
}
private boolean isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployee(int employee, int workPeriod){
int consecutivePreviousNonWorkingPeriods = 0;
int compteurWorkPeriod = workPeriod - 1;
while ( compteurWorkPeriod >= 0 && !isPartTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutivePreviousNonWorkingPeriods += 1;
compteurWorkPeriod--;
}
boolean validConsecutivePreviousNonWorkingPeriods = false;
if (compteurWorkPeriod == -1) {
validConsecutivePreviousNonWorkingPeriods = true;
} else if (consecutivePreviousNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees) {
validConsecutivePreviousNonWorkingPeriods = true;
}
int consecutiveNextNonWorkingPeriods = 0;
compteurWorkPeriod = workPeriod + 1;
while ( compteurWorkPeriod < this.workPeriodsPerSchedule && !isPartTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutiveNextNonWorkingPeriods += 1;
compteurWorkPeriod++;
}
boolean validConsecutiveNextNonWorkingPeriods = false;
if (compteurWorkPeriod == workPeriodsPerSchedule) {
validConsecutiveNextNonWorkingPeriods = true;
} else if (consecutiveNextNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees) {
validConsecutiveNextNonWorkingPeriods = true;
}
return validConsecutivePreviousNonWorkingPeriods && validConsecutiveNextNonWorkingPeriods;
}
private boolean isFullTimeEmployeeAvailableForAbsenceRecovering(int employee, int workPeriod){
return isFullTimeEmployeeActive(employee) && !isFullTimeEmployeeAbsent(employee, workPeriod) && isValidFullTimeEmployeeWorkPeriod(employee,workPeriod);
}
private boolean isValidFullTimeEmployeeWorkPeriod(int employee, int workPeriod){
return isValidWorkingPeriodsOfFullTimeEmployee(employee) &&
isValidConsecutiveWorkingPeriodsOfFullTimeEmployee(employee, workPeriod) &&
isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployee(employee, workPeriod);
}
private boolean isValidWorkingPeriodsOfFullTimeEmployee(int employee){
return this.workingPeriodsPerFullTimeEmployees[employee] < myModelInitialSchedules.myScheduleParameters.maxWorkingPeriodsOfFullTimeEmployeesPerSchedule;
}
private boolean isValidConsecutiveWorkingPeriodsOfFullTimeEmployee(int employee, int workPeriod){
int consecutiveWorkingPeriods = 1;
int compteurWorkPeriod = workPeriod - 1;
while ( compteurWorkPeriod >= 0 && isFullTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutiveWorkingPeriods += 1;
compteurWorkPeriod--;
}
compteurWorkPeriod = workPeriod + 1;
while ( compteurWorkPeriod < this.workPeriodsPerSchedule && isFullTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutiveWorkingPeriods += 1;
compteurWorkPeriod++;
}
return consecutiveWorkingPeriods <= myModelInitialSchedules.myScheduleParameters.maxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork;
}
private boolean isValidConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployee(int employee, int workPeriod){
int consecutivePreviousNonWorkingPeriods = 0;
int compteurWorkPeriod = workPeriod - 1;
while ( compteurWorkPeriod >= 0 && !isFullTimeEmployeeWorking(employee, compteurWorkPeriod)){
consecutivePreviousNonWorkingPeriods += 1;
compteurWorkPeriod--;
}
boolean validConsecutivePreviousNonWorkingPeriods = false;
if (compteurWorkPeriod == -1) {
validConsecutivePreviousNonWorkingPeriods = true;
} else if (consecutivePreviousNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees) {
validConsecutivePreviousNonWorkingPeriods = true;
}
int consecutiveNextNonWorkingPeriods = 0;
compteurWorkPeriod = workPeriod + 1;
while ( compteurWorkPeriod < this.workPeriodsPerSchedule && !isFullTimeEmployeeWorking(employee, compteurWorkPeriod) ){
consecutiveNextNonWorkingPeriods += 1;
compteurWorkPeriod++;
}
boolean validConsecutiveNextNonWorkingPeriods = false;
if (compteurWorkPeriod == workPeriodsPerSchedule) {
validConsecutiveNextNonWorkingPeriods = true;
} else if (consecutiveNextNonWorkingPeriods >= myModelInitialSchedules.myScheduleParameters.minConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees) {
validConsecutiveNextNonWorkingPeriods = true;
}
return validConsecutivePreviousNonWorkingPeriods && validConsecutiveNextNonWorkingPeriods;
}
}