Opposite Signs in Gurobi Dual Variables Output
AnsweredWhen I call Gurobi to output the dual variables, the outputted dual variables are exactly the opposite of the actual dual variables. Could you explain the reason for this, or provide the standard form of the dual variables as output by Gurobi?"
0
-
Hi Yuan,
Maybe it's a maximization problem, and that's why the values are different than you expected.
You would need to share more details to provide a better answer.Cheers,
Matthias0 -
Hi, Matthias, the following is my problem:
GRBVar[,,,] SeatNum = new GRBVar[TotalStaNum, TotalStaNum, TotalTypeNum, TotalSerNum];
for (int i = 0; i < TotalStaNum - 1; i++)
{
for (int j = i + 1; j < TotalStaNum; j++)
{
for (int z = 0; z < TotalTypeNum; z++)
{
for (int k = 0; k < TotalSerNum; k++)
{
SeatNum[i, j, z, k] = model.AddVar(0, double.MaxValue, 0, GRB.CONTINUOUS, "d_");
}
}
}
}
GRBVar[,,] ReDemand = new GRBVar[TotalStaNum, TotalStaNum, TotalTypeNum];//停站方案选择
for (int i = 0; i < TotalStaNum - 1; i++)
{
for (int j = i + 1; j < TotalStaNum; j++)
{
for (int z = 0; z < TotalTypeNum; z++)
{
ReDemand[i, j, z] = model.AddVar(0, double.MaxValue, 0, GRB.CONTINUOUS, "d_");
}
}
}
//GRBVar Theta = model.AddVar(0, double.MaxValue, 0, GRB.CONTINUOUS, "d_");
GRBLinExpr Obj = 0;
for (int i = 0; i < TotalStaNum; i++)
{
for (int j = i + 1; j < TotalStaNum; j++)
{
for (int z = 0; z < TotalTypeNum; z++)
{
Obj.Add(ReDemand[i, j, z] * StaticData.ReDemandCost[i, j, z]);
}
}
}
model.SetObjective(Obj, GRB.MINIMIZE);
for (int i = 0; i < TotalStaNum - 1; i++)
{
for (int j = i + 1; j < TotalStaNum; j++)
{
for (int z = 0; z < TotalTypeNum; z++)
{
GRBLinExpr x = ReDemand[ i, j, z];
for (int k = 0; k < TotalSerNum; k++)
{
x.Add(SeatNum[ i, j, z, k]);
}
model.AddConstr(x == StaticData.LDemandNum[i, j, z] + StaticData.UDemandNum[i, j, z] * StaticData.CurrentUncertain[i,j,z], "c7"+i+j+z);
}
}
}
for (int i = 0; i < TotalStaNum; i++)
{
for (int j = i + 1; j < TotalStaNum; j++)
{
for (int z = 0; z < TotalTypeNum; z++)
{
for (int k = 0; k < TotalSerNum; k++)
{
GRBLinExpr x = 0;
for (int u = 0; u < TotalPatNum; u++)
{
x.Add(StaticData.TrainPattern[k, u] * StaticData.PatStop[u, i] * StaticData.PatStop[u, j]);
}
double M = StaticData.LDemandNum[i, j, z] + StaticData.UDemandNum[i, j, z];
model.AddConstr(SeatNum[i, j, z, k] <= M * x, "c8" + i + j + z + k);
}
}
}
}
for (int k = 0; k < TotalSerNum; k++)
{
for (int z = 0; z < TotalTypeNum; z++)
{
GRBLinExpr y = 0;
for (int v = 0; v < TotalCompoNum; v++)
{
y.Add(StaticData.TrainCompo[k, v] * StaticData.CompoCapacity[v, z]);
}
for (int e = 0; e < TotalSegNum; e++)
{
GRBLinExpr x = 0;
for (int i = 0; i < e + 1; i++)
{
for (int j = e + 1; j < TotalStaNum; j++)
{
x.Add(SeatNum[i, j, z, k]);
}
}
model.AddConstr(x <= y, "c9"+k+z+e);
}
}
}
model.Optimize();0 -
You can always add this to your code to check strong duality
int optimstatus = model.get(GRB.IntAttr.Status);
if (optimstatus == GRB.Status.OPTIMAL) {
double objval = model.get(GRB.DoubleAttr.ObjVal);
int numVars = model.get(GRB.IntAttr.NumVars);
int numConstrs = model.get(GRB.IntAttr.NumConstrs);
GRBVar[] vars = model.getVars();
GRBConstr[] constrs = model.getConstrs();
double[] pi = model.get(GRB.DoubleAttr.Pi, constrs);
double[] rhs = model.get(GRB.DoubleAttr.RHS, constrs);
double[] rc = model.get(GRB.DoubleAttr.RC, vars);
double[] lb = model.get(GRB.DoubleAttr.LB, vars);
double[] ub = model.get(GRB.DoubleAttr.UB, vars);
int[] vb = model.get(GRB.IntAttr.VBasis, vars);
double dualObj = 0;
for (int i = 0; i < numConstrs; i++)
dualObj += pi[i]*rhs[i];
for (int i = 0; i < numVars; i++) {
if (vb[i] == -1)
dualObj += rc[i]*lb[i];
else if (vb[i] == -2)
dualObj += rc[i]*ub[i];
};
System.out.println("Strong duality: " + (objval == dualObj));
}If strong duality is true then your dual values are correct. (The above code assumes the objective doesn't have a constant).
0
Please sign in to leave a comment.
Comments
3 comments