Ajout de la contrainte des journées valides pour les travailleurs à temps partiel

Ajout de classes pour mettre les tableaux d'horaires valides
This commit is contained in:
François Pelletier 2018-03-24 10:30:23 -04:00
parent f36b59152a
commit 57b45430fa
5 changed files with 114 additions and 34 deletions

View file

@ -6,7 +6,7 @@ import org.chocosolver.solver.variables.IntVar;
public class ModelInitialSchedules {
// private final int HEURISTIQUE_DEFAUT = 0;
// private final int HEURISTIQUE_DEFAUT = 0;
// private final int HEURISTIQUE_DOMOVERWDEG = 1;
// private final int HEURISTIQUE_IMPACT_BASED_SEARCH = 2;
// private final int HEURISTIQUE_ACTIVITY = 3;
@ -25,6 +25,9 @@ public class ModelInitialSchedules {
public BoolVar workPeriodsSchedulesOfFullTimeEmployees[][];
private BoolVar transposeWorkPeriodsSchedulesOfFullTimeEmployees[][];
private BoolVar workPeriodsOfPartTimeEmployees[][];
private BoolVar workPeriodsOfFullTimeEmployees[][];
public BoolVar allWorkPeriods[];
public IntVar workingPeriodsPerPartTimeEmployees[];
@ -67,7 +70,7 @@ public class ModelInitialSchedules {
this.workPeriodsSchedulesOfFullTimeEmployees = chocoModelInitialSchedules.boolVarMatrix(this.maxFullTimeEmployee, this.myScheduleParameters.workPeriodsPerSchedule);
// Vecteur de toutes les variables
this.allWorkPeriods = chocoModelInitialSchedules.boolVarArray((this.maxPartTimeEmployee+this.maxFullTimeEmployee)*this.myScheduleParameters.workPeriodsPerSchedule);
/*this.allWorkPeriods = chocoModelInitialSchedules.boolVarArray((this.maxPartTimeEmployee+this.maxFullTimeEmployee)*this.myScheduleParameters.workPeriodsPerSchedule);
for (int employee = 0; employee < this.maxPartTimeEmployee; employee++) {
for(int workPeriod = 0; workPeriod < this.myScheduleParameters.workPeriodsPerSchedule; workPeriod++){
@ -81,7 +84,7 @@ public class ModelInitialSchedules {
employee*this.myScheduleParameters.workPeriodsPerSchedule+workPeriod] =
this.workPeriodsSchedulesOfFullTimeEmployees[employee][workPeriod];
}
}
}*/
// Variable pour faire le compte du nombre d'heures des employes
this.workingPeriodsPerPartTimeEmployees = chocoModelInitialSchedules.intVarArray(this.maxPartTimeEmployee, 0, this.myScheduleParameters.workPeriodsPerSchedule, true);
@ -109,6 +112,19 @@ public class ModelInitialSchedules {
this.employeesPerWorkPeriods = chocoModelInitialSchedules.intVarArray(this.myScheduleParameters.workPeriodsPerSchedule,
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() {
@ -143,7 +159,7 @@ public class ModelInitialSchedules {
this.myScheduleParameters.maxWorkingPeriodsOfPartTimeEmployeesPerSchedule).post();
}
// Constraintes pour compter le nombre d'employes par periode de travail et s'assurer qu'il
// 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.workPeriodsPerSchedule; workPeriod++) {
chocoModelInitialSchedules.count(chocoModelInitialSchedules.intVar(1),
@ -160,6 +176,17 @@ public class ModelInitialSchedules {
this.employeesPerWorkPeriods[workPeriod]).post();
}
// Contrainte pour heures consécutives des 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é

View file

@ -31,6 +31,8 @@ public class ParametersInitialSchedules {
public int[] requiredWorkforce;
Tuples enumerationWorkPeriodsSchedulesOfFullTimeEmployees;
Tuples ValidPartTimeEmployeeShiftTuples;
public ParametersInitialSchedules() {
this.setGeneralParameters();
@ -38,6 +40,7 @@ public class ParametersInitialSchedules {
this.setFullTimeEmployeesParameters();
this.setRequiredWorkforce();
this.setWorkPeriodsSchedulesOfFullTimeEmployees();
this.setValidPartTimeEmployeeShiftTuples();
}
@ -79,7 +82,7 @@ public class ParametersInitialSchedules {
this.requiredWorkforce = new int[this.daysPerSchedule * this.workPeriodsPerDay];
this.totalWorkedPeriodsInSchedule = 0;
int[] dailyRequiredWorkforce = new int[]{4,4,5,5,3,3};
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];
@ -88,38 +91,18 @@ public class ParametersInitialSchedules {
}
}
private void setWorkPeriodsSchedulesOfFullTimeEmployees() {
int[][] dailySchedulesOfFullTimeEmployees = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1},
{1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},
{1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},
{1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0},};
ValidDailySchedules v = new ValidDailySchedules();
int possibleDailyScheduleOfFullTimeEmployees = dailySchedulesOfFullTimeEmployees.length;
int[][] dailySchedulesOfFullTimeEmployees = v.dailySchedulesOfFullTimeEmployees;
int[][] workPeriodsSchedulesOfFullTimeEmployees
= new int[possibleDailyScheduleOfFullTimeEmployees * this.shiftWorkPerDay][this.workPeriodsPerSchedule];
= new int[v.length() * this.shiftWorkPerDay][this.workPeriodsPerSchedule];
// Cette fonction sera a ameliorer avec des sous-fonctions, car elle n'est pas tres explicite.
for (int scheduleNumber = 0; scheduleNumber < possibleDailyScheduleOfFullTimeEmployees; scheduleNumber++) {
for (int scheduleNumber = 0; scheduleNumber < v.length(); scheduleNumber++) {
for (int day = 0; day < this.daysPerSchedule; day++) {
for (int shiftNumber = 0; shiftNumber < this.shiftWorkPerDay; shiftNumber++) {
if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 0) {
@ -160,6 +143,11 @@ public class ParametersInitialSchedules {
= new Tuples(workPeriodsSchedulesOfFullTimeEmployees, true);
}
private void setValidPartTimeEmployeeShiftTuples() {
this.ValidPartTimeEmployeeShiftTuples = new ValidPartTimeEmployeeShift().makeTuples();
}
// A implementer plus tard si l'on veut travailler avec des fichiers texte
public ParametersInitialSchedules(String fileName) {

View file

@ -0,0 +1,34 @@
package InitialSchedules;
public class ValidDailySchedules {
int[][] dailySchedulesOfFullTimeEmployees;
public ValidDailySchedules() {
this.dailySchedulesOfFullTimeEmployees = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1},
{1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1},
{1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},
{1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0},
{1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0},
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0},};
}
public int length() {
return this.dailySchedulesOfFullTimeEmployees.length;
}
}

View file

@ -0,0 +1,32 @@
package InitialSchedules;
import org.chocosolver.solver.constraints.extension.Tuples;
public class ValidPartTimeEmployeeShift {
int[][] shiftsOfPartTimeEmployees;
public ValidPartTimeEmployeeShift() {
this.shiftsOfPartTimeEmployees = new int[][]{
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 1, 0},
{0, 0, 0, 1, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1},
{0, 0, 0, 1, 1, 0},
{0, 0, 1, 1, 0, 0},
{0, 1, 1, 0, 0, 0},
{1, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1},
{0, 0, 0, 1, 1, 1},
{0, 0, 0, 1, 1, 1},
{0, 0, 0, 1, 1, 1}
};
}
public Tuples makeTuples() {
return new Tuples(this.shiftsOfPartTimeEmployees, true);
}
}

View file

@ -1,6 +1,4 @@
import org.chocosolver.solver.Solver;
import org.chocosolver.solver.search.strategy.Search;
public class MainClass {
@ -23,9 +21,10 @@ public class MainClass {
= new InitialSchedules.ModelInitialSchedules(myScheduleParameters);
Solver solverInitialSchedules = myModelInitialSchedules.chocoModelInitialSchedules.getSolver();
solverInitialSchedules.setSearch(Search.domOverWDegSearch(myModelInitialSchedules.allWorkPeriods));
/*solverInitialSchedules.setSearch(Search.domOverWDegSearch(myModelInitialSchedules.allWorkPeriods));
solverInitialSchedules.limitSolution(10);
solverInitialSchedules.findAllSolutions();
solverInitialSchedules.findAllSolutions();*/
solverInitialSchedules.findSolution();
// Solution bestInitialSchedules = solverInitialSchedules.findOptimalSolution
// (myModelInitialSchedules.scheduleProfit, Model.MINIMIZE);