How to minimize total cost of external resource in MRCPSP? - optimization

Hi I'm trying to make a model with objective function to minimize cost of mode 2 usage( mode with using external resource). I confuse when I want to make a limitation total time <=21 the result is no value, but when I set the time <= 50 the result was came out, although the result when I running the model only spending time 25.
tuple Task {
key int id;
{int} succs;
int RelDate;
}
{Task} Tasks = ...;
tuple Mode {
key int taskId;
key int id;
int pt;
int costprod;
int dmdIntRes [IntRes];
int dmdExtRes [ExtRes];
int ExtCost;
}
{Mode} Modes = ...;
dvar interval Taskss [t in Tasks] in t.RelDate..(maxint div 2)-1;
dvar interval mode[m in Modes] optional size m.pt;
dexpr int totaltime = sum(m in Modes) presenceOf(mode[m]) * ( m.pt); //boolean expression
//dexpr int totalExtCost = sum(m in Modes) presenceOf(mode[m])* (m.ExtCost * m.pt);
cumulFunction IntResUsage[r in IntRes] =
sum (m in Modes: m.dmdIntRes[r]>0) pulse(mode[m], m.dmdIntRes[r]);
cumulFunction ExtResUsage[r in ExtRes] =
sum (m in Modes: m.dmdExtRes[r]>0) pulse(mode[m], m.dmdExtRes[r]);
execute {
cp.param.FailLimit = 10000;
}
minimize sum(m in Modes) (m.ExtCost * m.pt) * maxl (presenceOf(mode[m]));
//minimize max(t in Tasks) endOf(Taskss[t]);
subject to {
//Alternative mode of resource productivity in Cost's unit
forall (t in Tasks, m in Modes) {
// if(m.costprod *m.pt == 0 && 0 <= 559717712) presenceOf(mode[first(Modes)]);
alternative(Taskss[t], all(m in Modes: m.taskId==t.id) mode[m]);
}
forall (t in Tasks, m in Modes)
(sum(t in Tasks)sum(m in Modes) m.costprod * m.pt <= 285740966 in 0..NbDays-14) != presenceOf(mode[first(Modes)]);
//External resource's budget limitation
forall ( t in Tasks, m in Modes )
totaltime <= 50;
//forall ( m in Modes )
//totalExtCost <= 30000000;
//Resource Usage
forall (r in IntRes)
IntResUsage[r] <= CapIntRes[r];
forall (r in ExtRes)
ExtResUsage[r] <= CapExtRes[r];

Could you simplify your model so that it illustrates your problem ?
I do not see any value 50 or 25 in the model.
Also:
I do not see why you are using a “max” here:
minimize sum(m in Modes) (m.ExtCost * m.pt) * maxl (presenceOf(mode[m]));
I do not see why you post this constraint for each task and each mode (!). It is independent from the tasks and the modes: forall ( t in Tasks, m in Modes ) { totaltime <= 100; }
By the way, for readability reasons, you could also rewrite your expressions: “presenceOf(mode[m]) * ( m.pt)” as “sizeOf(mode[m])”. If the model duration is a constant, both formulations should be more or less similar from a performance perspective, but if the duration is a decision variable, the formulation with “sizeOf(model[m])” will definitively be better.

For the 'min', you should neither use the min or the max as your are dealing with a singleton, you directly use the presenceOf.
So I would simplify the formulation as follows:
dvar interval Tasks [t in Tasks] in t.RelDate..(maxint div 2)-1;
dvar interval mode[m in Modes] optional size m.pt;
dexpr int totaltime = sum(m in Modes) sizeOf(mode[m]);
dexpr int totalExtCost = sum(m in Modes) (m.ExtCost*sizeOf(mode[m]));
cumulFunction IntResUsage[r in IntRes] =
sum (m in Modes: m.dmdIntRes[r]>0) pulse(mode[m], m.dmdIntRes[r]);
cumulFunction ExtResUsage[r in ExtRes] =
sum (m in Modes: m.dmdExtRes[r]>0) pulse(mode[m], m.dmdExtRes[r]);
execute {
cp.param.FailLimit = 10000;
}
minimize totalExtCost;
subject to {
// Alternative mode of resource productivity in Cost's unit
forall (t in Tasks)
alternative(Tasks[t], all(m in Modes: m.taskId==t.id) mode[m]);
// I have no hint what the constraints below are supposed to do !
// forall (t in Tasks, m in Modes)
// (sum(t in Tasks) sum(m in Modes) m.costprod * m.pt <= 285740966 in 0..NbDays-14) != presenceOf(mode[first(Modes)]);
// External resource's budget limitation
totaltime <= 50;
// totalExtCost <= 30000000;
// Resource Usage
forall (r in IntRes)
IntResUsage[r] <= CapIntRes[r];
forall (r in ExtRes)
ExtResUsage[r] <= CapExtRes[r];
}
Then I still do not understand the problem with limiting the "totalTime" to 50. It does not prevent to compute a solution with "totalTime=25" indeed, as 25<=50.
In fact I do not understand your problem. You seem to say that the problem with "totalTime<=21" is infeasible, and that when you post a constraint "totalTime<=50" it finds a solution where "totalTime=25". I don't see where is the problem here ...

Related

how to print a result in cplex other than the decision variable

I want to print the value of pl[i]+pevdis[tvail][number]-pevch[tvail][number] as my result. The following is my code in Cplex.
int t=24;
int n=20;
int j=0;
range number =1..n;
range tavail=1..t;
float soc[number][tavail]=...;
//forcasted load at 0..4
float pl[tavail]=[10000000,7000000,9000000,6000000,12000000,6000000,4000000,15000000,9000000,12000000,6000000,8000000,10000000,7000000,9000000,6000000,12000000,6000000,4000000,15000000,9000000,12000000,6000000,8000000];
//soc of ev at 0..11
//generation
float pg[tavail]=[10000000,9500000,8500000,11000000,600000,7500000,10000000,9500000,8500000,11000000,600000,7500000,10000000,9500000,8500000,11000000,600000,7500000,10000000,9500000,8500000,11000000,600000,7500000];
//target load at 0..11
float pt[tavail]=[10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000];
//bus voltage at 0..11
float v[tavail]=[240,232,229,233,230,235,228,234,227,229,231,230,226,232,233,230,236,233,231,232,232,233,233,230];
//bus voltage at
// target bus voltage at 0..11
float vt[tavail]=[230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230];
//decision variable charging power ev
dvar float pevch[tavail][number] in 0..100000;
//decision variable discharging power of ev
dvar float pevdis[tavail][number] in 0..100000;
//levelised load
//objective function
minimize sum(i in tavail)((pt[i]-pl[i])+sum(j in number)-pevch[i][j]+sum(j in number)pevdis[i][j]);
subject to
{
forall(i in tavail,j in number)
if(pt[i]-pl[i]<0 && 0.7<soc[j][i]<0.9&& v[i]<vt[i])
pevdis[i][j]==soc[j][i]*100000;
else
pevdis[i][j]==0;
forall(i in tavail,j in number)
if(pt[i]-pl[i]>0 &&
soc[j][i]<=0.7 && v[i]>vt[i])
pevch[i][j]==soc[j][i]*100000;
else
pevch[i][j]==0;
}
After the subject to block you can do whatever printing you need.
For instance
minimize sum(i in tavail)((pt[i]-pl[i])+sum(j in number)-pevch[i][j]+sum(j in number)pevdis[i][j]);
subject to
{
forall(i in tavail,j in number)
if(pt[i]-pl[i]<0 && 0.7<soc[j][i]<0.9&& v[i]<vt[i])
pevdis[i][j]==soc[j][i]*100000;
else
pevdis[i][j]==0;
forall(i in tavail,j in number)
if(pt[i]-pl[i]>0 &&
soc[j][i]<=0.7 && v[i]>vt[i])
pevch[i][j]==soc[j][i]*100000;
else
pevch[i][j]==0;
}
int i=1;
int tvail=2;
int n2=3;
execute
{
writeln(
pl[i]+pevdis[tvail][n2]-pevch[tvail][n2] );
}

Write a forall constraint in CPLEX, indexing over a union of variables

I'm modelling a routing problem in CPLEX opl. I am struggling to implement a certain constraint in CPLEX, which sums a decision variable X over a set of indexes j, and this ∀i ∈ V, where V = C ⋃ S.
The constraint is the following: sum(j ∈ (1..10)) Xij < 1 ∀i ∈ V
I implemented this in CPLEX as follows:
forall(i in customers, i in stations) {
sum(j in reach) X[i][j] < 1; }
Customers refers to C, stations refers to S, and reach refers to the range of 1..10.
However, it seems impossible to use the same index (i) twice in the forall statement.
Could anyone help me to solve this problem.
Thanks a lot!
Instead of
forall(i in customers, i in stations) { sum(j in reach) X[i][j] <= 0; }
you could write
forall(i in customers union stations) { sum(j in reach) X[i][j] <= 0; }
I tried
{int} customers={1,2};
{int} stations={2,3};
{int} reach={5};
dvar boolean X[customers union stations][reach];
subject to
{
forall(i in customers union stations) { sum(j in reach) X[i][j] <= 0; }
}
and that works

Transition matrix not included in my solution of my scheduling problem in CPLEX CP

My distance matrix in my no overlap constraint does not seem to work in my model outcome. I have formulated the distance matrix by means of a tuple set. I have tried this in 2 different ways as can be seen in the code. Both tuple sets seem to be correct and the distance matrix is added in the noOverlap constraint for the dvar sequence.
Nevertheless I do not see the added transition distance between products in the optimal results. Jobs seem to continue at the same time when a job is finished. Instead of waiting for a transition time. I would like this transition matrix to hold both for machine 1 and machine 2.
Could someone tell me what I did wrong in my model formulation? I have looked into the examples, but they seem to be constructed in the same way. So I do not know what I am doing wrong.
mod.
using CP;
// Number of Machines (Packing + Manufacturing)
int nbMachines = ...;
range Machines = 1..nbMachines;
// Number of Jobs
int nbJobs = ...;
range Jobs = 1..nbJobs;
int duration[Jobs,Machines] = ...;
int release = ...;
int due = ...;
tuple Matrix { int job1; int job2; int value; };
//{Matrix} transitionTimes ={<1,1,0>,<1,2,6>,<1,3,2>,<2,1,2>,<2,2,0>,<2,3,1>,<3,1,2>,<3,2,3>,<3,3,0>};
{Matrix} transitionTimes ={ <i,j, ftoi(abs(i-j))> | i in Jobs, j in Jobs };
dvar interval task[j in Jobs] in release..due;
dvar interval opttask[j in Jobs][m in Machines] optional size duration[j][m];
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m];
execute {
cp.param.FailLimit = 5000;
}
// Minimize the max timespan
dexpr int makespan = max(j in Jobs, m in Machines)endOf(opttask[j][m]);
minimize makespan;
subject to {
// Each job needs one unary resource of the alternative set s (28)
forall(j in Jobs){
alternative(task[j], all(m in Machines) opttask[j][m]);
}
forall(m in Machines){
noOverlap(tool[m],transitionTimes);
}
};
execute {
writeln(task);
};
dat.
nbMachines = 2;
nbJobs = 3;
duration = [
[5,6],
[3,4],
[5,7]
];
release = 1;
due = 30;
``
You should specify interval types for each sequence.
In your case, the type is the job id:
int JobId[j in Jobs] = j;
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m] types JobId;

Array issue with endbefore start in CPLEX

I am trying to add an Endbeforestartconstraint to my contrained programming problem. However, I receive an error saying that my end beforestart is not an array type. I do not understand this as I almost copied the constraint and data from the sched_seq example in CPLEX, I only changed it to integers.
What I try to accomplish with the constraint, is that task 3 and task 1 will be performed before task 2 will start.
How I can fix the array error for this constraint?
Please find below the relevant parts of my code
tuple Precedence {int pre;int post;};
{Precedence} Precedences = {<3,2>,<1,2>};
dvar interval task[j in Jobs] in release..due;
dvar interval opttask[j in Jobs][m in Machines] optional size duration[j][m];
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m]
dexpr int makespan = max(j in Jobs, m in Machines)(endOf(opttask[j][m]));
minimize makespan;
subject to {
// Each job needs one unary resource of the alternative set s (28)
forall(j in Jobs){
alternative(task[j], all(m in Machines) opttask[j][m]);
}
// No overlap on machines
forall(j in Jobs)
forall(p in Precedences)
endBeforeStart(opttask[j][p.pre],opttask[j][p.post]);
forall(m in Machines){
noOverlap(tool[m],transitionTimes);
}
};
execute {
writeln(task);
dat.
nbMachines = 2;
nbJobs = 3;
duration = [
[5,6],
[4,4],
[5,8]
];
release = 1;
due = 30;
There are several errors in your model, on ranges or on inverted indices.
Also, next time, please post a complete program showing the problem, not just a partial one, this may help you to get quicker answers.
A corrected program:
using CP;
int nbMachines = 2;
int nbJobs = 3;
range Machines = 0..nbMachines-1;
range Jobs = 0..nbJobs-1;
int duration[Jobs][Machines] = [
[5,6],
[4,4],
[5,8]
];
int release = 1;
int due = 30;
tuple Precedence {int pre;int post;};
{Precedence} Precedences = {<2,1>,<0,1>};
dvar interval task[j in Jobs] in release..due;
dvar interval opttask[j in Jobs][m in Machines] optional size duration[j][m];
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m];
dexpr int makespan = max(j in Jobs, m in Machines)(endOf(opttask[j][m]));
minimize makespan;
subject to {
// Each job needs one unary resource of the alternative set s (28)
forall(j in Jobs){
alternative(task[j], all(m in Machines) opttask[j][m]);
}
// No overlap on machines
forall(m in Machines)
forall(p in Precedences)
endBeforeStart(opttask[p.pre][m],opttask[p.post][m]);
};
execute {
writeln(task);
}
You must have values in p.pre or p.post that are outside of the array indexing range.

How to make a if and else in alternative function in OPL?

I want to make if the earn value is not same with the plan then choose alternative 2, if same then choose alternative 1. I used tuple mode to determine the 2 alternative in OPL using CP(constraint programming)
I still stuck until this part
**subject to {
forall (p in Precedences, m in Modes) {
alternative(Tasks[p], all(m in Modes: m.taskId==p.id) mode[m]);**
thanks, I need this part to finish my master thesis, because I don't have a basic about programming
You can use presenceOf.
using CP;
int v=1;
// if v is 1 we choose a1p[1] , if not a1p[2];
dvar interval a1;
dvar interval a1p[i in 1..2] optional size i;
subject to {
alternative(a1, a1p);
(v==1) == (presenceOf(a1p[1])==1);
};
execute
{
writeln(a1);
}
gives
<1 0 1 1>
but if I change v=1 to v=2 then I get
<1 0 2 2>
thanks for response my question, I felt bless. this code plicable to using tuple? because I make my mode at tuple? when I tried using range 1..2 the dvar was error. this is my original code
tuple Mode {
key int taskId;
key int id;
int pt;
int costprod;
int dmdIntRes [IntRes];
int dmdExtRes [ExtRes];
}
{Mode} Modes = ...;
dvar interval Tasks [p in Precedences]in p.RelDate..EndMax ; //in p.RelDate..EndMax in 0..EndMax
dvar interval mode[m in Modes] optional size m.pt;
cumulFunction IntResUsage[r in IntRes] =
sum (m in Modes: m.dmdIntRes[r]>0) pulse(mode[m], m.dmdIntRes[r]);
cumulFunction ExtResUsage[r in ExtRes] =
sum (m in Modes: m.dmdExtRes[r]>0) pulse(mode[m], m.dmdExtRes[r]);
execute {
cp.param.FailLimit = 10000;
}
minimize max(p in Precedences) endOf(Tasks[p]);
subject to {
forall (p in Precedences, m in Modes) {
alternative(Tasks[p], all(m in Modes: m.taskId==p.id) mode[m]);