I don't know how to appreciate your help enough. Thanks a lot! It works beautifully. Initially, I could not understand the difference between the bug in OPL and Engine, although you explained it multiple times. Thanks for your patience. I think I am getting old ^^.
Original Message:
Sent: Thu April 30, 2020 02:17 PM
From: Petr Vilím
Subject: heightAtEnd
Hello Andy,
I think I found it. Here is the modified model. I changed also the script at the end a little. And I changed value of FailureDirectedSearchEmphasis from 1 to 0.99. If you look for proof and you want to use multiple cores then you can also experiment with values such as 1.99, 2.99 etc.
Petr
------------------------------
Petr Vilím
IBM
Original Message:
Sent: Thu April 30, 2020 09:25 AM
From: Andy Ham
Subject: heightAtEnd
Your model works great! Thanks! Although you mentioned that it is not a good problem for CPO, the code still beats MIP and combined model of MIP/CP for VRP+ time-of-use pricing problem in most of benchmark instances.
This paper addresses an electrical vehicle routing problem with time window (E-VRPTW) under time-of-use (TOU) pricing aiming to minimize the electricity-cost as well as the number of used vehicles and total travel distance. In particular, the proposed solution cleverly shifts battery charging to off-peak periods and adjusts the charging duration to reduce the cost. First, the problem is carefully carved in a mixed integer linear programming model. Second, a constraint programming model is built. Third, a combined model is constructed to exploit the strengths of both models. The computational study demonstrates we can reduce the electricity-cost by ??% on average while not compromising other objectives.
I am sorry but I have one more favor. The benchmark instances have float values for battery capacity and refueling rate. When I solve the problems with simple ftoi conversion, it worked well. However, when I tried to consider the exact values with scaling factor, the battery restriction does not work any more, as you can see in below. There must be my errors, but I could not find them ^^
Truck 2 cumBattery levels:
From time 0 value 7775
From time 67 value 6475
From time 193 value 2875
From time 321 value -925
From time 416 value -1425
From time 989 value -5225
From time 1090 value -6325
From time 1114 value -8725
int Q=ftoi(ceil(QQ*scale)); //77.5; // Vehicle fuel tank capacity
int g=ftoi(ceil(gg*scale));// 3.47; //inverse refueling rate
//Battery consumption
dischargeValues[j][t] == - scale*dNtoN[j.id][predecessor[t][j]];
dischargeValues[j][t] == scale*dischargeExprs[j][t];
//Battery charging
forall(j in aJobs,t in Trucks: j.t=="f") chargeValues[j][t] == g*sizeOf(itvJ2T[j][t]);
forall(j in aJobs,t in Trucks) chargeValues[j][t] == scale*chargeExprs[j][t];
------------------------------
Andy Ham
Original Message:
Sent: Wed April 29, 2020 10:55 AM
From: Petr Vilím
Subject: heightAtEnd
For me it finds the optimal solution (objective 176). Note that there are two typeOfNext in the model, it is necessary to change both.
Regarding the workaround and the bug. The bug in version 12.10 is only in computation of cumulative function in OPL that happens after the solve. The bug is not in the engine. I.e. engine computes the solution correctly, and due to the bug OPL is not able to display it. The workaround is to introduce integer variables that store the changes of the cumulative function so that the cumulative function can be computed manually after the solve. That's what the script at the end of the model file does.
In other words, the bug in OPL does not influence is not the reason why it is not easy for the engine to find the solution and prove its optimality. I'm afraid that it is not a good problem for CP Optimizer because some important propagation are missing (at least in version 12.10).
I attach one more version of the model. I introduced variables "predecessor". They does not seem to be very useful in the model, but by having them explicitly, the search my start to work on them instead of working on time. I also added a redundant constraint and a search phase. This way we have a proof now. However this is just a toy problem and I'm afraid it will not work very well on real problems.
Regards, Petr
------------------------------
Petr Vilím
IBM
Original Message:
Sent: Wed April 29, 2020 08:39 AM
From: Andy Ham
Subject: heightAtEnd
After changing to typeOfPrev as you suggested, the work-around code seems working! Owing to the postscript, I was able to confirm the model.
dischargeValues[j][t] == - dNtoN[j.id][typeOfPrev(seqTrk[t], itvJ2T[j][t], j.id, j.id)];
Only concern is the speed. This work-around could not find the optimal after 10 mins run-time, compared to immediate results from MIP. I guess I need to wait the next release of CPO that addresses the cumulative function issue.
| name | type | start | end | size | dist | charge | discharge | Battery |
| itvJ2T[<1001,"D0","d",40,50,0,0,1236,0>][1] | 1001 | 52 | 52 | 0 | | | | 78 |
| itvJ2T[<7,"C65","c",48,40,10,67,139,90>][1] | 7 | 67 | 157 | 90 | 13 | 0 | -13 | 65 |
| itvJ2T[<1,"S01","f",40,50,0,0,1236,0>][1] | 1 | 170 | 174 | 4 | 13 | 12 | -13 | 64 |
| itvJ2T[<6,"C98","c",58,75,20,0,1115,90>][1] | 6 | 205 | 295 | 90 | 31 | 0 | -31 | 33 |
| itvJ2T[<2,"S01","f",40,50,0,0,1236,0>][1] | 2 | 359 | 375 | 16 | 31 | 48 | -31 | 50 |
| itvJ2T[<5,"C20","c",30,50,10,0,1136,90>][1] | 5 | 385 | 475 | 90 | 10 | 0 | -10 | 40 |
| itvJ2T[<9,"C24","c",25,50,10,0,1131,90>][1] | 9 | 480 | 570 | 90 | 5 | 0 | -5 | 35 |
| itvJ2T[<4,"S151","f",39,26,0,0,1236,0>][1] | 4 | 642 | 644 | 2 | 28 | 6 | -28 | 13 |
| itvJ2T[<3,"S151","f",39,26,0,0,1236,0>][1] | 3 | 766 | 777 | 11 | 0 | 33 | 0 | 46 |
| itvJ2T[<8,"C57","c",40,15,40,989,1063,90>][1] | 8 | 989 | 1079 | 90 | 11 | 0 | -11 | 35 |
| itvJ2T[<2001,"DN","r",40,50,0,0,1236,0>][1] | 2001 | 1114 | 1114 | 0 | 35 | 0 | -35 | 0 |
| | | | | 177 | | | |
Thanks for all your help.
Andy
------------------------------
Andy Ham
Original Message:
Sent: Wed April 29, 2020 04:25 AM
From: Petr Vilím
Subject: heightAtEnd
Hello Andy,
yes, the truck recharges 12 units at S1 immediately after departing from the depot at time 4. However it already discharged 13 units at time 0. This discharge was caused by stepAtStart for the S1. The value 13 was computed by:
dischargeValues[j][t] == - dNtoN[j.id][typeOfNext(seqTrk[t], itvJ2T[j][t], j.id, j.id)];
I'm wondering whether instead of typeOfNext there shouldn't be typeOfPrev?
I added into postprocessing display of the events (charges and discharges) for each truck. Here is the result:
Truck 1 events: (Battery starts charged with level 78.) Time 0 at S01 discharging -13 Time 4 at S01 charging +12 Time 67 at C65 discharging -36 Time 157 at C65 (no change) Time 193 at C98 discharging -31 Time 283 at C98 (no change) Time 314 at S01 discharging -10 Time 340 at S01 charging +78 Time 350 at C20 discharging -5 Time 440 at C20 (no change) Time 445 at C24 discharging -38 Time 535 at C24 (no change) Time 989 at C57 discharging -11 Time 1079 at C57 (no change) Time 1090 at S151 (no change) Time 1116 at S151 discharging -24 Time 1116 at S151 (no change) Time 1116 at S151 charging +78 Time 1140 at DN (no change) Time 1140 at DN (no change)
I attach the modified model file.
Regards, Petr
------------------------------
Petr Vilím
IBM
Original Message:
Sent: Mon April 27, 2020 09:54 AM
From: Andy Ham
Subject: heightAtEnd
This place looks nicer than old one ^^ I have been a big beneficiary of this forum.
I feel very lucky to learn CPO. I see huge publication opportunities as a researcher and huge real-world implementation opportunities as a practitioner. Currently, I am working with semiconductor & display industries to introduce CPO. It has been very difficult due to the bad experience with CPO about 20 years ago in that particular companies ^^. They don't know how much CPO has been improved. I think the door will be soon open because of CPO's own merits.
This is the continuation of https://www.ibm.com/developerworks/community/forums/html/forum?id=11111111-0000-0000-0000-000000002067&ps=25
I think we are getting close to the solution.
The revised code generates a following tour.
Depot=>S1=>65=>98=>S1=>20=>24=>57=>S15=>Depot (Where S refers the charging station).
The truck recharges (12 units) at S1 immediately after departing from the depot. The truck starts with a full battery level of 78 units. Since both the depot and S1 are located at the same cords. This recharging is not valid.
The code seems to using this invalid charging to give the truck enough energy until the next charging. Note the distance S1=>65=>98=>S1 is equal to 90 (12+78).
The code seems to allow the battery go beyond the maximum level of 78.
Thanks,
Andy
------------------------------
Andy Ham
------------------------------
#DecisionOptimization