Skip to main content

Opposite Signs in Gurobi Dual Variables Output

Answered

Comments

3 comments

  • Matthias Miltenberger
    Gurobi Staff Gurobi Staff

    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,
    Matthias

    0
  • Yuan Jiawei Yuan Jiawei
    Gurobi-versary
    First Comment
    First Question

      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
  • Riley Clement
    Gurobi Staff Gurobi Staff

    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.