CPLEX ILOG - 3 Crops across 3 Farms - linear-programming

I am trying to solve 9 planting decisions for 3 crops on each of 3 farms.
I am given data for Available land on each farm, Available water on each farm, Maximum Quota for each crop, Water Consumption for each crop, and Profit for each crop. I am not allowed to list all of the coefficients in the .dat file.
Below is what I have entered in the .dat file:
Farms = {Rice,Barns,Snyder};
Crops = {Corn,Wheat,SoyBeans};
UsableLand = [400,600,300];
Water = [600,800,375];
MaximumQuota = [600,500,325];
WaterConsumption = [3,2,1];
Profit = [1000,750,250];
There are 3 constraints: Usable Land, Available water, and Maximum Quota.
The Objective is to maximize profit.
Below is what I have in the .mod file which is (finally) solving with no errors but not giving me the correct answer that Excel's solver runs. Any guidance would be greatly appreciated!
{string} Farms = ...;
{string} Crops = ...;
int UsableLand[Farms]=...;
int Water[Farms]=...;
int MaximumQuota[Crops]=...;
int WaterConsumption[Crops]=...;
int Profit[Crops]=...;
constraint LandAcre[Farms];
constraint WaterAcre[Farms];
constraint CropLimit[Crops];
dvar float+ ProductionAmount[Crops][Farms];
maximize
sum(i in Crops, p in Farms)
Profit[i]*ProductionAmount[i][p];
subject to {
forall(i in Farms)
LandAcre[i]:
sum(j in Crops, p in Farms) ProductionAmount[j][p] <= UsableLand[i];
forall(i in Farms)
WaterAcre[i]:
sum(j in Crops, p in Farms) WaterConsumption[j] <= Water[i];
forall(i in Crops)
CropLimit[i]:
sum(j in Crops, p in Farms) ProductionAmount[j][p] <= MaximumQuota[i];
}

This looks suspicious:
forall(i in Farms)
LandAcre[i]:
sum(j in Crops, p in Farms) ProductionAmount[j][p] <= UsableLand[i];
It probably should read:
forall(i in Farms)
LandAcre[i]:
sum(j in Crops) ProductionAmount[j][i] <= UsableLand[i];
Same for the other constraints.
A useful debugging tool is to write out the LP file and inspect that for unexpected things.

Related

Proportionality in ILOG CPLEX

I am trying to include proportionality in my solution.
The .dat is as follows:
Farms = {Rice,Barns,Snyder};
Crops = {Corn,Wheat,SoyBeans};
UsableLand = [400,600,300];
Water = [600,800,375];
MaximumQuota = [600,500,325];
WaterConsumption = [3,2,1];
Profit = [1000,750,250];
My .mod is currently built as follows:
{string} Farms = ...;
{string} Crops = ...;
int UsableLand[Farms]=...;
int Water[Farms]=...;
int MaximumQuota[Crops]=...;
int WaterConsumption[Crops]=...;
int Profit[Crops]=...;
constraint LandAcre[Farms];
constraint WaterAcre[Farms];
constraint CropLimit[Crops];
constraint Propotionality[Crops][Farms];
dvar float+ ProductionAmount[Crops][Farms];
maximize
sum(i in Crops)
sum(j in Farms)
Profit[i]*ProductionAmount[i][j];
subject to {
forall(j in Farms)
LandAcre[j]:
sum(i in Crops) ProductionAmount[i][j] <= UsableLand[j];
forall(j in Farms)
WaterAcre[j]:
sum(i in Crops) WaterConsumption[i] * ProductionAmount[i][j] <= Water[j];
forall(i in Crops)
CropLimit[i]:
sum(j in Farms) ProductionAmount[i][j] <= MaximumQuota[i];
My question is how to include proportionality as a constraint. Do I add such as:
forall(j in Farms)
Proportionality [j]:
sum(i in Crops) ProductionAmount[i][j] / UsableLand[j] == ProductionAmount[i][j] / UsableLand[j];
Any guidance is greatly appreciated!
You could use
dvar float ratio[Crops] in 0..1;
and then write
forall(j in Farms)
Proportionality :
forall(i in Crops)ProductionAmount[i][j] / UsableLand[j] == ratio[i];
You entire .mod would then be
{string} Farms = ...;
{string} Crops = ...;
int UsableLand[Farms]=...;
int Water[Farms]=...;
int MaximumQuota[Crops]=...;
int WaterConsumption[Crops]=...;
int Profit[Crops]=...;
constraint LandAcre[Farms];
constraint WaterAcre[Farms];
constraint CropLimit[Crops];
//constraint Propotionality[Crops][Farms];
dvar float+ ProductionAmount[Crops][Farms];
dvar float ratio[Crops] in 0..1;
maximize
sum(i in Crops)
sum(j in Farms)
Profit[i]*ProductionAmount[i][j];
subject to {
forall(j in Farms)
LandAcre[j]:
sum(i in Crops) ProductionAmount[i][j] <= UsableLand[j];
forall(j in Farms)
WaterAcre[j]:
sum(i in Crops) WaterConsumption[i] * ProductionAmount[i][j] <= Water[j];
forall(i in Crops)
CropLimit[i]:
sum(j in Farms) ProductionAmount[i][j] <= MaximumQuota[i];
forall(j in Farms)
Proportionality :
forall(i in Crops)ProductionAmount[i][j] / UsableLand[j] == ratio[i];
}

Formulating diagonal constraint for N Queen problem C++

I'm having a problem with the N Queens problem. I try to implement a constraint that the queens cannot be placed in the diagonals. The program is embedded in CPLEX.
Here is what I have for the column constraint, that max. one queen is placed per column:
for (rr = 0; rr < ROWS; rr++)
{
IloExpr constraint2(env);
for (rr=0;rr<ROWS;rr++)
constraint2 += x[rr][cc];
mod.add(constraint2 == 1);
constraint2.end();
}
I tried to implement this for the upper left diagonal:
for (d = rr - 1; d < (ROWS - 2); d++)
{
IloExpr constraint3(env);
for (d = cc - 1; d < (ROWS - 2); d++)
constraint3 += x[d][d];
mod.add(constraint3 >= 1);
constraint3.end();
}
But this does not work. Can somebody help me with this?
Within CPLEX you can rely on MIP.
With OPL you could write
int Dim=400;
range Bord=1..Dim;
dvar boolean x[Bord][Bord];
subject to
{
forall(i in Bord) sum(j in Bord) x[i][j]==1;
forall(i in Bord) sum(j in Bord) x[j][i]==1;
forall(k in 2..2*Dim) sum(i,j in Bord:i+j==k) x[i][j]<=1;
forall(k in 1-Dim..Dim-1) sum(i,j in Bord:i-j==k) x[i][j]<=1;
}
But with Dim=400 it takes 15 s on my laptop whereas with CPOptimizer within CPLEX , in less than 1 s
using CP;
int Dim=400;
range Bord=1..Dim;
dvar int queen[Bord] in Bord;
dvar int d1[Bord];
dvar int d2[Bord];
constraints {
forall(ind in Bord) {
d1[ind]== queen[ind]+ind;
d2[ind ]== queen[ind]-ind;
};
allDifferent(queen); // One queen max per line
allDifferent(d1); // One queen max per diagonal 1
allDifferent(d2); // One queen max per diagonal 2
};

Why my work in ILOG CPLEX have no solution?

i'm working on a production mix problem in ILOG CPLEX. But there are some problems that occur. My work is about sawmill production mix (production planning for lumber products that transform from log). I tried to solve my problem using 2 file .dat, one using dummy data and one using real data.
Data processing with dummy data show the solution, but when i'm using real data, result show no solution. So i've tried to change each of my dummy data with my real data (one by one to see what data that caused the problem). And it turned out the data are "LumberRecFac" and "DemandMaks". Then, i tried to change that two data with a several random numbers. And it shows that the maximum data for "LumberRecFac" is 0.5 and the maximum data for "DemandMaks" is 10.9.
Is there something that i missed/wrong in my .mod and .dat? Because i have to run my ILOG CPLEX .mod using my real data.
Here my .mod
//product mix
//i= (RST)
//d,l (Log)
//p (Cutting_Pattern)
int i=...;
int d=...;
int l=...;
int p=...;
range RST= 1..i; //Lumber Product(Raw Sawn Timber)
range Diameter_Log=1..d; //Diameter Log
range Panjang_Log=1..l; //Length log
range Cutting_Pattern=1..p; //Cutting Pattern
//set tuple
tuple DMdl{ //diameter and length
int d;
int l;
}
tuple DMdlp{ //diameter, length, and cutting pattern
int d;
int l;
int p;
}
tuple Cdpi{ //conversion factor (from log to lumber products)
int d;
int p;
int i;
}
//set
setof (DMdl) Log={<d,l> | d in Diameter_Log, l in Panjang_Log};
setof (DMdlp) Log_LCR={<d,l,p> | d in Diameter_Log, l in Panjang_Log, p in Cutting_Pattern};
setof (Cdpi) KonversiLog_LCR={<d,p,i> | d in Diameter_Log, p in Cutting_Pattern, i in RST};
//import data
int HargaJual[RST]=...; //Selling price of RST
int BiayaLogBaru[Log]=...; //Cost of new log
int BiayaLogLama[Log]=...; //Cost of old log
int BiayaProduksiLog=...; //Production cost
int BiayaSetup=...; //Setup cost
float LumberRecFac[KonversiLog_LCR]=...; //Conversion Factor (Lumber Recovery Ratio)
float DemandMaks[RST]=...; //Demand
int BM=...; //Big Constant (Big M)
int Tmax=...; //Max Production Time
int ProcessTime[Cutting_Pattern]=...; //Process time for one log
float SetupTime[Cutting_Pattern]=...; //Setup time
float TotalLogLamaSimpan[Log]=...; //Quantity of old log
//decision variable
dvar float+ Pi[RST]; //Quantity of lumber products
dvar float+ VF[RST]; //Quantity of selling lumber products
dvar boolean CPp[Cutting_Pattern];
dvar float TotalLogBaruBeli[Log]; //Quantity of new lod that have to buy
dvar float+ LogProduksi[Log_LCR]; //Total quantity of log to produce
dvar float+ LogBaruDipakai[Log]; //Total quantity of new log that processed
dvar float+ LogLamaDipakai[Log]; //Total quantity of old log that processed
dvar float+ TotalLogSimpan[Log]; //Total inventor of new log
//objective function
dexpr float sales=sum(i in RST) VF[i]*HargaJual[i];
dexpr float purchased=sum(d in Diameter_Log, l in Panjang_Log) (TotalLogBaruBeli[<d,l>]*BiayaLogBaru[<d,l>])+(LogLamaDipakai[<d,l>]*BiayaLogLama[<d,l>]);
dexpr float production=sum(d in Diameter_Log, l in Panjang_Log) LogProduksi[<d,l,p>]*BiayaProduksiLog;
dexpr float setup=sum(p in Cutting_Pattern) BiayaSetup*CPp[p];
maximize sales-(purchased+production+setup);
//constraint
subject to{
//constraint 1 : raw material inventory
forall (d in Diameter_Log, l in Panjang_Log)
TotalLogBaruBeli[<d,l>]==LogBaruDipakai[<d,l>]+TotalLogSimpan[<d,l>];
forall (d in Diameter_Log, l in Panjang_Log)
TotalLogLamaSimpan[<d,l>]>=LogLamaDipakai[<d,l>];
//constraint 2 : log processing
forall (l in Panjang_Log, i in RST)
sum(d in Diameter_Log, p in Cutting_Pattern) LogProduksi[<d,l,p>]*LumberRecFac[<d,p,i>]==Pi[i];
forall (d in Diameter_Log, l in Panjang_Log)
sum(p in Cutting_Pattern )LogProduksi[<d,l,p>]==LogLamaDipakai[<d,l>]+LogBaruDipakai[<d,l>];
forall (p in Cutting_Pattern)
sum(d in Diameter_Log, l in Panjang_Log) LogProduksi[<d,l,p>]<=BM*CPp[p];
forall (p in Cutting_Pattern)
sum(d in Diameter_Log, l in Panjang_Log) (LogProduksi[<d,l,p>]*ProcessTime[p])+(SetupTime[p]*CPp[p])<=Tmax;
//constraint 3 : production management and demand satisfaction
forall (i in RST)
Pi[i]>=VF[i];
forall (i in RST)
VF[i]==DemandMaks[i];
}
Here my dummy data
i = 3;
d = 2;
l = 2;
p = 1;
HargaJual= [1500 1400 1600];
BiayaLogLama=[100 250
200 400];
BiayaLogBaru=[150 250
300 450];
BiayaProduksiLog= 400;
BiayaSetup= 5;
LumberRecFac= [0.5 0.5 0.5
0.5 0.5 0.5];
DemandMaks= [9.8 10.9 10.8];
BM= 10000;
Tmax= 48;
ProcessTime= [1];
SetupTime= [0.1];
TotalLogLamaSimpan=[2 1
1 2];
Here my real data
i = 10;
d = 2;
l = 5;
p = 1;
HargaJual= [3114984
43347890
22956482
7775850
15380010
16984110
8703344
3500008
3288741
2525224
];
BiayaLogLama=[2328042 2834346 3035619 3044953 3199186
4446927 4872151 4924974 6006590 6637329];
BiayaLogBaru=[2360389 3291645 3212665 3231400 3453636
4456572 4884165 5057298 6261820 6733965];
BiayaProduksiLog= 17435453;
BiayaSetup= 5;
LumberRecFac= [0.0127 0.0145 0.0982 0.1353 0.4127 0.0001 0.2800 0.0107 0.1348 0.0166
0.6842 0.2105 0.0643 0.2359 0.4730 0.0497 0.3728 0.0187 0.2393 0.0434];
DemandMaks= [188.110
75.259
121.711
253.759
1206.444
5.248
180.735
0
164.510
0];
BM= 1000000;
Tmax= 480;
ProcessTime= [1];
SetupTime= [0.1];
TotalLogLamaSimpan=[0.030 2.770
3.776 5.530
2.993 3.880
1.678 2.970
1.588 0.140];
your model is not feasible. If you label your constraints then CPLEX will give you some relaxation and conflicts that will help you understand why.
For instance:
forall (d in Diameter_Log, l in Panjang_Log)
ct1:TotalLogLamaSimpan[<d,l>]>=LogLamaDipakai[<d,l>];
//constraint 2 : log processing
forall (l in Panjang_Log, i in RST)
ct2:sum(d in Diameter_Log, p in Cutting_Pattern) LogProduksi[<d,l,p>]*LumberRecFac[<d,p,i>]==Pi[i];
will display a conflict with ct2 and if you remove that then you get a feasible solution

How to add new constraints in the scheduling problem at CPLEX?

I am a beginner at CPLEX and I am struggling to add more constraints in my project. The script works well when I have multiple origin and destination, and just one product
I would like to do it with more products demand in each destination, and I do not know how to write the Constraints.
{string} Forest = {"A","B","C","D","E"};
{string} Destination = {"D1" , "D2"};
{string} Products = {"Pinus","Eucalyptus"};
float Demand [Destination][Products]= [[3,1],[4,5]];
float Distance [Forest][Destination]=[[21,52],[42,12],[25,15],[52,31],[9,42]];
float Stock [Forest][Products]= [[0.94,0],[0,8.62],[0,1.21],[2.6,0],[8.77,0]];`
//Decision Variables
dvar float+ Delivered [Forest][Destination];
//Função Objetivo
minimize
sum (u in Forest, c in Destination) Distance[u][c] * Delivered[u][c];
//Constraints
subject to {
forall (u in Forest)
sum (c in Destination)
Delivered[u][c] <= Stock [u];
forall (c in Destination)
sum (u in Forest)
Delivered[u][c] >= Demand[c];
}
I have cross-posted this question.
You shave to also expand your decision variable by Products (like you did for Demand and Stock) so that you can know how much of each product is delivered.
Then you can replicate each constraint for each product by adding a "forall (p in Products)".
dvar float+ Delivered [Forest][Destination][Products];
forall (p in Products)
forall (u in Forest)
sum (c in Destination)
Delivered[u][c][p] <= Stock[u][p];
you could try something like
{string} Forest = {"A","B","C","D","E"};
{string} Destination = {"D1" , "D2"};
{string} Products = {"Pinus","Eucalyptus"};
float Demand [Destination][Products]= [[3,1],[4,5]];
float Distance [Forest][Destination]=[[21,52],[42,12],[25,15],[52,31],[9,42]];
float Stock [Forest][Products]= [[0.94,0],[0,8.62],[0,1.21],[2.6,0],[8.77,0]];
//Decision Variables
dvar float+ Delivered [Products][Forest][Destination];
//Função Objetivo
minimize sum (p in Products,u in Forest, c in Destination) Distance[u][c] * Delivered[p][u][c];
//Constraints
subject to {
forall (u in Forest,p in Products) sum (c in Destination) Delivered[p][u][c] <= Stock [u][p];
forall (p in Products,c in Destination) sum (u in Forest) Delivered[p][u][c] >= Demand[c][p];
}

Reducing time complexity in maximal minimum-sum 2-partitioning of an array

Let array[N] an array of N non-negative values. We're trying to recursively partition the array in two (2) subarrays, so that we can achieve the maximum "minimum-sum" of each subarray. The solution is described by the following recursion:
We want to calculate opt[0][N-1].
Let c[x][y] denote the sum{array[i]} from x up to y (including).
I have managed to unwind the recursion in the following C++ code snippet, using dynamic programming:
for ( uint16_t K1 = 0; K1 < N; K1 ++ ) {
for ( uint16_t K2 = 0; K2 < N-K1; K2 ++ ) {
const uint16_t x = K2, y = K2 + K1;
opt[x][y] = 0;
for ( uint16_t w = x; w < y; w ++ ) {
uint32_t left = c[x][w] + opt[x][w];
uint32_t right = c[w+1][y] + opt[w+1][y];
/* Choose minimum between left-right */
uint32_t val = MIN( left, right );
/* Best opt[x][y] ? */
if ( val > opt[x][y] ) {
opt[x][y] = val;
}
}
} /* K2 */
} /* K1 */
This technique parses all subarrays, beginning from size 1 and up to size N. The final solution will thus be stored in opt[0][N-1].
For example, if N=6, the matrix will be iterated as follows: (0,0) (1,1) (2,2) (3,3) (4,4) (5,5) (0,1) (1,2) (2,3) (3,4) (4,5) (0,2) (1,3) (2,4) (3,5) (0,3) (1,4) (2,5) (0,4) (1,5) (0,5). The final answer will be in opt[0][5].
I have tested and verified that the above technique works to unwind the recursion. I am trying to further reduce the complexity, as this will run in O(n^3), if I'm correct. Could this be achieved?
edit: I'm also noting the physical meaning of the recursion, as it was asked in the comments. Let N denote N cities across a straight line. We're a landlord who controls these cities; at the end of a year, each city i pays an upkeep of array[i] coins as long as it's under our control.
Our cities are under attack by a superior force and defeat is unavoidable. At the beginning of each year, we erect a wall between two adjacent cities i,i+1, x <= i <= y. During each year, the enemy forces will attack either from the west, thus conquering all cities in [x,i], or will attack from the east, thus conquering all cities in [i+1,y]. The remaining cities will pay us their upkeep at the end of the year. The enemy forces destroy the wall at the end of the year, retreat, and launch a new attack in the following year. The game ends when only 1 city is left standing.
The enemy forces will always attack from the optimal position, in order to reduce our maximum income over time. Our strategy is to choose the optimal position of the wall, so as to maximize our total income at the end of the game.
Here's the final answer to the problem, following the contribution of #NiklasB. . Let w(x,y) denote the optimal partition of an array for the problem opt[x][y]. As follows, x <= w(x,y) < y. We assume that the positions for all subproblems opt[x][y] with a given subarray size d = y-x are known.
Let's now try to find the optimal w positions for all subproblems of size k+1. We can easily prove that w(x,y+1) >= w(x,y); IOW if we add another element to the right, the optimal partition might "move to the right", in order to more evenly balance the two sums; it however cannot "move to the left". In a similar fashion, w(x-1,y) <= w(x,y).
NB: it would be helpful if someone could attempt to mathematically verify the above.
As follows, let wall[x][y] denote the optimal w solution for the subproblem opt[x][y]. Loop for ( uint16_t w = x; w < y; w ++ ) in the original snippet, will be modified as follows:
for ( uint16_t w = wall[x][y-1]; w <= wall[x+1][y]; w ++ ) {
...
if ( val > opt[x][y] ) {
opt[x][y] = val;
wall[x][y] = w;
}
}
A few modifications are needed to deal with corner cases when 0 <= y-x <= 1, but it does the job. It reduces the running time complexity from O(n^3) to O(n^2), since the time to compute the solution for a larger subproblem is amortized O(1), by taking into account the w boundaries. Example: with N = 2500, the recursive algorithm (with memoization) runs in 58 sec. The O(n^2) algorithm runs in only 148 msec.