I just have encountered the same issue when I tried to run the flow control for 100 iterations. I am not sure what it is causing it but I believe it is the way the data is created, I mean the randomness of the data and the triangular distribution.
I ran the model for 50 iterations and it worked. I saved the data under a first csv file. I changed the name the csv file and rerun the model for 50 iterations a 2nd time and it worked again. Since the data is random, the likelihood that the data of 1st run = data of the 2nd run is close to 0! I even run it a 3rd time (50 iterations) and 4 time (50 iterations) and it went well as well .
At this time, I am not sure why the randomness of the data creates an issue.Perhaps our IBM-ers can provide more insights to your problem.
PS: I am not an expert in OPL, I just have some practical experience.
Original Message:
Sent: Sat December 26, 2020 09:03 AM
From: Mohamed Awad
Subject: Running OPL model for n times and exporting each feasible result per run
Dear Nourredine,
Thanks a million for your kind reply. I made few modifications to match my original case and your solution is perfect.
I have another question, whenever I run the model, which is a large model, with IterationNum =100 for example, the OPL stops working after it reaches a certain iteration number (i.e. 30). Is there a way to check why the OPL stops working in that case?
Thanks again,
------------------------------
Mohamed Awad
Original Message:
Sent: Thu December 24, 2020 07:47 AM
From: Nourredine Hail
Subject: Running OPL model for n times and exporting each feasible result per run
Hello Mohamed,
I've added to your .mod (MyCPModel) an iteration number (IterNum) and a output set that captures the iteration number, the start of the activity and the end of the activity (you can customized the output at your convenience). I have also created a control flow (flow_control.mod) in which I created a function that solve a CP instance for each iteration. In the main, a csv file is created that will save the output of each iteration. You just need to change the path, customize your output and rerun it. It works for me. I hope this helps. Let me know if you have any issues copying the file to your IDE. I can email them to you. Please confirm if it works. Cheers!
//This is your modified MyCPModel.mod
/********************************************* * OPL 12.10.0.0 Model
* Author: S00184272 * Creation Date: 23 Dec 2020 at 16:38:28
* Modified on Dec 24 2020 by 007
*********************************************/
using CP; {string} House_category = ...; // Only one house category is used in this model
{string} ActivityTypes = ...;
// each house category has its own activities
int IterNum=...;
int requiredQuantities[House_category] = ...;
// number of required houses for each house category
// This tuple is sued to define the information of "activities"
tuple ActivityInfo
{
key string activity;
int duration;
int lb_duration;
int ub_duration;
{string} precedences;
};
{ActivityInfo} activities[House_category] = ...;
// This tuple is used to combine the information of activities with house category and the required number of houses per category
tuple ActivityMatch
{
ActivityInfo activity;
string House_category;
int nOrders; };
{ActivityMatch} allActivities = {<a,c,j> | c in House_category,a in activities[c], j in 1..requiredQuantities[c]};
// created to store the randomly generated processing times
int tringular_processing[allActivities];
// triangular distribution generation block
execute
{
for (var rand_time in allActivities)
{
{ for (var i = 1; i < allActivities.size; ++i) {
var rnd = IloOplCallJava("java.util.Random", "<init>", "()"); t = rnd.nextDouble();
var a=rand_time.activity.lb_duration;
var c=rand_time.activity.duration;
var b=rand_time.activity.ub_duration;
if (t< ((c-a)/(b-a)))
{ t=a+Math.round((Math.sqrt((b-a)*(c-a)*t))); }
else { t=b-Math.round((Math.sqrt((b-a)*(b-c)*(1 - t))));
}
tringular_processing[rand_time]=t;
}
}
}
}
// This tuple is used to combine the allActivities with the randomly generated processing times from the triangular distribution
tuple combined{ ActivityMatch allActivities; int trig_process; }
{combined} allActivities_tri={<a,c> | a in allActivities,c in 0..tringular_processing[a]:c==maxl (tringular_processing[a]) && c>=0 }; // used to define the precedence relations
{combined} precedences[a in allActivities_tri] =
{ b | b in allActivities_tri : a.allActivities.House_category == b.allActivities.House_category
&& a.allActivities.nOrders == b.allActivities.nOrders && b.allActivities.activity.activity in a.allActivities.activity.precedences};
// This tuple is used to enable using the if condition in dvar interval activity as seen below
tuple combined_2{ string House_category ; int requiredQuantities; }; {combined_2} allActivities_2 = {<c,j> | c in House_category, j in 1..requiredQuantities[c]};
// the decision variable that represents the activities for each house
dvar interval activity[a in allActivities_tri][b in allActivities_2] size (a.allActivities.House_category ==b.House_category && a.allActivities.nOrders==b.requiredQuantities)? (a.trig_process):0;
execute
{
settings.bigmapthreshold = 50000;
cp.param.FailLimit = 5000;
}
// objective function
minimize sum(a in allActivities_tri, b in allActivities_2) endOf(activity[a][b]);
//constraints
subject to
{
Precedence_all: forall (a in allActivities_tri, b in allActivities_2, p in precedences[a]: a.allActivities.House_category==b.House_category && a.allActivities.nOrders==b.requiredQuantities)
endAtStart(activity[p][b],activity[a][b]);
}
tuple tup_out
{
int IterNum;
int StartOfActivity;
int EndOfActivity;
}
{tup_out} Set_out={<IterNum,startOf(activity[a][b]),endOf(activity[a][b])>| a in allActivities_tri, b in allActivities_2};
//This is the flow control
/*********************************************
* OPL 12.6.3.0 Model
* Author: 007
* Creation Date: 2020-12-16 at 10:24:18 AM
*********************************************/
int IterationNum=10;
{int} Set=asSet(1..IterationNum);
main{
var DIR="C:\\Users\\nourredine.hail\\Desktop\\CPLEXModels\\Test\\"
var csvFileName="MyCPModel.csv";
var ofile=new IloOplOutputFile(DIR+csvFileName);
//var ofile = new IloOplOutputFile("C:\\Users\\nourredine.hail\\Desktop\\CPLEXModels\\Test\\Test.csv");
//Create the Column names
ofile.writeln(
"IterNum",",","StartOfActivity",",","EndOfActivity");
//Function that solves a CP instance
function SolveOPL_CPModel(IterNum)
{
var MyCPModel_source = new IloOplModelSource("MyCPModel.mod");
var MyCPModel_cplex = new IloCP();
var MyCPModel_def = new IloOplModelDefinition(MyCPModel_source);
var MyCPModel_opl = new IloOplModel(MyCPModel_def,MyCPModel_cplex);
var MyCPModel_data = new IloOplDataSource("MyCPModel.dat");
var MyCPModel_dataelts= new IloOplDataElements();
MyCPModel_opl.settings.mainEndEnabled=true;
MyCPModel_opl.settings.warnings=false;
//Add the iteration number
MyCPModel_dataelts.IterNum=IterNum;
MyCPModel_opl.addDataSource(MyCPModel_dataelts);
MyCPModel_opl.addDataSource(MyCPModel_data);
MyCPModel_opl.generate();
if(MyCPModel_cplex.solve()) MyCPModel_opl.postProcess();
//write the output into the cvs file
for(var a in MyCPModel_opl.Set_out)
ofile.writeln(a.IterNum,",",a.StartOfActivity,",",a.EndOfActivity)
//End the opl instance to free memory
MyCPModel_opl.end();
}
for(var IterNum in thisOplModel.Set) SolveOPL_CPModel(IterNum)
ofile.close();
}
------------------------------
Nourredine Hail
Original Message:
Sent: Wed December 23, 2020 02:38 PM
From: Mohamed Awad
Subject: Running OPL model for n times and exporting each feasible result per run
Dears,
I would appreciate your help regarding the model below. In this model, I am using CP solver to minimise the makespan of houses construction. I simplified the model to make my questions clear. In the model, you will see that each activity in the house construction has a variable time. These times are generated using triangular distribution as seen in the pre-processing block. My question is how can I run the model n times (i.e. 50 times) and for each run, how can I export all the feasible results, for each run, to a unique excel file.
Please find the model and data below:
.mod:
/********************************************* * OPL 12.10.0.0 Model * Author: S00184272 * Creation Date: 23 Dec 2020 at 16:38:28 *********************************************/using CP;{string} House_category = ...; // Only one house category is used in this model{string} ActivityTypes = ...; // each house category has its own activitiesint requiredQuantities[House_category] = ...; // number of required houses for each house category// This tuple is sued to define the information of "activities"tuple ActivityInfo { key string activity; int duration; int lb_duration; int ub_duration; {string} precedences;};{ActivityInfo} activities[House_category] = ...;// This tuple is used to combine the information of activities with house category and the required number of houses per category tuple ActivityMatch { ActivityInfo activity; string House_category; int nOrders; };{ActivityMatch} allActivities = {<a,c,j> | c in House_category,a in activities[c], j in 1..requiredQuantities[c]};// created to store the randomly generated processing timesint tringular_processing[allActivities];// triangular distribution generation blockexecute{ for (var rand_time in allActivities) { { for (var i = 1; i < allActivities.size; ++i) { var rnd = IloOplCallJava("java.util.Random", "<init>", "()"); t = rnd.nextDouble(); var a=rand_time.activity.lb_duration; var c=rand_time.activity.duration; var b=rand_time.activity.ub_duration; if (t< ((c-a)/(b-a))) { t=a+Math.round((Math.sqrt((b-a)*(c-a)*t))); } else { t=b-Math.round((Math.sqrt((b-a)*(b-c)*(1 - t)))); } tringular_processing[rand_time]=t; } } } } // This tuple is used to combine the allActivities with the randomly generated processing times from the triangular distribution tuple combined{ ActivityMatch allActivities; int trig_process; }{combined} allActivities_tri={<a,c> | a in allActivities,c in 0..tringular_processing[a]:c==maxl (tringular_processing[a]) && c>=0 };// used to define the precedence relations{combined} precedences[a in allActivities_tri] = { b | b in allActivities_tri : a.allActivities.House_category == b.allActivities.House_category && a.allActivities.nOrders == b.allActivities.nOrders && b.allActivities.activity.activity in a.allActivities.activity.precedences }; // This tuple is used to enable using the if condition in dvar interval activity as seen belowtuple combined_2{ string House_category ; int requiredQuantities; }; {combined_2} allActivities_2 = {<c,j> | c in House_category, j in 1..requiredQuantities[c]}; // the decision variable that represents the activities for each house dvar interval activity[a in allActivities_tri][b in allActivities_2] size (a.allActivities.House_category ==b.House_category && a.allActivities.nOrders==b.requiredQuantities)?(a.trig_process):0;execute { settings.bigmapthreshold = 50000; cp.param.FailLimit = 5000;}// objective functionminimize sum(a in allActivities_tri, b in allActivities_2) endOf(activity[a][b]);//constraintssubject to { Precedence_all: forall (a in allActivities_tri, b in allActivities_2, p in precedences[a]: a.allActivities.House_category==b.House_category && a.allActivities.nOrders==b.requiredQuantities) endAtStart(activity[p][b],activity[a][b]); }
.dat
/********************************************* * OPL 12.10.0.0 Data * Author: S00184272 * Creation Date: 23 Dec 2020 at 16:38:38 *********************************************/ActivityTypes = { activity_A, activity_B, activity_C, activity_D, activity_E };House_category= {House_1};requiredQuantities = [5]; activities = #[ House_1: { <activity_A, 10, 5, 15, {}>, <activity_B, 30, 20, 40, {activity_A}>, <activity_C, 38, 27, 87, {activity_B}>, <activity_D, 32, 12, 54, {activity_C}>, <activity_E, 25, 10, 30, {activity_D}>} , ]#;
------------------------------
Mohamed Awad
------------------------------
#DecisionOptimization