Multiobj.java#

/* Copyright 2024, Gurobi Optimization, LLC */

/* Want to cover three different sets but subject to a common budget of
   elements allowed to be used. However, the sets have different priorities to
   be covered; and we tackle this by using multi-objective optimization. */

import com.gurobi.gurobi.*;

public class Multiobj {
  public static void main(String[] args) {

    try {
      // Sample data
      int groundSetSize = 20;
      int nSubsets      = 4;
      int Budget        = 12;
      double Set[][] = new double[][]
      { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
        { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0 },
        { 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0 } };
      int    SetObjPriority[] = new int[] {3, 2, 2, 1};
      double SetObjWeight[]   = new double[] {1.0, 0.25, 1.25, 1.0};
      int e, i, status, nSolutions;

      // Create environment
      GRBEnv env = new GRBEnv("Multiobj.log");

      // Create initial model
      GRBModel model = new GRBModel(env);
      model.set(GRB.StringAttr.ModelName, "Multiobj");

      // Initialize decision variables for ground set:
      // x[e] == 1 if element e is chosen for the covering.
      GRBVar[] Elem = model.addVars(groundSetSize, GRB.BINARY);
      for (e = 0; e < groundSetSize; e++) {
        String vname = "El" + String.valueOf(e);
        Elem[e].set(GRB.StringAttr.VarName, vname);
      }

      // Constraint: limit total number of elements to be picked to be at most
      // Budget
      GRBLinExpr lhs = new GRBLinExpr();
      for (e = 0; e < groundSetSize; e++) {
        lhs.addTerm(1.0, Elem[e]);
      }
      model.addConstr(lhs, GRB.LESS_EQUAL, Budget, "Budget");

      // Set global sense for ALL objectives
      model.set(GRB.IntAttr.ModelSense, GRB.MAXIMIZE);

      // Limit how many solutions to collect
      model.set(GRB.IntParam.PoolSolutions, 100);

      // Set and configure i-th objective
      for (i = 0; i < nSubsets; i++) {
        GRBLinExpr objn = new GRBLinExpr();
        String vname = "Set" + String.valueOf(i);

        for (e = 0; e < groundSetSize; e++)
          objn.addTerm(Set[i][e], Elem[e]);

        model.setObjectiveN(objn, i, SetObjPriority[i], SetObjWeight[i],
                            1.0 + i, 0.01, vname);
      }

      // Save problem
      model.write("Multiobj.lp");

      // Optimize
      model.optimize();

      // Status checking
      status = model.get(GRB.IntAttr.Status);

      if (status == GRB.INF_OR_UNBD ||
          status == GRB.INFEASIBLE  ||
          status == GRB.UNBOUNDED     ) {
        System.out.println("The model cannot be solved " +
                 "because it is infeasible or unbounded");
        System.exit(1);
      }
      if (status != GRB.OPTIMAL) {
        System.out.println("Optimization was stopped with status " + status);
        System.exit(1);
      }

      // Print best selected set
      System.out.println("Selected elements in best solution:");
      System.out.println("\t");
      for (e = 0; e < groundSetSize; e++) {
        if (Elem[e].get(GRB.DoubleAttr.X) < .9) continue;
        System.out.print(" El" + e);
      }
      System.out.println();

      // Print number of solutions stored
      nSolutions = model.get(GRB.IntAttr.SolCount);
      System.out.println("Number of solutions found: " + nSolutions);

      // Print objective values of solutions
      if (nSolutions > 10) nSolutions = 10;
      System.out.println("Objective values for first " + nSolutions);
      System.out.println(" solutions:");
      for (i = 0; i < nSubsets; i++) {
        model.set(GRB.IntParam.ObjNumber, i);

        System.out.print("\tSet" + i);
        for (e = 0; e < nSolutions; e++) {
          System.out.print(" ");
          model.set(GRB.IntParam.SolutionNumber, e);
          double val = model.get(GRB.DoubleAttr.ObjNVal);
          System.out.print("      " + val);
        }
        System.out.println();
      }
      model.dispose();
      env.dispose();
    } catch (GRBException e) {
      System.out.println("Error code = " + e.getErrorCode());
      System.out.println(e.getMessage());
    }
  }
}