Originally posted by: SanaeB
Hi Alex,
When i run a config, i have the error "file not found". I already red what you answered to other users and i can tell you that:
.MOD:
/*********************************************
* OPL 12.8.0.0 Model
* Author: Sanae
* Creation Date: 2018-09-18 at 11:06:13
*********************************************/
//DONNEES
int NE=...; // Nombre d'Employés
float TH=...; // Taux horaire de chaque employé
int NC=...; //Nombre de commandes
setof(int) COMMANDES= asSet(1..NC); //Ensemble des commandes
int NT[COMMANDES]=...;// Nombre de tâches pour chaque commande
int NU[COMMANDES]=...;// Nombre d'unités par commande'
int NTMax=max(c in COMMANDES) NT[c]; // permet de calculer le nombre maximal de tâches toutes commandes confondues
int NTMin=min(c in COMMANDES) NT[c]; // on pourrait l'utiliser pour s'assurer que les données en entrée sont cohérentes: NSmin doit etre inférieur ou egal à NTMin. pas de lien avec NECMin car des employes peuvent se partager une tache et une tache peut être partagée par plusieurs employés
setof(int) TASKS[c in COMMANDES]= asSet(1..NT[c]);// liste des tâches d'une commmande'
int NSMin=...;// Nombre de stations minimales (le même pour chacune des commandes)
assert NTMin>=NSMin;// permet de s'assurer que la ligne ayant le moindre nombre de tâche est coherente avec la contrainte de nombre de stations minimales'
int NECMin=...;
int NECMax=NE-(NC-1)*maxl(NSMin,NECMin); // Valider Nombre d'Employés maximal par ligne, permet de borner les l et les k. LA vraie formule serait NECMax=NE-(NC-1)*max(NSMin,NECMin)
tuple tasksbis {int c;int i; int j;};
{tasksbis} TASKSBIS= {<c,i,j>|c in COMMANDES, i in TASKS[c], j in TASKS[c] union {NT[c]+1} : j>=i+1}; // l'ensemble des couples de taches d'une commande composé de chaque tache et ses successeurs'
tuple employesbis {int k; int l;};
{employesbis} EMPLOYESBIS= {<k,l>|k,l in 1..NECMax : l>=k && k>=1};
float t[COMMANDES][1..NTMax]=...; // temps de la tâche i (i ayant une positiion 1 à NTmax) de la commande c ayant NT commandes
assert forall(c in COMMANDES, i in 1..NTMax) (i>NT[c]=>t[c][i]==0);// s'assure que les tâches dont l'index depasse NT pour une commande ont un temps nul
float ts [c in 1..NC][i in 1..NTMax][j in 1..NTMax]=sum (l in i..j)(t[c][l]);// temps entre deux taches d'une commande ts cij: doit être du même format que t
float delai[COMMANDES]=...;// donnée ajoutée délai maximal pour chaque commande en heures
float ProductiviteCMin=...;
float ProductiviteUMin=...;
setof (string) TYC={"Ref","NSMin","NECMin","NE","NU","t","NT","delai", "ProducC", "ProducU"};// Utile pour indiquer dans le fichier output le type de contrainte des instances utilisés
// VARIABLES
dvar float+ CT; // coût total à minimiser
dvar int NEC[COMMANDES];// Le nombre d'employés affecté à chaque commande / à voir si ce n'Est pas pluutôt une variable d'expression
dvar boolean X[<c,i,j> in TASKSBIS][<k,l> in EMPLOYESBIS];// déclaration des variables binaires Xcijkl
dvar float+ TCP[COMMANDES][1..NECMax]; // Valider la formulation de la vriable TCPcl (temps de cycle partiel de la ligne de la commande c lorsque l emoloyés y sont affectés)
dexpr float TC[c in COMMANDES] = sum(l in 1..NECMax)TCP[c][l];// équivaut contrainte 15 // Calcul du temps de cycle (avec la solution retenue) d'une ligne a partir des temps de cycle de la ligne avec l employés (TCP)'
dexpr int NS[c in COMMANDES]=sum (i in 1..NT[c], j in i+1..NT[c]+1, k in 1..NECMax, l in k..NECMax ) X[<c,i,j>][<k,l>]; // est-ce que c'Est pas bizarre ici de faire varien c aussi dans le tuple TASKSbis alors que c a deja ete predeterminé pour NS'
dvar boolean Z[COMMANDES][1..NECMax]; //Valider la formulation de la variable, est vrai lorsque l employés sont affectés à la commande c
dvar float coutP[c in COMMANDES][l in 1..NECMax]; // cout de la commande avec l employés qui y sont affectés, sera nul avec les nombres d'employés non retenus'
dexpr float coutC[c in COMMANDES]=sum(l in 1..NECMax) coutP[c][l]; // coût de la commande
dexpr float TPr[c in COMMANDES]=((NU[c])*TC[c])/3600;// temps de production total de la commande en heures car le temps de cycle sera donné en secondes- Hypothèse : toutes les unités prennent le même temps de fabrication: le temps de cycle.
dexpr float ProductiviteS[<c,i,j> in TASKSBIS][<k,l> in EMPLOYESBIS]=(X[<c,i,j>][<k,l>]*ts[c][i][j-1]/k)/TC[c];// Valider. Calcul de la productivité de la station cijkl.
dexpr float ProductiviteC[c in COMMANDES]= sum (i in 1..NT[c], j in i+1..NT[c]+1, k in 1..NECMax, l in k..NECMax) k/l*ProductiviteS[<c,i,j>][<k,l>];//VALIDER Productivité de la commande c. N'accepte pas que je mette NEC en division'
dexpr float ProductiviteU=(sum (c in COMMANDES) ProductiviteC[c]*NEC[c])/sum (c in COMMANDES)NEC[c];
//FONCTION OBJECTIF
minimize CT;
// CONTRAINTES
subject to {
forall (c in COMMANDES)sum (j in 2..NT[c]+1, k in 1..NECMax, l in k..NECMax)X[<c,1,j>][<k,l>]==1; // Contrainte 9
forall (c in COMMANDES,i in asSet(2..NT[c]), l in 1..NECMax) sum (j in 1..(i-1)) sum (k in 1..l)X[<c,j,i>][<k,l>]==sum(j in (i+1)..(NT[c]+1))sum(k in 1..l)X[<c,i,j>][<k,l>]; // Contrainte 10
forall (c in COMMANDES) NEC[c]==sum(i in 1..NT[c], j in i+1..NT[c]+1, k in 1..NECMax, l in k..NECMax) k*X[<c,i,j>][<k,l>];// premiere moitié de la contrainte 11 // Valider variation début et de fin de k. es fois c'est k qui est en fonction de l et des fois c l qui en fonction de k'
forall (c in COMMANDES) NEC[c]== sum(j in 2..NT[c]+1, k in 1..NECMax, l in k..NECMax) l*X[<c,1,j>][<k,l>]; // 2ème moitié de la contrainte 11 // valider variation début et fin de k. Des fois c'est k qui est en fonction de l et des fois c l qui en fonction de k'
sum (c in COMMANDES) NEC[c]<=NE; // Contrainte 12
forall (c in COMMANDES, i in 1..NT[c], j in i+1..NT[c]+1, k in 1..NECMax, l in k..NECMax) X[<c,i,j>][<k,l>]*ts[c][i][j-1]/k<=TCP[c][l];// Contrainte 13 // Valider les intervalles de k et l
forall (c in COMMANDES, l in 1..NECMax) TCP[c][l]<=ts[c][1][NT[c]]*sum (i in 1..NT[c], j in i+1..NT[c]+1, k in 1..l) X[<c,i,j>][<k,l>];// Contrainte 14 // Valider cette borne
forall (c in COMMANDES, i in 1..NT[c], j in i+1..NT[c]+1) sum(k in 1..NECMax, l in k..NECMax)X[<c,i,j>][<k,l>]<=1; // Contrainte 16, pas sure que cette contrainte est nécessaire
forall (c in COMMANDES, l in 1..NECMax) sum(k in 1..l, j in 2..NT[c]+1)X[<c,1,j>][<k,l>]==Z[c][l]; // Contrainte 17
forall (c in COMMANDES, l in 1..NECMax) coutP[c][l]<=Z[c][l]*ts[c][1][NT[c]]*l*TH/3600*NU[c]; // Contrainte 19 // Valider cette borne
forall (c in COMMANDES, l in 1..NECMax) coutP[c][l]>=TCP[c][l]*l*TH/3600*NU[c]; //Contrainte 20
CT==sum (c in COMMANDES, l in 1..NECMax)coutP[c][l]; // Contrainte 21
forall (c in COMMANDES) NS[c]>=NSMin; // Contrainte ajoutée pour controle le nombre minimal de station par ligne
forall (c in COMMANDES) NEC[c]>=NECMin; // Contrainte ajoutée pour controle le nombre minimal d'employés par ligne'
forall (c in COMMANDES) TPr[c]<=delai[c]; // contrainte ajoutée pour tenir en compte le délai de chaque commande. Exprimee en heures
//forall (c in COMMANDES) ProductiviteC[c]>=ProductiviteCMin;
//ProductiviteU>=ProductiviteUMin;
}
//Main: base prise à partir de sum basic model.mod
main {
var v; // pour décrire les fichiers de data. Indicateur de la position dans l'ensemble TYC (de 0 à 9 car 10 types de contraintes)
var tyc; // pour décrire les fichiers de data Indicateur de la valeur de tyc (En fonctionde la position spécifiée dans l'ensemble TYC')
var dc; // pour décrire les fichiers de data. indicateur du degré de contrainte, de 0 à 3 mais tous les degrées n'Existent pas pour tous les types de contraintes. Voir si cela pose problème'
var nc; // pour décrire les fichiers de data. indicateur de NC ()nombre de lignes(Commandes)) (peut prendre la valeur 2, 6, ou 10) Voir si cela marche ou bien il faut leur assigner des positions
var cfg; // pour décrire les fichiers de data. indicateur de quel numéro de configuration de tâche (de 1 à 10)
var status;
var before;
var after;
var totaltime;
var source = new IloOplModelSource("Cas plusieurs commandes.mod");
var cplex = new IloCplex();
var def = new IloOplModelDefinition(source);
var opl1 = new IloOplModel(def,cplex);
var data = new IloOplDataSource("Ref_0_2_1.dat"); // juste pour initialiser la lecture des données
opl1.addDataSource(data);
opl1.generate();
for (v=0; v=1; v++) //indique la position dans l'ensemble de type de contraintes
{
tyc=Opl.item(opl1.TYC,v);
var f = new IloOplOutputFile(tyc+"_"+"Output.txt");
//Definition de paramètres// Cette section a été gardée telle quelle du code d'origine
f.writeln("parallelmode = \t ",cplex.parallelmode);
f.writeln("threads = \t ",cplex.threads);
//cplex.tilim = 1200;
f.writeln("time limit = \t", cplex.tilim);
//cplex.nodefileind = 3;
f.writeln("nodefileind = \t", cplex.nodefileind);
//cplex.workmem = 4096.0;
f.writeln("workmem = \t", cplex.workmem);
//cplex.symmetry = -1;
f.writeln("symmetry = \t", cplex.symmetry);
//cplex.workdir="F:/IBM/ILOG/Basic Model"; // ou il stocke les noeuds: // A remplacer par? "C:\Users\Sanae\AppData\Roaming\IBM\ILOG\Repertoire modele de base" les barres sont inversées
cplex.workdir="C:/Users/Sanae/opl/Cas plusieurs commandes"
f.writeln("\t Numero Instance \t Degre de contrainte \t Numero configuration \t NC \t NE \t NU \t NSMin \t NECMin \t delai \t Cout Total (CT) \t coutC ©\t NEC © \t TC © (Temps de cycle)\t NS © \t TPr © \t ProductiviteC© \t ProductiviteU \t Statut \t Temps de resolution \t BestLB \t Detail statut \t Nnodes\t TCP \t ");
for (dc=0; dc<=0; dc++) //indique, dans le titre du fichier .dat, le degré de la contrainte mais ce degré n'est pas applicable a tous les types de contraintes'
{
for (nc=2; nc<=2; nc+=4) // Valider Formulation. indique, dans le titre du fichier .dat, le nombre de comande mais ce derniers prend uniquement 3 valeur 2,6 et 10
{
for (cfg=1; cfg<=4; cfg++)
{
cplex = new IloCplex();
/*f.writeln("parallelmode = \t ",cplex.parallelmode);
f.writeln("threads = \t ",cplex.threads); */
cplex.tilim = 1200;
//f.writeln("time limit = \t", cplex.tilim);
cplex.nodefileind = 3;
//f.writeln("nodefileind = \t", cplex.nodefileind);
cplex.workmem = 4096.0;
//f.writeln("workmem = \t", cplex.workmem);
cplex.symmetry = -1;
//f.writeln("symmetry = \t", cplex.symmetry);*/
//cplex.workdir="F:/IBM/ILOG/Basic Model"; // ou il stocke les noeuds: // A remplacer par? "C:\Users\Sanae\AppData\Roaming\IBM\ILOG\Repertoire modele de base" les barres sont inversées
cplex.workdir="C:/Users/Sanae/opl/Cas plusieurs commandes"
// cplex.workdir="C:/Users/Sanae/AppData/Roaming/IBM/ILOG/CPLEX_Studio128/workspace"
source = new IloOplModelSource("Cas plusieurs commandes.mod");
def = new IloOplModelDefinition(source);
var opl = new IloOplModel(def,cplex);
var dataset=new IloOplFile (tyc+"_"+dc+"_"+nc+"_"+cfg+".dat");
if (dataset.exists){
var data = new IloOplDataSource(tyc+"_"+dc+"_"+nc+"_"+cfg+".dat");
opl.addDataSource(data);
opl.generate();
before = new Date();
status = cplex.solve();
after = new Date();
totaltime = after - before;
f.write("\t", tyc+"_"+dc+"_"+nc+"_"+cfg);
f.write("\t", dc);
f.write("\t", cfg);
f.write("\t", opl.NC);
f.write("\t", opl.NE);
f.write("\t", opl.NU);
f.write("\t", opl.NSMin);
f.write("\t", opl.NECMin);
f.write("\t", opl.delai);
f.write("\t", cplex.getObjValue()); // borne supérieur. cout total, quel est la difference avec best objectif value
f.write("\t", opl.coutC);
f.write("\t", opl.NEC);
f.write("\t", "a corriger TC");
//f.write("\t", opl.TC);
//f.write("\t", opl.NS);
f.write("\t", "a corriger");
// f.write("\t", opl.TPr);
// f.write("\t", opl.ProductiviteS);
//f.write("\t", opl.ProductiviteU);
f.write("\t", "a corriger");
f.write("\t", "a corriger");
f.write("\t", "a corriger");
f.write("\t", status);
f.write("\t", totaltime);
f.write("\t", cplex.getBestObjValue()); // Best LB. Comment avoir celui qui calcule le GAP// pas sure que c'est une solution optimale réelle. pas entière.'
f.write("\t", cplex.getCplexStatus()); //
f.write("\t", cplex.getNnodes()); //indication nombre de calcul qu'il afaite, pour savoir combien de calcul qu'il a fait
f.write("\t", opl.TCP)
cplex.clearModel;
opl.settings.mainEndEnabled = true;
opl.end();
data.end();
def.end();
cplex.end();
source.end();
// ci après le détail des xijk dans le programme une ligne. Pour le moment je n'Affiche rien des xijik par commande.'
/*var i //première tâche d'une statio xijk'
var j // dernière tache+1 d'une station xijk'
var k // nombre d'employés affectés à une station'
var p=0 // compteur position de la station
var nsg=0 // compteur nombre de station goulot
var psg=100 // sert pour calculer position de la première station goulot, initialement très haut pour être mis à jour après
var tcsmin= opl.tcl // temps de cycle de station minimal
for (i=1; i<=opl.NT; i++)
{
for(j=i+1; j<=opl.NT+1; j++)
{
for(k=1; k<=opl.NE; k++)
{
if(opl.X[i][j][k]==1)
{
var p = p+1 // incrémente le numéro de la station à chaque fois que xijk =1
{if (opl.tcl<=opl.X[i][j][k]*opl.ts[i][j-1]/k+0.000000000001 && opl.tcl>=opl.X[i][j][k]*opl.ts[i][j-1]/k-0.000000000001)// pas eu besoin de définir le tcs comme variable d'expression'
{
nsg=nsg+1 // incrémente le nombre de stations goulot à chaque fois qu'il en trouve 1, c a d que tcs=tcl
psg=Math.min(p,psg) // calcule la position de première station goulot
//f.write("\t", "station goulot=", p) // Affiche la liste de toutes les stations goulot
}
else
{
tcsmin=Math.min(tcsmin,opl.X[i][j][k]*opl.ts[i][j-1]/k)// calcule le plus petit temps de cycle de station pour une ligne
}
}
}
}
}
}
//ci-dessus, je quitte la boucle ijk car ce que j'affiche ci-dessous est relié à l'instance (la ligne excel) et basé sur ce que j'Ai calculé pour chaque station'
f.write("\t", nsg); // afficher le nombre de stations goulot
f.write("\t", psg); // afficher la position de la première station goulot.
f.write("\t", psg/opl.NS); // afficher la position relative de la 1ère station goulot
f.write("\t", tcsmin); // Afficher le plus petit temps de cycle de station pour une ligne
f.write("\t", opl.tcl/tcsmin); // affiche le rapport entre tcl et le temps de cycle de station minimal
// ci-après je refais une boucle ijk car je dois afficher les détails de chaque station
for (i=1; i<=opl.NT; i++)
{
for(j=i+1; j<=opl.NT+1; j++)
{
for(k=1; k<=opl.NE; k++)
{
if(opl.X[i][j][k]==1)
{
f.write("\t"," " ,"\t",i,"\t",j-1,"\t",k)
}
}
}
}
// ici je termine la 2eme boucle des xijk car j'Ai fini les affichages reliés aux regroupements (Stations)' */
f.writeln("\t") // je reviens à la ligne après avoir terminé toutes les boucles ijk pour une instance (une ligne excel)
}
}
}
}
}
}
.DAT:
NC=2;
NE=14;
NU=[1000,1000];
NSMin=2;
NECMin=2;
delai=[7000,7000];
ProductiviteCMin=0;
ProductiviteUMin=0;
TH=12;
NT=[5,25];
t=[ [ 5.1 3.2 3.9 7.8 1.7 ] [ 7.9 9.7 2.8 9.9 9.8 9.2 3.5 2 8.5 0.1 8.8 9.9 9 2.7 8.6 4.8 0.9 7.9 6.9 0.8 5.4 8.5 1.7 3 8.8 ] ];
#DecisionOptimization#OPLusingCPLEXOptimizer