Merge branch 'VariableDemand' into 'master'
Variable demand See merge request franc00018/tpIFT7020!3
39
.gitignore
vendored
|
@ -1,3 +1,38 @@
|
|||
choco-4.0.6
|
||||
choco*
|
||||
/tp/code/TP/Travail_de_session/nbproject/private/
|
||||
/out
|
||||
## Core latex/pdflatex auxiliary files:
|
||||
*.aux
|
||||
*.lof
|
||||
*.log
|
||||
*.lot
|
||||
*.fls
|
||||
*.out
|
||||
*.toc
|
||||
*.fmt
|
||||
*.fot
|
||||
*.cb
|
||||
*.cb2
|
||||
.*.lb
|
||||
|
||||
/tp/code/TP/Travail_de_session/nbproject/private/
|
||||
## Bibliography auxiliary files (bibtex/biblatex/biber):
|
||||
*.bbl
|
||||
*.bcf
|
||||
*.blg
|
||||
*-blx.aux
|
||||
*-blx.bib
|
||||
*.run.xml
|
||||
|
||||
## Build tool auxiliary files:
|
||||
*.fdb_latexmk
|
||||
*.synctex
|
||||
*.synctex(busy)
|
||||
*.synctex.gz
|
||||
*.synctex.gz(busy)
|
||||
*.pdfsync
|
||||
|
||||
## Intellij
|
||||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
|
|
|
@ -3,61 +3,61 @@
|
|||
\label{sec:AnnexeHoraires}
|
||||
\pagebreak
|
||||
\begin{landscape}
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule1.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule1.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.11.}
|
||||
\label{fig:InitialSchedule1}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule2.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule2.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.17.}
|
||||
\label{fig:InitialSchedule2}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule3.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule3.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.22.}
|
||||
\label{fig:InitialSchedule3}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule4.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule4.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.28.}
|
||||
\label{fig:InitialSchedule4}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule5.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule5.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.33.}
|
||||
\label{fig:InitialSchedule5}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule6.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule6.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.39.}
|
||||
\label{fig:InitialSchedule6}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule7.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule7.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.44.}
|
||||
\label{fig:InitialSchedule7}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=25cm]{Figures/InitialSchedule8.png}
|
||||
\includegraphics[width=25cm]{Tables/InitialSchedule8.png}
|
||||
\caption{Horaire initiale ayant un ratio employés temps plein / employés temps partiel de 0.50.}
|
||||
\label{fig:InitialSchedule8}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
\end{landscape}
|
||||
%%% Local Variables:
|
||||
|
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
24
Rapport_de_session/etapes.dot
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
digraph etapes {
|
||||
graph [splines=false];
|
||||
|
||||
node[fontsize=10, color=black, shape=box, width=3, height=0.5];
|
||||
a[label="Générer les tableaux\nd'horaires valides"];
|
||||
b1[label="Générer les horaires initiales"];
|
||||
b2[label="Calculer le coût initial"];
|
||||
c1[label="Générer les scénarios d'absences"];
|
||||
c2[label="Calculer le coût\ndes absences"];
|
||||
d1[label="Générer les horaires\nde recouvrement optimales"];
|
||||
d2[label="Calculer le coût\nde recouvrement moyen"];
|
||||
|
||||
{a -> b1};
|
||||
{rank=same;b1 -> b2};
|
||||
{b2 -> c1};
|
||||
{rank=same;c1 -> c2};
|
||||
{c2 -> d1};
|
||||
{rank=same;d1 -> d2};
|
||||
|
||||
edge[style=invis];
|
||||
{b1 -> c1 -> d1};
|
||||
{b2 -> c2 -> d2};
|
||||
}
|
BIN
Rapport_de_session/etapes.pdf
Normal file
|
@ -3,8 +3,15 @@
|
|||
|
||||
La planification d'horaires de travail est un enjeu important pour plusieurs industries et entités gouvernementales. Une mauvaise planification des ressources en fonction de la demande de travail d'une entreprise peut entraîner une diminution des profits en plus d'avoir des répercussions sur les dates de livraison de ses différents contrats. Parmi les raisons qui rendent cette tâche difficile, il y a les restrictions complexes provenant de la loi du travail, une variabilité de la demande de travail selon les période de l'année et une incertitude liée à l'absentéisme des employés. Il devient donc important de produire des horaires de travail permettant une flexibilité d'ajustement en fonction de la demande de travail et de l'absentéisme des employés, tout en minimisant le coût des salaires.
|
||||
|
||||
Le présent travail propose une approche pour la génération d'horaires de travail optimale en fonction du taux d'absentéisme et du taux d'augmentation de la demande de travail.
|
||||
|
||||
Le présent travail propose une approche pour la génération d'horaires de travail optimales et robustes en fonction du taux d'absentéisme et du taux d'augmentation de la demande de travail. Les différentes étapes suivies sont présentées à la Figure \ref{fig:etapes}.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\label{fig:etapes}
|
||||
\includegraphics[]{etapes}
|
||||
\caption{Étapes de la production d'horaires optimales et robustes}
|
||||
\end{figure}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "rapport_de_recherche"
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
build: rapport_de_recherche.pdf
|
||||
|
||||
maxconsecutif.svg:
|
||||
maxconsecutif.pdf:
|
||||
dot -Tpdf maxconsecutif.dot -o maxconsecutif.pdf
|
||||
|
||||
etapes.pdf:
|
||||
dot -Tpdf etapes.dot -o etapes.pdf
|
||||
|
||||
rapport_de_recherche.pdf: rapport_de_recherche.bbl
|
||||
pdflatex rapport_de_recherche.tex
|
||||
pdflatex rapport_de_recherche.tex
|
||||
|
||||
rapport_de_recherche.bbl: rapport_de_recherche.tex maxconsecutif.svg
|
||||
rapport_de_recherche.bbl: rapport_de_recherche.tex maxconsecutif.pdf etapes.pdf
|
||||
pdflatex rapport_de_recherche.tex
|
||||
bibtex rapport_de_recherche.aux
|
||||
|
||||
|
@ -22,3 +25,6 @@ clean:
|
|||
-rm *.log
|
||||
-rm *.out
|
||||
-rm *.toc
|
||||
-rm *.pdf
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ Notre modèle considère deux types $A$ d'employés: les employés à temps plei
|
|||
|
||||
\begin{align}
|
||||
\label{typeemployes}
|
||||
A \in {FT,PT}
|
||||
A \in \lbrace FT,PT \rbrace
|
||||
\end{align}
|
||||
|
||||
Ils travaillent des périodes consécutives d'une durée $i_{A}$ heures. L'intervalle de travail des employés à temps plein doit cependant débuter à la première, troisième ou cinquième période. On définit aussi un nombre d'heures de repos minimal $r_{min,A}$ entre les périodes travaillées. Les employés à temps plein travaillent $h_{reg}^{FT}$ heures par période de deux semaines et les employés à temps partiel travaillent entre $h_{min}^{PT}$ et $h_{max}^{PT}$ heures durant cette même période. Les employés ne travaillent pas plus que $j_{max,A}$ journées consécutives. Le nombre d'employés $E$ de chaque type est variable et sera déterminé par les ratios \eqref{eq:eftept}:
|
||||
|
@ -84,7 +84,7 @@ L'horaire doit inclure le travail durant une fin de semaine sur deux \eqref{eq:c
|
|||
h_{6} &= h_{7} \wedge h_{13} = h_{14} \wedge h_{6} \neq h_{13}
|
||||
\end{align}
|
||||
|
||||
L'horaire doit respecter le nombre maximum de jours consécutifs travaillés autorisés. On utilise une contrainte \textsc{Regular} \guillemotleft réifiée \guillemotright pour représenter le non-respect de cette contrainte, c'est-à-dire lorsque qu'on retrouve une séquence de jours consécutifs dont la longueur est supérieure à $j_{max,A}$. L'automate fini pour cette contrainte lorsque $j_{max,A}=4$ est représenté à la Figure \ref{fig:automatemaxconsecutif}. L'expression régulière représentant cet automate prend la forme \texttt{[01]*1\{5,\}[01]*}.
|
||||
L'horaire doit respecter le nombre maximum de jours consécutifs travaillés autorisés. On utilise une contrainte \textsc{Regular} \guillemotleft réifiée \guillemotright pour représenter le non-respect de cette contrainte, c'est-à-dire lorsque qu'on retrouve une séquence de jours consécutifs dont la longueur est supérieure à $j_{max,A}$. L'automate fini pour cette contrainte lorsque $j_{max,A}=4$ est représenté à la Figure \ref{fig:automatemaxconsecutif}.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
|
@ -93,7 +93,16 @@ L'horaire doit respecter le nombre maximum de jours consécutifs travaillés aut
|
|||
\label{fig:automatemaxconsecutif}
|
||||
\end{figure}
|
||||
|
||||
On obtient, pour chaque type de travailleur, une liste de vecteurs à laquelle on ajouter le vecteur nul, représentant la situation où l'employé est exclus de l'horaire.
|
||||
|
||||
|
||||
L'expression régulière représentant cet automate est représenté à la Figure \ref{fig:regexpautomate}. On obtient, pour chaque type de travailleur, une liste de vecteurs à laquelle on ajouter le vecteur nul, représentant la situation où l'employé est exclus de l'horaire.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\fbox{\texttt{[01]*1\{5,\}[01]*}}
|
||||
\caption{Expression régulière représentant l'automate fini}
|
||||
\label{fig:regexpautomate}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection{Ajout des périodes}
|
||||
\label{sec:horaireajoutperiode}
|
||||
|
@ -115,15 +124,16 @@ On considère la matrice des horaires quinzomadaires valides \eqref{eq:horairejo
|
|||
\subsection{Contraintes}
|
||||
\label{sec:contraintes}
|
||||
|
||||
Chaque horaire d'employé doit d'abord correspondre à un horaire valide tel qu'établi à la section \ref{sec:horairesvalides}. Il doit donc satisfaire une contrainte \textsc{Tableau} \eqref{eq:contraintetableau}.
|
||||
Chaque horaire d'employé $X_e$ doit d'abord correspondre à un horaire valide tel qu'établi à la section \ref{sec:horairesvalides}. Il doit donc satisfaire une contrainte \textsc{Tableau} \eqref{eq:contraintetableau}.
|
||||
|
||||
\begin{align}
|
||||
\label{eq:contraintetableau}
|
||||
\mathcal{C}_1 &: \textsc{Tableau}\left( \mathbf{V}_A,
|
||||
\begin{bmatrix}x_{e,1,1}&\cdots&x_{e,1,J}\\
|
||||
X_e &= \begin{bmatrix}x_{e,1,1}&\cdots&x_{e,1,J}\\
|
||||
\vdots&\ddots&\vdots\\
|
||||
x_{e,P,1}&\cdots&x_{e,P,J}
|
||||
\end{bmatrix}\right) & \forall e
|
||||
\end{bmatrix}\\
|
||||
\label{eq:contraintetableau}
|
||||
\mathcal{C}_1 &: \textsc{Tableau}\left( \mathbf{V}_A,
|
||||
X_e \right) & \forall e
|
||||
\end{align}
|
||||
|
||||
La planification doit aussi satisfaire la demande en employés, en utilisant une contrainte \textsc{Sum} \eqref{eq:contrsumemployes}.
|
||||
|
@ -133,6 +143,12 @@ La planification doit aussi satisfaire la demande en employés, en utilisant une
|
|||
\mathcal{C}_2 &: \sum_{A}\sum_{e=1}^{E_A} x_{e,p,j} = d_{p,j} & \forall 1 \leq p \leq P, 1 \leq j \leq J
|
||||
\end{align}
|
||||
|
||||
Afin de réduire la taille de l'arbre de recherche, nous imposons la contrainte de bris de symétrie suivante: les horaires des employés à temps plein, de même que les horaires des employés à temps partiel, doivent être dans un ordre lexicographique \eqref{eq:lex}.
|
||||
\begin{align}
|
||||
\label{eq:lex}
|
||||
X_i &\leq X_{i+1} &\forall i \in [1,E^A],A
|
||||
\end{align}
|
||||
|
||||
\subsection{Fonction objectif}
|
||||
\label{sec:fonctionobjectif}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
\documentclass[12pt]{article} % Précise le type de document, et la taille de la police de caractère
|
||||
\documentclass[11pt]{article} % Précise le type de document, et la taille de la police de caractère
|
||||
\usepackage[square,sort,numbers]{natbib}% Pour pouvoir utiliser une bibliographie externe
|
||||
\usepackage[french]{babel} % Pour préciser la langue du document
|
||||
\usepackage[utf8]{inputenc} % Précise comment le texte est saisi : cela permet de tapper directement les accents
|
||||
|
@ -57,12 +57,17 @@
|
|||
\usepackage{cprotect} % Pour pouvoir personaliser la légende des figures
|
||||
\DeclareMathOperator*{\argmax}{arg\,max}
|
||||
\DeclareMathOperator*{\argmin}{arg\,min}
|
||||
\setlength{\fboxsep}{3pt}
|
||||
\setlength{\fboxrule}{1pt}
|
||||
%----------------------------------------------------------------
|
||||
|
||||
\begin{document}
|
||||
\input{pagetitre} % Inclut le code contenu dans un fichier comme s'il était entré ici
|
||||
\tableofcontents
|
||||
%\listoffigures
|
||||
\newpage
|
||||
\listoffigures
|
||||
\newpage
|
||||
\listoftables
|
||||
% Le package newclude mis en commentaire permet d'introduire une * pour éviter le saut de page entre les section
|
||||
\include{introduction}
|
||||
\include{modelisation}
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
\subsection{Résultats de l'étude de cas}
|
||||
À l'aide du modèle de génération d'horaires en 2 phases, 8 horaires présentant des ratios employés temps plein / employés temps partiel différents ont été obtenus (voir Annexe 1). Puisque les 2 types d'employés ont des contraintes différentes quant au recouvrement de ces derniers, il a été possible de tester l'effet du taux d'absentéisme et de l'augmentation de la demande. L'effet de ces 2 paramètres sur le coût de recouvrement des 8 horaires sont présentés au Tableau \ref{table:TableauEffetsParametres}. Ces coûts de recouvrement sont présentés comme un ratio par rapport au coût de l'horaire optimale, soit celle ayant un nombre d'employé temps plein maximal.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=16cm]{Figures/TableaueffetsParametres.png}
|
||||
\includegraphics[width=16cm]{Tables/TableaueffetsParametres.png}
|
||||
\caption{Effet des probabilités d'absentéisme et d'augmentation de la demande de travail sur le coût moyen de recouvrement des horaires.}
|
||||
\label{table:TableauEffetsParametres}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
Comme le montre ce tableau, pour une probabilité d'absentéisme nulle (sans absence), le coût des horaires augmente en fonction du nombre d'employé à temps partiel. Cela est dû au fait que ces employés ont un taux horaire régulier 20\% plus élevé que celui des employés à temps plein. De plus, pour tous les ratios de type employés, l'augmentation de la probabilité d'absentéisme et l'augmentation de la probabilité d'augmentation de la demande de travail sont associées à l'augmentation du coût de recouvrement des horaires. Cette augmentation de coûts est liée au temps supplémentatire des employés à temps plein (+50\%) ainsi que du taux horaire régulier supérieur des employés à temps partiel, lesquels sont privilégiés pour effectuer les recouvrements. Enfin, ces résultats démontrent que le ratio de type d'employés qui conduit à l'horaire avec un coût de recouvrement minimal varie selon les deux paramètres testés. En effet, lorsque le nombre d'absence et/ou la demande de travail supplémentaire augmente de façon importante, un nombre d'employés à temps partiel supérieur par rapport au nombre d'employés à temps plein permet d'obtenir un horaire au coût de recouvrement le plus faible. La prinpale raison est un diminution du temps supplémentaire effectué par les employés à temps plein. La Figure xx montre les ratios de type d'employés à privilégier pour la construction d'horaires en fonction des probabilités d'absence et d'augmentation de la demande de travail.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{table}[ht]
|
||||
\centering
|
||||
\includegraphics[width=16cm]{Figures/Mapping.png}
|
||||
\caption{Proportion d'employés à temps plein optimale en fonction des probabilités d'absentéisme et d'augmentation de la demande de travail.}
|
||||
\label{table:MappingRatioOptimal}
|
||||
\end{figure}
|
||||
\end{table}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
|
|
|
@ -5,8 +5,8 @@ import ScheduleUtil.SchedulesArray;
|
|||
import jdistlib.rng.RandomEngine;
|
||||
|
||||
public class AbsenceSchedulesArray extends SchedulesArray{
|
||||
|
||||
public SchedulesArray initialSchedulesArray;
|
||||
|
||||
private final SchedulesArray initialSchedulesArray;
|
||||
public int numberOfRecoveringActionsToPerform;
|
||||
|
||||
public AbsenceSchedulesArray(SchedulesArray initialSchedulesArray, RandomEngine r) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package AbsenceSchedules;
|
|||
import jdistlib.Binomial;
|
||||
import jdistlib.rng.RandomEngine;
|
||||
|
||||
public class AbsencesVector {
|
||||
class AbsencesVector {
|
||||
private final boolean[] AbsencesVector;
|
||||
|
||||
public AbsencesVector(int length, RandomEngine r) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package AbsenceSchedules;
|
||||
|
||||
import ScheduleUtil.SchedulesArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -14,8 +15,8 @@ import java.util.List;
|
|||
* @author frabe
|
||||
*/
|
||||
public class BankAbsenceSchedules {
|
||||
public SchedulesArray initialSchedulesArray;
|
||||
public List<AbsenceSchedulesArray> bankAbsenceSimulation;
|
||||
public final SchedulesArray initialSchedulesArray;
|
||||
public final List<AbsenceSchedulesArray> bankAbsenceSimulation;
|
||||
|
||||
public BankAbsenceSchedules(SchedulesArray initialSchedulesArray) {
|
||||
this.initialSchedulesArray = initialSchedulesArray;
|
||||
|
|
|
@ -10,7 +10,7 @@ package AbsenceSchedules;
|
|||
* @author frabe
|
||||
*/
|
||||
public class ParametersAbsencesSimulator {
|
||||
public static double probPresence = 0.99;
|
||||
public static final double probPresence = 0.99;
|
||||
public static final double probReturn = 0.50;
|
||||
public static int numberAbsenceSimulations = 1000;
|
||||
public static final int numberAbsenceSimulations = 1000;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,12 @@ import org.chocosolver.solver.constraints.extension.Tuples;
|
|||
*
|
||||
* @author frabe
|
||||
*/
|
||||
public class GenerationPossibleEmployeeSchedules {
|
||||
class GenerationPossibleEmployeeSchedules {
|
||||
public static Tuples setWorkPeriodsSchedulesOfFullTimeEmployees(int shiftWorkPerDay, int workPeriodsPerSchedule, int workPeriodPerDay, int daysPerSchedule) {
|
||||
|
||||
ValidDailySchedules validDailyFullTimeSchedules = new ValidDailySchedules(daysPerSchedule,
|
||||
10,
|
||||
10,
|
||||
0,
|
||||
5,
|
||||
7,
|
||||
12,
|
||||
|
@ -35,28 +34,28 @@ public class GenerationPossibleEmployeeSchedules {
|
|||
for (int day = 0; day < daysPerSchedule; day++) {
|
||||
for (int shiftNumber = 0; shiftNumber < shiftWorkPerDay; shiftNumber++) {
|
||||
if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 0) {
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 0] = 1;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay] = 1;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 1] = 1;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 4] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 5] = 0;
|
||||
} else if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 1) {
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 2] = 1;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 3] = 1;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 4] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 5] = 0;
|
||||
} else if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 2) {
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 4] = 1;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 5] = 1;
|
||||
} else if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 0) {
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * shiftWorkPerDay + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
|
@ -68,8 +67,7 @@ public class GenerationPossibleEmployeeSchedules {
|
|||
}
|
||||
|
||||
// Creation des tuples a partir du tableau pour creer les 3 types de quart de travail (nuit, jour soir).
|
||||
Tuples enumerationWorkPeriodsSchedulesOfFullTimeEmployees = new Tuples(workPeriodsSchedulesOfFullTimeEmployees, true);
|
||||
return enumerationWorkPeriodsSchedulesOfFullTimeEmployees;
|
||||
return new Tuples(workPeriodsSchedulesOfFullTimeEmployees, true);
|
||||
}
|
||||
public static Tuples setWorkPeriodsSchedulesOfPartTimeEmployees(int workPeriodsPerSchedule, int workPeriodPerDay, int daysPerSchedule) {
|
||||
|
||||
|
@ -79,7 +77,6 @@ public class GenerationPossibleEmployeeSchedules {
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
6);
|
||||
|
||||
int NbPartTimeSolutions = validDailyPartTimeSchedules.getNbSolutions();
|
||||
|
@ -96,42 +93,42 @@ public class GenerationPossibleEmployeeSchedules {
|
|||
for (int day = 0; day < daysPerSchedule; day++) {
|
||||
for (int shiftNumber = 0; shiftNumber < maxShiftConfig; shiftNumber++) {
|
||||
if (dailySchedulesOfPartTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 0) {
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 0] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 1] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 4] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 5] = 0;
|
||||
} else if (dailySchedulesOfPartTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 1) {
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 1] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 2] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 4] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 5] = 0;
|
||||
} else if (dailySchedulesOfPartTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 2) {
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 2] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 3] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 4] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 5] = 0;
|
||||
} else if (dailySchedulesOfPartTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 3) {
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 3] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 4] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 5] = 0;
|
||||
} else if (dailySchedulesOfPartTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 4) {
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 4] = 1;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 5] = 1;
|
||||
} else if (dailySchedulesOfPartTimeEmployees[scheduleNumber][day] == 0) {
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 0] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 1] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 2] = 0;
|
||||
workPeriodsSchedulesOfPartTimeEmployees[scheduleNumber * maxShiftConfig + shiftNumber][day * workPeriodPerDay + 3] = 0;
|
||||
|
@ -143,7 +140,6 @@ public class GenerationPossibleEmployeeSchedules {
|
|||
}
|
||||
|
||||
// Creation des tuples a partir du tableau pour creer les 3 types de quart de travail (nuit, jour soir).
|
||||
Tuples enumerationWorkPeriodsSchedulesOfPartTimeEmployees = new Tuples(workPeriodsSchedulesOfPartTimeEmployees, true);
|
||||
return enumerationWorkPeriodsSchedulesOfPartTimeEmployees;
|
||||
return new Tuples(workPeriodsSchedulesOfPartTimeEmployees, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,16 +14,16 @@ import org.chocosolver.solver.variables.IntVar;
|
|||
* @author frabe
|
||||
*/
|
||||
public class ModelFullTimeEmployeesInitialSchedules {
|
||||
public ParametersInitialSchedules myScheduleParameters;
|
||||
public final ParametersInitialSchedules myScheduleParameters;
|
||||
|
||||
public int numberOfFullTimeEmployees;
|
||||
public final int numberOfFullTimeEmployees;
|
||||
|
||||
public BoolVar workPeriodsSchedulesOfFullTimeEmployees[][];
|
||||
private BoolVar transposeWorkPeriodsSchedulesOfFullTimeEmployees[][];
|
||||
|
||||
private IntVar fullTimeEmployeesPerWorkPeriods[];
|
||||
|
||||
public Model chocoModelInitialSchedules;
|
||||
public final Model chocoModelInitialSchedules;
|
||||
|
||||
public ModelFullTimeEmployeesInitialSchedules(ParametersInitialSchedules myScheduleParameters, int numberOfFullTimeEmployees) {
|
||||
|
||||
|
@ -70,7 +70,7 @@ public class ModelFullTimeEmployeesInitialSchedules {
|
|||
transposeWorkPeriodsSchedulesOfFullTimeEmployees[workPeriod],
|
||||
this.fullTimeEmployeesPerWorkPeriods[workPeriod]).post();
|
||||
chocoModelInitialSchedules.arithm(this.fullTimeEmployeesPerWorkPeriods[workPeriod], "<=",
|
||||
this.myScheduleParameters.requiredWorkforce[workPeriod]).post();
|
||||
this.myScheduleParameters.getRequiredWorkForce(workPeriod)).post();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,16 @@ import org.chocosolver.solver.variables.IntVar;
|
|||
|
||||
public class ModelPartTimeEmployeesInitialSchedules {
|
||||
|
||||
public ParametersInitialSchedules myScheduleParameters;
|
||||
public final ParametersInitialSchedules myScheduleParameters;
|
||||
|
||||
public int maxPartTimeEmployee;
|
||||
public final int maxPartTimeEmployee;
|
||||
|
||||
public BoolVar workPeriodsSchedulesOfPartTimeEmployees[][];
|
||||
private BoolVar transposeWorkPeriodsSchedulesOfPartTimeEmployees[][];
|
||||
|
||||
private IntVar partTimeEmployeesPerWorkPeriods[];
|
||||
|
||||
public Model chocoModelInitialSchedules;
|
||||
public final Model chocoModelInitialSchedules;
|
||||
|
||||
public ModelPartTimeEmployeesInitialSchedules(ParametersInitialSchedules myScheduleParameters) {
|
||||
|
||||
|
@ -65,7 +65,7 @@ public class ModelPartTimeEmployeesInitialSchedules {
|
|||
transposeWorkPeriodsSchedulesOfPartTimeEmployees[workPeriod],
|
||||
this.partTimeEmployeesPerWorkPeriods[workPeriod]).post();
|
||||
chocoModelInitialSchedules.arithm(this.partTimeEmployeesPerWorkPeriods[workPeriod], "=",
|
||||
this.myScheduleParameters.requiredWorkforce[workPeriod]).post();
|
||||
this.myScheduleParameters.getRequiredWorkForce(workPeriod)).post();
|
||||
}
|
||||
|
||||
// Contrainte de bris de symétrie:
|
||||
|
|
|
@ -6,37 +6,37 @@ import org.chocosolver.solver.constraints.extension.Tuples;
|
|||
public class ParametersInitialSchedules {
|
||||
|
||||
//General Parameters
|
||||
final int shiftWorkPerDay = 3;
|
||||
final int daysPerSchedule = 14;
|
||||
final int hoursPerWorkPeriod = 4;
|
||||
final int workingHoursPaidAtRegularHourlyRatePerSchedule = 80;
|
||||
final int workingHoursPaidAtRegularHourlyRatePerShiftWork = 8;
|
||||
private final int shiftWorkPerDay = 3;
|
||||
private final int daysPerSchedule = 14;
|
||||
private final int hoursPerWorkPeriod = 4;
|
||||
private final int workingHoursPaidAtRegularHourlyRatePerSchedule = 80;
|
||||
private final int workingHoursPaidAtRegularHourlyRatePerShiftWork = 8;
|
||||
|
||||
|
||||
//PartTime Employees Parameters
|
||||
final int fixedCostOfPartTimeEmployeesPerSchedule = 50;
|
||||
final int regularHourlyRateOfPartTimeEmployees = 12;
|
||||
final int overtimeHourlyRateOfPartTimeEmployees = 17;
|
||||
final int minWorkingHoursOfPartTimeEmployeesPerSchedule = 32;
|
||||
final int maxWorkingHoursOfPartTimeEmployeesPerSchedule = 64;
|
||||
final int maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork = 12;
|
||||
final int minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees = 12;
|
||||
private final int fixedCostOfPartTimeEmployeesPerSchedule = 50;
|
||||
private final int regularHourlyRateOfPartTimeEmployees = 12;
|
||||
private final int overtimeHourlyRateOfPartTimeEmployees = 17;
|
||||
private final int minWorkingHoursOfPartTimeEmployeesPerSchedule = 32;
|
||||
private final int maxWorkingHoursOfPartTimeEmployeesPerSchedule = 64;
|
||||
private final int maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork = 12;
|
||||
private final int minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees = 12;
|
||||
|
||||
//FullTime Employees Parameters
|
||||
final int fixedCostOfFullTimeEmployeesPerSchedule = 50;
|
||||
final int regularHourlyRateOfFullTimeEmployees = 10;
|
||||
final int overtimeHourlyRateOfFullTimeEmployees = 15;
|
||||
final int workingHoursOfFullTimeEmployeesPerSchedule = 80;
|
||||
final int maxWorkingHoursOfFullTimeEmployeesPerSchedule = 120;
|
||||
final int maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork = 12;
|
||||
final int minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees = 12;
|
||||
private final int fixedCostOfFullTimeEmployeesPerSchedule = 50;
|
||||
private final int regularHourlyRateOfFullTimeEmployees = 10;
|
||||
private final int overtimeHourlyRateOfFullTimeEmployees = 15;
|
||||
private final int workingHoursOfFullTimeEmployeesPerSchedule = 80;
|
||||
private final int maxWorkingHoursOfFullTimeEmployeesPerSchedule = 120;
|
||||
private final int maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork = 12;
|
||||
private final int minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees = 12;
|
||||
|
||||
int[] requiredWorkforce;
|
||||
private int[] requiredWorkforce;
|
||||
int NbFullTimeSolutions;
|
||||
int NbPartTimeSolutions;
|
||||
Tuples enumerationWorkPeriodsSchedulesOfFullTimeEmployees;
|
||||
Tuples enumerationWorkPeriodsSchedulesOfPartTimeEmployees;
|
||||
Tuples ValidPartTimeEmployeeShiftTuples;
|
||||
private Tuples ValidPartTimeEmployeeShiftTuples;
|
||||
|
||||
public ParametersInitialSchedules() {
|
||||
|
||||
|
@ -77,6 +77,12 @@ public class ParametersInitialSchedules {
|
|||
public int getRequiredWorkForce(int workPeriod) {
|
||||
return this.requiredWorkforce[workPeriod];
|
||||
}
|
||||
|
||||
public void setRequiredWorkforce(int[] vector) {
|
||||
for(int workPeriod=0;workPeriod<vector.length;workPeriod++) {
|
||||
this.requiredWorkforce[workPeriod] = vector[workPeriod];
|
||||
}
|
||||
}
|
||||
|
||||
public int getDaysPerSchedule() {
|
||||
return daysPerSchedule;
|
||||
|
@ -87,7 +93,7 @@ public class ParametersInitialSchedules {
|
|||
}
|
||||
|
||||
public int getWorkPeriodPerDay() {
|
||||
return (int) 24/this.hoursPerWorkPeriod;
|
||||
return 24 / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getFixedCostOfPartTimeEmployeesPerSchedule() {
|
||||
|
@ -99,64 +105,64 @@ public class ParametersInitialSchedules {
|
|||
}
|
||||
|
||||
public int getWorkingPeriodsPaidAtRegularHourlyRatePerSchedule () {
|
||||
return (int) (workingHoursPaidAtRegularHourlyRatePerSchedule / this.hoursPerWorkPeriod);
|
||||
return workingHoursPaidAtRegularHourlyRatePerSchedule / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getWorkingPeriodsPaidAtRegularHourlyRatePerShiftWork () {
|
||||
return (int) (workingHoursPaidAtRegularHourlyRatePerShiftWork / this.hoursPerWorkPeriod);
|
||||
return workingHoursPaidAtRegularHourlyRatePerShiftWork / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate () {
|
||||
return (int) (regularHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod);
|
||||
return regularHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate () {
|
||||
return (int) (regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod);
|
||||
return regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMinimumWorkingPeriodCost () {
|
||||
return (int) (regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod);
|
||||
return regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getWorkingPeriodCostOfPartTimeEmployeesPaidAtOvertimeHourlyRate () {
|
||||
return (int) (overtimeHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod);
|
||||
return overtimeHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getWorkingPeriodCostOfFullTimeEmployeesPaidAtOvertimeHourlyRate () {
|
||||
return (int) (overtimeHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod);
|
||||
return overtimeHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMaxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork () {
|
||||
return (int) (maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod);
|
||||
return maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMaxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork () {
|
||||
return (int) (maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod);
|
||||
return maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees () {
|
||||
return (int) (minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees / this.hoursPerWorkPeriod);
|
||||
return minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees () {
|
||||
return (int) (minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees / this.hoursPerWorkPeriod);
|
||||
return minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMaxWorkingPeriodsOfPartTimeEmployeesPerSchedule () {
|
||||
return (int) (this.maxWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
|
||||
return this.maxWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMaxWorkingPeriodsOfFullTimeEmployeesPerSchedule () {
|
||||
return (int) (this.maxWorkingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
|
||||
return this.maxWorkingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
public int getMinWorkingPeriodsOfPartTimeEmployeesPerSchedule () {
|
||||
return (int) (this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
|
||||
return this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
|
||||
|
||||
}
|
||||
|
||||
public int getWorkingPeriodsOfFullTimeEmployeesPerSchedule () {
|
||||
return (int) (this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
|
||||
return this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
|
||||
}
|
||||
|
||||
// A implementer plus tard si l'on veut travailler avec des fichiers texte
|
||||
|
|
|
@ -5,20 +5,21 @@
|
|||
*/
|
||||
package InitialSchedules;
|
||||
|
||||
import java.util.List;
|
||||
import org.chocosolver.solver.Solution;
|
||||
import org.chocosolver.solver.Solver;
|
||||
import org.chocosolver.solver.exception.ContradictionException;
|
||||
import org.chocosolver.solver.search.limits.BacktrackCounter;
|
||||
import org.chocosolver.solver.search.restart.MonotonicRestartStrategy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author frabe
|
||||
*/
|
||||
public class SolverInitialSchedules {
|
||||
|
||||
Solver solverInitialSchedules;
|
||||
|
||||
private final Solver solverInitialSchedules;
|
||||
|
||||
public SolverInitialSchedules (ModelFullTimeEmployeesInitialSchedules myModelFullTimeEmployeesInitialSchedules){
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ import org.chocosolver.solver.variables.IntVar;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class ValidDailySchedules {
|
||||
class ValidDailySchedules {
|
||||
|
||||
int[][] ValidSchedules;
|
||||
private int nbSolutions;
|
||||
private final int[][] ValidSchedules;
|
||||
private final int nbSolutions;
|
||||
|
||||
ValidDailySchedules(int nbPeriodes, int nbPeriodesTravailleesMin, int nbPeriodesTravailleesMax, int p1Min, int p1Max, int p2Min, int p2Max, int nbMaxConsecutif) {
|
||||
ValidDailySchedules(int nbPeriodes, int nbPeriodesTravailleesMin, int nbPeriodesTravailleesMax, int p1Max, int p2Min, int p2Max, int nbMaxConsecutif) {
|
||||
|
||||
Model model = new Model("Horaire de " + nbPeriodes + "-periodes");
|
||||
BoolVar[] horaire = new BoolVar[nbPeriodes];
|
||||
|
@ -21,14 +21,14 @@ public class ValidDailySchedules {
|
|||
horaire[p] = model.boolVar("P_" + p);
|
||||
}
|
||||
|
||||
BoolVar[] horaires1 = new BoolVar[p1Max - p1Min];
|
||||
BoolVar[] horaires2 = new BoolVar[p1Max - p1Min];
|
||||
BoolVar[] horaires1 = new BoolVar[p1Max - 0];
|
||||
BoolVar[] horaires2 = new BoolVar[p1Max - 0];
|
||||
|
||||
IntVar sumhoraire1 = model.intVar("SP_1", 0, nbPeriodes);
|
||||
IntVar sumhoraire2 = model.intVar("SP_2", 0, nbPeriodes);
|
||||
|
||||
for (int p = 0; p < p1Max - p1Min; p++) horaires1[p] = horaire[p1Min + p];
|
||||
for (int p = 0; p < p2Max - p2Min; p++) horaires2[p] = horaire[p2Min + p];
|
||||
System.arraycopy(horaire, 0 + 0, horaires1, 0, p1Max - 0);
|
||||
System.arraycopy(horaire, p2Min + 0, horaires2, 0, p2Max - p2Min);
|
||||
|
||||
/* Travaille entre le nombre minimum et maximum de périodes */
|
||||
model.sum(horaire, ">=", nbPeriodesTravailleesMin).post();
|
||||
|
|
|
@ -2,8 +2,8 @@ package InitialSchedules;
|
|||
|
||||
import org.chocosolver.solver.constraints.extension.Tuples;
|
||||
|
||||
public class ValidPartTimeEmployeeShift {
|
||||
int[][] shiftsOfPartTimeEmployees;
|
||||
class ValidPartTimeEmployeeShift {
|
||||
private final int[][] shiftsOfPartTimeEmployees;
|
||||
|
||||
public ValidPartTimeEmployeeShift() {
|
||||
this.shiftsOfPartTimeEmployees = new int[][]{
|
||||
|
|
|
@ -2,6 +2,9 @@ import AbsenceSchedules.*;
|
|||
import InitialSchedules.*;
|
||||
import ScheduleUtil.*;
|
||||
import SchedulesRecovery.*;
|
||||
import VariableDemandSchedules.BankVariableDemandSchedules;
|
||||
import VariableDemandSchedules.ParametersVariableDemandSimulator;
|
||||
import VariableDemandSchedules.VariableDemandSchedulesArray;
|
||||
import jdistlib.rng.MersenneTwister;
|
||||
import jdistlib.rng.RandomEngine;
|
||||
import org.chocosolver.solver.Solution;
|
||||
|
@ -10,6 +13,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class MainClass {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -24,17 +28,20 @@ public class MainClass {
|
|||
|
||||
List<SchedulesArray> initialSchedulesArrayList = generateInitialSchedules();
|
||||
|
||||
//List<BankVariableDemandSchedules> listBankVariableDemandSchedules = GenerateModifiedDemandSchedules(initialSchedulesArrayList);
|
||||
|
||||
List<BankAbsenceSchedules> listBankAbsenceSchedules = GenerateAbsencesSchedules(initialSchedulesArrayList);
|
||||
|
||||
List<BankRecoveredSchedules> bankRecoveredSchedulesOrderedByMeanCost = GenerateOptimalRecoveredSchedules(listBankAbsenceSchedules);
|
||||
|
||||
SchedulesWindows.ShowSolutionResultsFrame initialSchedulesViewer = new SchedulesWindows.ShowSolutionResultsFrame(bankRecoveredSchedulesOrderedByMeanCost);
|
||||
@SuppressWarnings("unused") SchedulesWindows.ShowSolutionResultsFrame initialSchedulesViewer = new SchedulesWindows.ShowSolutionResultsFrame(bankRecoveredSchedulesOrderedByMeanCost);
|
||||
|
||||
// int optimalFullTimeEmployee = bankRecoveredSchedulesOrderedByMeanCost.get(0).initialSchedulesArray.getNumberFullTimeEmployee();
|
||||
// System.out.println(optimalFullTimeEmployee + " ");
|
||||
// }
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static List<SchedulesArray> generateInitialSchedules() {
|
||||
|
||||
// Trouver les horaires des employes a temps plein possibles pour different ratio templein/temps partiel
|
||||
|
@ -90,6 +97,25 @@ public class MainClass {
|
|||
|
||||
}
|
||||
|
||||
private static List<BankVariableDemandSchedules> GenerateModifiedDemandSchedules(List<SchedulesArray> initialSchedulesArrayList) {
|
||||
RandomEngine r = new MersenneTwister(987654321);
|
||||
List<BankVariableDemandSchedules> listBankVariableDemandSchedules = new ArrayList<>();
|
||||
List<SchedulesArray> listVariableDemandSchedules = new ArrayList<>(); // to be removed
|
||||
for (SchedulesArray initialSchedule : initialSchedulesArrayList) {
|
||||
BankVariableDemandSchedules bankVariableDemandSimulations = new BankVariableDemandSchedules(initialSchedule);
|
||||
for (int simNum = 0; simNum < ParametersVariableDemandSimulator.numberVariableDemandSimulation ; simNum++){
|
||||
VariableDemandSchedulesArray variableDemandSchedule = new VariableDemandSchedulesArray(initialSchedule,r);
|
||||
listVariableDemandSchedules.add(variableDemandSchedule);
|
||||
bankVariableDemandSimulations.addVariableDemandSchedules(variableDemandSchedule);
|
||||
}
|
||||
listBankVariableDemandSchedules.add(bankVariableDemandSimulations);
|
||||
}
|
||||
// Pour afficher les horaires avec demande modifiée
|
||||
SchedulesWindows.ShowSchedulesFrame variableDemandSchedulesViewer = new SchedulesWindows.ShowSchedulesFrame(listVariableDemandSchedules,"Variable Demand Schedules");
|
||||
|
||||
return listBankVariableDemandSchedules;
|
||||
}
|
||||
|
||||
private static List<BankAbsenceSchedules> GenerateAbsencesSchedules(List<SchedulesArray> initialSchedulesArrayList) {
|
||||
|
||||
RandomEngine r = new MersenneTwister(123456789);
|
||||
|
|
|
@ -8,6 +8,8 @@ package ScheduleUtil;
|
|||
import AbsenceSchedules.AbsenceSchedulesArray;
|
||||
import InitialSchedules.ParametersInitialSchedules;
|
||||
import SchedulesRecovery.RecoveredSchedulesArray;
|
||||
import VariableDemandSchedules.VariableDemandSchedulesArray;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author frabe
|
||||
|
@ -28,6 +30,18 @@ public class EmployeeCostCalculator {
|
|||
}
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
public static int getFullVariableDemandScheduleCost( VariableDemandSchedulesArray myVariableDemandSchedule, ParametersInitialSchedules myScheduleParameters) {
|
||||
int totalCost = 0;
|
||||
|
||||
/* Coût spécifique à une augmentation de la demande */
|
||||
for(int p=0;p<myScheduleParameters.getWorkPeriodsPerSchedule();p++){
|
||||
totalCost += (myVariableDemandSchedule.getInitialSchedulesArrayVariableDemand().myParametersInitialSchedules.getRequiredWorkForce(p)-myScheduleParameters.getRequiredWorkForce(p))*
|
||||
myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate()*1.5;
|
||||
}
|
||||
totalCost += getFullInitialScheduleCost(myVariableDemandSchedule.getInitialSchedulesArray(),myScheduleParameters);
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
public static int getFullAbsenceScheduleCost( AbsenceSchedulesArray myAbsenceSchedule, ParametersInitialSchedules myScheduleParameters) {
|
||||
int totalCost = 0;
|
||||
|
@ -76,17 +90,20 @@ public class EmployeeCostCalculator {
|
|||
public static int getPartTimeEmployeeCost(boolean[][] currentEmployeesSchedule, int employee, ParametersInitialSchedules myScheduleParameters) {
|
||||
int numberWorkingPeriod = 0;
|
||||
for (int workPeriod = 0 ; workPeriod < currentEmployeesSchedule.length ; workPeriod++) {
|
||||
if (currentEmployeesSchedule[employee][workPeriod] == true){numberWorkingPeriod++;}
|
||||
if (currentEmployeesSchedule[employee][workPeriod]) {
|
||||
numberWorkingPeriod++;
|
||||
}
|
||||
}
|
||||
int totalCost = myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule() +
|
||||
return myScheduleParameters.getFixedCostOfPartTimeEmployeesPerSchedule() +
|
||||
numberWorkingPeriod * myScheduleParameters.getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate();
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
public static int getFullTimeEmployeeCost(boolean[][] currentEmployeesSchedule, AbsenceSchedulesArray myAbsenceSchedule, int employee, ParametersInitialSchedules myScheduleParameters) {
|
||||
int numberWorkingPeriod = 0;
|
||||
for (int workPeriod = 0 ; workPeriod < currentEmployeesSchedule.length ; workPeriod++) {
|
||||
if (currentEmployeesSchedule[employee][workPeriod] == true){numberWorkingPeriod++;}
|
||||
if (currentEmployeesSchedule[employee][workPeriod]) {
|
||||
numberWorkingPeriod++;
|
||||
}
|
||||
}
|
||||
int numberAbsencePeriod = myAbsenceSchedule.getAbsencePeriodsPerFullTimeEmployees(employee);
|
||||
int regularHourlyRateCost; int overtimeHourlyRateCost;
|
||||
|
@ -99,7 +116,6 @@ public class EmployeeCostCalculator {
|
|||
overtimeHourlyRateCost = (numberWorkingPeriod + numberAbsencePeriod - myScheduleParameters.getWorkingPeriodsPaidAtRegularHourlyRatePerSchedule()) *
|
||||
myScheduleParameters.getWorkingPeriodCostOfFullTimeEmployeesPaidAtOvertimeHourlyRate();
|
||||
}
|
||||
int totalCost = myScheduleParameters.getFixedCostOfFullTimeEmployeesPerSchedule() + regularHourlyRateCost + overtimeHourlyRateCost;
|
||||
return totalCost;
|
||||
return myScheduleParameters.getFixedCostOfFullTimeEmployeesPerSchedule() + regularHourlyRateCost + overtimeHourlyRateCost;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
package ScheduleUtil;
|
||||
|
||||
import InitialSchedules.*;
|
||||
import InitialSchedules.ModelFullTimeEmployeesInitialSchedules;
|
||||
import InitialSchedules.ParametersInitialSchedules;
|
||||
import org.chocosolver.solver.Solution;
|
||||
|
||||
/**
|
||||
|
@ -14,20 +15,19 @@ import org.chocosolver.solver.Solution;
|
|||
*/
|
||||
public class FullTimeEmployeeScheduleArray {
|
||||
public int initialScheduleSolutionNumber;
|
||||
public boolean[][] fullTimeSchedules;
|
||||
protected ParametersInitialSchedules myParametersInitialSchedules;
|
||||
public final boolean[][] fullTimeSchedules;
|
||||
final ParametersInitialSchedules myParametersInitialSchedules;
|
||||
|
||||
public FullTimeEmployeeScheduleArray(ModelFullTimeEmployeesInitialSchedules m, Solution s) {
|
||||
this.myParametersInitialSchedules = m.myScheduleParameters;
|
||||
Solution mySolution = s;
|
||||
|
||||
|
||||
this.fullTimeSchedules = new boolean[getNumberOfFullTimeEmployees(s, m)][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
|
||||
|
||||
int fullTimeEmployee = 0;
|
||||
for (int i = 0; i < m.numberOfFullTimeEmployees; i++) {
|
||||
if (isFullTimeEmployeeActive (i, s, m)) {
|
||||
for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
|
||||
this.fullTimeSchedules[fullTimeEmployee][workPeriod] = mySolution.getIntVal(m.workPeriodsSchedulesOfFullTimeEmployees[i][workPeriod]) == 1;
|
||||
this.fullTimeSchedules[fullTimeEmployee][workPeriod] = s.getIntVal(m.workPeriodsSchedulesOfFullTimeEmployees[i][workPeriod]) == 1;
|
||||
}
|
||||
fullTimeEmployee++;
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ public class FullTimeEmployeeScheduleArray {
|
|||
}
|
||||
return employeesWorking;
|
||||
}
|
||||
|
||||
public int getNumberFullTimeEmployee() {
|
||||
|
||||
private int getNumberFullTimeEmployee() {
|
||||
return this.fullTimeSchedules.length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package ScheduleUtil;
|
||||
|
||||
import InitialSchedules.*;
|
||||
import InitialSchedules.ModelPartTimeEmployeesInitialSchedules;
|
||||
import InitialSchedules.ParametersInitialSchedules;
|
||||
import org.chocosolver.solver.Solution;
|
||||
|
||||
|
@ -15,20 +15,19 @@ import org.chocosolver.solver.Solution;
|
|||
*/
|
||||
public class PartTimeEmployeeScheduleArray {
|
||||
public int initialScheduleSolutionNumber;
|
||||
public boolean[][] partTimeSchedules;
|
||||
protected ParametersInitialSchedules myParametersInitialSchedules;
|
||||
public final boolean[][] partTimeSchedules;
|
||||
private final ParametersInitialSchedules myParametersInitialSchedules;
|
||||
|
||||
public PartTimeEmployeeScheduleArray(ModelPartTimeEmployeesInitialSchedules m, Solution s) {
|
||||
this.myParametersInitialSchedules = m.myScheduleParameters;
|
||||
Solution mySolution = s;
|
||||
|
||||
|
||||
this.partTimeSchedules = new boolean[getNumberOfFullTimeEmployees(s, m)][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
|
||||
|
||||
int partTimeEmployee = 0;
|
||||
for (int i = 0; i < m.maxPartTimeEmployee; i++) {
|
||||
if (isPartTimeEmployeeActive (i, s, m)) {
|
||||
for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
|
||||
this.partTimeSchedules[partTimeEmployee][workPeriod] = mySolution.getIntVal(m.workPeriodsSchedulesOfPartTimeEmployees[i][workPeriod]) == 1;
|
||||
this.partTimeSchedules[partTimeEmployee][workPeriod] = s.getIntVal(m.workPeriodsSchedulesOfPartTimeEmployees[i][workPeriod]) == 1;
|
||||
}
|
||||
partTimeEmployee++;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
*/
|
||||
package ScheduleUtil;
|
||||
|
||||
import InitialSchedules.*;
|
||||
import org.chocosolver.solver.Solution;
|
||||
import InitialSchedules.ParametersInitialSchedules;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -14,11 +13,11 @@ import org.chocosolver.solver.Solution;
|
|||
*/
|
||||
//Dans cette classe, toutes les fonctions sont dedoublees. On devrait faire du polymorphisme.
|
||||
public class SchedulesArray {
|
||||
public int initialScheduleSolutionNumber;
|
||||
public final int initialScheduleSolutionNumber;
|
||||
public boolean[][] partTimeSchedules;
|
||||
public boolean[][] fullTimeSchedules;
|
||||
public int totalScheduleCost;
|
||||
protected ParametersInitialSchedules myParametersInitialSchedules;
|
||||
protected final ParametersInitialSchedules myParametersInitialSchedules;
|
||||
|
||||
// Constructeur Copie
|
||||
protected SchedulesArray(SchedulesArray myScheduleArray) {
|
||||
|
@ -39,6 +38,26 @@ public class SchedulesArray {
|
|||
|
||||
this.totalScheduleCost = EmployeeCostCalculator.getFullInitialScheduleCost(this, myParametersInitialSchedules);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates a SchedulesArray with a modified required workforce vector
|
||||
*
|
||||
* @param myParametersInitialSchedules Parameters from initial schedule
|
||||
* @param fteisa initial schedules array for full time employees
|
||||
* @param pteisa initial schedules array for part time employees
|
||||
* @param scheduleNumber Schedule number that comes from the initial Choco solution
|
||||
* @param VariableDemandVector new required workforce vector
|
||||
*/
|
||||
public SchedulesArray(ParametersInitialSchedules myParametersInitialSchedules, boolean[][] fteisa, boolean[][] pteisa, int scheduleNumber, int[] VariableDemandVector) {
|
||||
|
||||
this.initialScheduleSolutionNumber = scheduleNumber;
|
||||
this.myParametersInitialSchedules = myParametersInitialSchedules;
|
||||
this.myParametersInitialSchedules.setRequiredWorkforce(VariableDemandVector);
|
||||
|
||||
this.partTimeSchedules = getDeepCopyEmployeesSchedules(pteisa);
|
||||
this.fullTimeSchedules = getDeepCopyEmployeesSchedules(fteisa);
|
||||
}
|
||||
|
||||
protected boolean[][] getDeepCopyEmployeesSchedules(boolean[][] schedules) {
|
||||
int nbrEmployee = schedules.length;
|
||||
|
@ -58,20 +77,22 @@ public class SchedulesArray {
|
|||
if (this.partTimeSchedules[employee][workPeriod]) {employeesWorking += 1;}
|
||||
}
|
||||
for (int employee = 0; employee < this.getNumberFullTimeEmployee(); employee++) {
|
||||
if (this.fullTimeSchedules[employee][workPeriod]) {employeesWorking += 1;}
|
||||
if (this.fullTimeSchedules[employee][workPeriod]) {
|
||||
employeesWorking += 1;
|
||||
}
|
||||
}
|
||||
return employeesWorking;
|
||||
}
|
||||
|
||||
protected int getWorkingPeriodsPerPartTimeEmployees(int employee) {
|
||||
|
||||
public int getWorkingPeriodsPerPartTimeEmployees(int employee) {
|
||||
int workingPeriodsPerPartTimeEmployees = 0;
|
||||
for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
|
||||
if (this.partTimeSchedules[employee][workPeriod]) {workingPeriodsPerPartTimeEmployees += 1;}
|
||||
}
|
||||
return workingPeriodsPerPartTimeEmployees;
|
||||
}
|
||||
|
||||
protected int getWorkingPeriodsPerFullTimeEmployees(int employee) {
|
||||
|
||||
public int getWorkingPeriodsPerFullTimeEmployees(int employee) {
|
||||
int workingPeriodsPerFullTimeEmployees = 0;
|
||||
for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
|
||||
if (this.fullTimeSchedules[employee][workPeriod]) {workingPeriodsPerFullTimeEmployees += 1;}
|
||||
|
@ -92,11 +113,11 @@ public class SchedulesArray {
|
|||
}
|
||||
|
||||
public boolean isPartTimeEmployeeWorking(int employee, int workPeriod) {
|
||||
return partTimeSchedules[employee][workPeriod] == true;
|
||||
return partTimeSchedules[employee][workPeriod];
|
||||
}
|
||||
|
||||
public boolean isFullTimeEmployeeWorking(int employee, int workPeriod) {
|
||||
return fullTimeSchedules[employee][workPeriod] == true;
|
||||
return fullTimeSchedules[employee][workPeriod];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package SchedulesRecovery;
|
|||
|
||||
import AbsenceSchedules.AbsenceSchedulesArray;
|
||||
import ScheduleUtil.SchedulesArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -15,9 +16,9 @@ import java.util.List;
|
|||
* @author frabe
|
||||
*/
|
||||
public class BankRecoveredSchedules {
|
||||
public SchedulesArray initialSchedulesArray;
|
||||
public List<SchedulesArray> bankRecoveredSimulation;
|
||||
public List<AbsenceSchedulesArray> bankAbsenceSimulation;
|
||||
public final SchedulesArray initialSchedulesArray;
|
||||
public final List<SchedulesArray> bankRecoveredSimulation;
|
||||
private final List<AbsenceSchedulesArray> bankAbsenceSimulation;
|
||||
public double meanCostRecoveredSimulations;
|
||||
|
||||
public BankRecoveredSchedules(SchedulesArray initialSchedulesArray, List<AbsenceSchedulesArray> bankAbsenceSimulation) {
|
||||
|
|
|
@ -17,7 +17,6 @@ public class BankRecoveredSchedulesComparator implements Comparator< BankRecover
|
|||
if (meanCostCmp !=0) {
|
||||
return meanCostCmp;
|
||||
}
|
||||
int simNumberCmp = Integer.compare(b1.initialSchedulesArray.initialScheduleSolutionNumber, b2.initialSchedulesArray.initialScheduleSolutionNumber);
|
||||
return simNumberCmp;
|
||||
return Integer.compare(b1.initialSchedulesArray.initialScheduleSolutionNumber, b2.initialSchedulesArray.initialScheduleSolutionNumber);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,19 @@
|
|||
package SchedulesRecovery;
|
||||
|
||||
import AbsenceSchedules.AbsenceSchedulesArray;
|
||||
import ScheduleUtil.EmployeeCostCalculator;
|
||||
import ScheduleUtil.SchedulesArray;
|
||||
|
||||
import java.util.*;
|
||||
import ScheduleUtil.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author frabe
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class RecoveredSchedulesArray extends SchedulesArray{
|
||||
|
||||
public AbsenceSchedulesArray absenceSchedulesArray;
|
||||
|
||||
public final AbsenceSchedulesArray absenceSchedulesArray;
|
||||
|
||||
public RecoveredSchedulesArray(AbsenceSchedulesArray absenceSchedulesArray){
|
||||
super(absenceSchedulesArray);
|
||||
|
@ -140,7 +143,7 @@ public class RecoveredSchedulesArray extends SchedulesArray{
|
|||
&& !alreadyRecoveredWorkPeriodByPartTimeEmployees[partTimeEmployee][remainingRecoveringAction-1]){
|
||||
RecoveringActionPartTimeEmployee recoveringAction =
|
||||
new RecoveringActionPartTimeEmployee(partTimeEmployee, workPeriod);
|
||||
recoveringAction.calculateRecoveringActionCost (currentPartTimeSchedule, absenceSchedulesArray, myParametersInitialSchedules);
|
||||
recoveringAction.calculateRecoveringActionCost(currentPartTimeSchedule, myParametersInitialSchedules);
|
||||
recoveringActionsOrderedByCost.add(recoveringAction);
|
||||
}
|
||||
}
|
||||
|
@ -162,13 +165,13 @@ public class RecoveredSchedulesArray extends SchedulesArray{
|
|||
int workingEmployees;
|
||||
for (int workPeriod = 0 ; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule() ; workPeriod++) {
|
||||
workingEmployees = 0;
|
||||
for (int partTimeEmployee = 0 ; partTimeEmployee < currentPartTimeSchedule.length ; partTimeEmployee++) {
|
||||
if ( currentPartTimeSchedule[partTimeEmployee][workPeriod] ) {
|
||||
for (boolean[] aCurrentPartTimeSchedule : currentPartTimeSchedule) {
|
||||
if (aCurrentPartTimeSchedule[workPeriod]) {
|
||||
workingEmployees++;
|
||||
}
|
||||
}
|
||||
for (int fullTimeEmployee = 0 ; fullTimeEmployee < currentFullTimeSchedule.length ; fullTimeEmployee++) {
|
||||
if ( currentFullTimeSchedule[fullTimeEmployee][workPeriod] ) {
|
||||
for (boolean[] aCurrentFullTimeSchedule : currentFullTimeSchedule) {
|
||||
if (aCurrentFullTimeSchedule[workPeriod]) {
|
||||
workingEmployees++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ package SchedulesRecovery;
|
|||
*
|
||||
* @author frabe
|
||||
*/
|
||||
public class RecoveringAction {
|
||||
public int employee;
|
||||
public int workPeriod;
|
||||
class RecoveringAction {
|
||||
public final int employee;
|
||||
public final int workPeriod;
|
||||
public int recoveringActionCost;
|
||||
|
||||
public RecoveringAction( int employee, int workPeriod){
|
||||
|
||||
RecoveringAction(int employee, int workPeriod) {
|
||||
this.employee = employee;
|
||||
this.workPeriod = workPeriod;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.util.Comparator;
|
|||
* @author frabe
|
||||
|
||||
*/
|
||||
public class RecoveringActionComparator implements Comparator< RecoveringAction > {
|
||||
class RecoveringActionComparator implements Comparator<RecoveringAction> {
|
||||
public int compare(RecoveringAction a2, RecoveringAction a1) {
|
||||
return Integer.compare(a1.recoveringActionCost, a2.recoveringActionCost);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ package SchedulesRecovery;
|
|||
|
||||
import AbsenceSchedules.AbsenceSchedulesArray;
|
||||
import InitialSchedules.ParametersInitialSchedules;
|
||||
import ScheduleUtil.*;
|
||||
import ScheduleUtil.EmployeeCostCalculator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author frabe
|
||||
*/
|
||||
public class RecoveringActionFullTimeEmployee extends RecoveringAction{
|
||||
class RecoveringActionFullTimeEmployee extends RecoveringAction {
|
||||
|
||||
public RecoveringActionFullTimeEmployee( int employee, int workPeriod){
|
||||
super(employee, workPeriod);
|
||||
|
|
|
@ -5,21 +5,20 @@
|
|||
*/
|
||||
package SchedulesRecovery;
|
||||
|
||||
import AbsenceSchedules.AbsenceSchedulesArray;
|
||||
import InitialSchedules.ParametersInitialSchedules;
|
||||
import ScheduleUtil.*;
|
||||
import ScheduleUtil.EmployeeCostCalculator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author frabe
|
||||
*/
|
||||
public class RecoveringActionPartTimeEmployee extends RecoveringAction{
|
||||
class RecoveringActionPartTimeEmployee extends RecoveringAction {
|
||||
|
||||
public RecoveringActionPartTimeEmployee( int employee, int workPeriod){
|
||||
super(employee, workPeriod);
|
||||
}
|
||||
|
||||
public void calculateRecoveringActionCost ( boolean[][] currentEmployeesSchedule,AbsenceSchedulesArray absenceSchedulesArray, ParametersInitialSchedules myScheduleParameters) {
|
||||
|
||||
public void calculateRecoveringActionCost(boolean[][] currentEmployeesSchedule, ParametersInitialSchedules myScheduleParameters) {
|
||||
int costBeforeAction = EmployeeCostCalculator.getPartTimeEmployeeCost(currentEmployeesSchedule, this.employee, myScheduleParameters);
|
||||
currentEmployeesSchedule[this.employee][this.workPeriod] = true;
|
||||
int costAfterAction = EmployeeCostCalculator.getPartTimeEmployeeCost(currentEmployeesSchedule, this.employee, myScheduleParameters);
|
||||
|
|
|
@ -14,7 +14,7 @@ import InitialSchedules.ParametersInitialSchedules;
|
|||
*/
|
||||
|
||||
// classe statique pour mettre fonction utilitaire
|
||||
public class ValidationRecoveringAction {
|
||||
class ValidationRecoveringAction {
|
||||
|
||||
//Toutes les fonctions sont dedoublees. On devrait faire du polymorphisme.
|
||||
static boolean isPartTimeEmployeeAvailableForAbsenceRecovering(boolean[][] currentPartTimeSchedule, ParametersInitialSchedules myScheduleParameters,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package SchedulesWindows;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -13,8 +13,8 @@ import java.util.*;
|
|||
*/
|
||||
public class ShowSchedulesFrame extends javax.swing.JFrame {
|
||||
|
||||
private List<ScheduleUtil.SchedulesArray> schedulesArrayList;
|
||||
private String title;
|
||||
private final List<ScheduleUtil.SchedulesArray> schedulesArrayList;
|
||||
private final String title;
|
||||
/**
|
||||
* Creates new form ShowSchedulesFrame
|
||||
**/
|
||||
|
@ -40,20 +40,16 @@ public class ShowSchedulesFrame extends javax.swing.JFrame {
|
|||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
mainPanel = new javax.swing.JPanel();
|
||||
javax.swing.JPanel mainPanel = new javax.swing.JPanel();
|
||||
changeScheduleNumberScrollBar = new javax.swing.JScrollBar();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
|
||||
scheduleViewerArea = new javax.swing.JTextArea();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
javax.swing.JLabel jLabel1 = new javax.swing.JLabel();
|
||||
textSolutionNumber = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
|
||||
changeScheduleNumberScrollBar.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
|
||||
public void adjustmentValueChanged(java.awt.event.AdjustmentEvent evt) {
|
||||
changeScheduleNumberScrollBarAdjustmentValueChanged(evt);
|
||||
}
|
||||
});
|
||||
changeScheduleNumberScrollBar.addAdjustmentListener(evt -> changeScheduleNumberScrollBarAdjustmentValueChanged(evt));
|
||||
|
||||
scheduleViewerArea.setEditable(false);
|
||||
scheduleViewerArea.setColumns(20);
|
||||
|
@ -124,9 +120,6 @@ public class ShowSchedulesFrame extends javax.swing.JFrame {
|
|||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JScrollBar changeScheduleNumberScrollBar;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JPanel mainPanel;
|
||||
private javax.swing.JTextArea scheduleViewerArea;
|
||||
private javax.swing.JLabel textSolutionNumber;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
package SchedulesWindows;
|
||||
|
||||
import SchedulesRecovery.BankRecoveredSchedules;
|
||||
import java.util.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -14,7 +15,7 @@ import java.util.*;
|
|||
*/
|
||||
public class ShowSolutionResultsFrame extends javax.swing.JFrame {
|
||||
|
||||
private List< BankRecoveredSchedules > bankRecoveredSchedulesOrderedByMeanCost;
|
||||
private final List<BankRecoveredSchedules> bankRecoveredSchedulesOrderedByMeanCost;
|
||||
/**
|
||||
* Creates new form ShowSchedulesFrame
|
||||
*/
|
||||
|
@ -39,22 +40,18 @@ public class ShowSolutionResultsFrame extends javax.swing.JFrame {
|
|||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
mainPanel = new javax.swing.JPanel();
|
||||
javax.swing.JPanel mainPanel = new javax.swing.JPanel();
|
||||
changeScheduleNumberScrollBar = new javax.swing.JScrollBar();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
|
||||
scheduleViewerArea = new javax.swing.JTextArea();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
javax.swing.JLabel jLabel1 = new javax.swing.JLabel();
|
||||
textSolutionNumber = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
setPreferredSize(new java.awt.Dimension(1400, 600));
|
||||
setSize(new java.awt.Dimension(1000, 600));
|
||||
|
||||
changeScheduleNumberScrollBar.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
|
||||
public void adjustmentValueChanged(java.awt.event.AdjustmentEvent evt) {
|
||||
changeScheduleNumberScrollBarAdjustmentValueChanged(evt);
|
||||
}
|
||||
});
|
||||
changeScheduleNumberScrollBar.addAdjustmentListener(evt -> changeScheduleNumberScrollBarAdjustmentValueChanged(evt));
|
||||
|
||||
scheduleViewerArea.setEditable(false);
|
||||
scheduleViewerArea.setColumns(20);
|
||||
|
@ -130,9 +127,6 @@ public class ShowSolutionResultsFrame extends javax.swing.JFrame {
|
|||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JScrollBar changeScheduleNumberScrollBar;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JPanel mainPanel;
|
||||
private javax.swing.JTextArea scheduleViewerArea;
|
||||
private javax.swing.JLabel textSolutionNumber;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package VariableDemandSchedules;
|
||||
|
||||
import ScheduleUtil.SchedulesArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BankVariableDemandSchedules {
|
||||
public final SchedulesArray initialSchedulesArray;
|
||||
public final List<VariableDemandSchedulesArray> bankVariableDemandSimulation;
|
||||
|
||||
public BankVariableDemandSchedules(SchedulesArray initialSchedulesArray) {
|
||||
this.initialSchedulesArray = initialSchedulesArray;
|
||||
this.bankVariableDemandSimulation = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addVariableDemandSchedules(VariableDemandSchedulesArray variableDemandSchedulesArray) {
|
||||
this.bankVariableDemandSimulation.add(variableDemandSchedulesArray);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package VariableDemandSchedules;
|
||||
|
||||
public class ParametersVariableDemandSimulator {
|
||||
public static final int numberVariableDemandSimulation = 1;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package VariableDemandSchedules;
|
||||
|
||||
import ScheduleUtil.EmployeeCostCalculator;
|
||||
import ScheduleUtil.SchedulesArray;
|
||||
import jdistlib.rng.RandomEngine;
|
||||
|
||||
public class VariableDemandSchedulesArray extends SchedulesArray {
|
||||
private final SchedulesArray initialSchedulesArray;
|
||||
private SchedulesArray initialSchedulesArrayVariableDemand;
|
||||
|
||||
public VariableDemandSchedulesArray(SchedulesArray initialSchedulesArray, RandomEngine r) {
|
||||
super(initialSchedulesArray);
|
||||
this.initialSchedulesArray = initialSchedulesArray;
|
||||
generateDemandSimulation(r);
|
||||
this.totalScheduleCost = EmployeeCostCalculator.getFullVariableDemandScheduleCost(this, myParametersInitialSchedules);
|
||||
}
|
||||
|
||||
private void generateDemandSimulation(RandomEngine r) {
|
||||
int[] vd = new VariableDemandVector(this.myParametersInitialSchedules.getWorkPeriodsPerSchedule(), r).getVariableDemandVector();
|
||||
int[] adjd = new int[this.myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
|
||||
for (int p = 0; p < this.myParametersInitialSchedules.getWorkPeriodsPerSchedule(); p++) {
|
||||
adjd[p] = /*this.myParametersInitialSchedules.getRequiredWorkForce(p) + */vd[p];
|
||||
}
|
||||
|
||||
this.initialSchedulesArrayVariableDemand = new SchedulesArray(
|
||||
myParametersInitialSchedules,
|
||||
initialSchedulesArray.fullTimeSchedules,
|
||||
initialSchedulesArray.partTimeSchedules,
|
||||
initialSchedulesArray.initialScheduleSolutionNumber,
|
||||
adjd);
|
||||
}
|
||||
|
||||
public SchedulesArray getInitialSchedulesArrayVariableDemand() {
|
||||
return initialSchedulesArrayVariableDemand;
|
||||
}
|
||||
|
||||
public SchedulesArray getInitialSchedulesArray() {
|
||||
return initialSchedulesArray;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package VariableDemandSchedules;
|
||||
|
||||
import jdistlib.Binomial;
|
||||
import jdistlib.rng.RandomEngine;
|
||||
|
||||
public class VariableDemandVector {
|
||||
private int[] VariableDemandVector;
|
||||
|
||||
VariableDemandVector(int length, RandomEngine r) {
|
||||
VariableDemandVector = new int[length];
|
||||
Binomial p1 = new Binomial(1,0.5);
|
||||
p1.setRandomEngine(r);
|
||||
for (int i = 0; i < length; i++) {
|
||||
VariableDemandVector[i] = (int) p1.random();
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getVariableDemandVector() {
|
||||
return VariableDemandVector;
|
||||
}
|
||||
}
|