Skip to content

Commit 9c00614

Browse files
committed
Adding comments, re-enabling logs, more metrics
1 parent fdeb544 commit 9c00614

File tree

4 files changed

+99
-24
lines changed

4 files changed

+99
-24
lines changed

java-gurobi-multiknapsack-multiexcel/src/main/java/com/nextmv/example/ExcelReader.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
import java.util.Iterator;
99
import java.util.List;
1010

11+
/**
12+
* ExcelReader class that reads the input from an Excel file.
13+
* It expects two sheets: one for items ('items') and one for
14+
* knapsacks ('knapsacks'). Each sheet should have a header row.
15+
*/
1116
public class ExcelReader {
1217

1318
public Input readExcelFile(String filePath) throws IOException {

java-gurobi-multiknapsack-multiexcel/src/main/java/com/nextmv/example/ExcelWriter.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,19 @@
66
import java.io.IOException;
77
import java.util.List;
88

9+
/**
10+
* ExcelWriter class to write the solution to an Excel file.
11+
* It creates two sheets: one for assignments and one for unassigned items.
12+
*/
913
public class ExcelWriter {
1014

15+
/**
16+
* Writes the solution to an Excel file.
17+
*
18+
* @param solution The solution containing assignments and unassigned items.
19+
* @param filePath The path where the Excel file will be saved.
20+
* @throws IOException If an I/O error occurs while writing the file.
21+
*/
1122
public void writeSolutionToExcel(Solution solution, String filePath) throws IOException {
1223
Workbook workbook = new XSSFWorkbook();
1324

@@ -56,7 +67,10 @@ private void createUnassignedSheet(Sheet sheet, List<String> unassigned) {
5667
}
5768
}
5869

59-
// Assuming these classes are defined as follows:
70+
/**
71+
* Represents a solution containing assignments of items to knapsacks
72+
* and a list of unassigned items.
73+
*/
6074
class Solution {
6175
private List<Assignment> assignments;
6276
private List<String> unassigned;
@@ -75,6 +89,9 @@ public List<String> getUnassigned() {
7589
}
7690
}
7791

92+
/**
93+
* Represents an assignment of an item to a knapsack.
94+
*/
7895
class Assignment {
7996
private String itemId;
8097
private String knapsackId;

java-gurobi-multiknapsack-multiexcel/src/main/java/com/nextmv/example/Main.java

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111

1212
public final class Main {
1313

14+
/**
15+
* Main entry point for the application.
16+
*
17+
* @param args Command line arguments.
18+
*/
1419
public static void main(String[] args) {
1520
try {
1621
// Parse arguments.
@@ -43,7 +48,7 @@ public static void main(String[] args) {
4348

4449
// Setup Gurobi environment and model.
4550
GRBEnv env = new GRBEnv(true);
46-
env.set("OutputFlag", "0"); // Disable output if needed
51+
// env.set("OutputFlag", "0"); // Disable output if needed
4752
env.start();
4853
GRBModel model = new GRBModel(env);
4954

@@ -53,9 +58,10 @@ public static void main(String[] args) {
5358
// Create assignment variable for each item in each knapsack.
5459
// Variables are binary, indicating whether an item is assigned to a knapsack.
5560
List<GRBVar> variables = new ArrayList<>();
56-
List<Item> inputItems = input.getItems();
57-
for (Knapsack knapsack : input.getKnapsacks()) {
58-
for (Item item : inputItems) {
61+
List<Item> items = input.getItems();
62+
List<Knapsack> knapsacks = input.getKnapsacks();
63+
for (Knapsack knapsack : knapsacks) {
64+
for (Item item : items) {
5965
variables.add(model.addVar(0.0, 1.0, 0.0, GRB.BINARY, knapsack.getId() + "_" + item.getId()));
6066
}
6167
}
@@ -64,29 +70,29 @@ public static void main(String[] args) {
6470
model.update();
6571

6672
// Create capacity constraint.
67-
for (int i = 0; i < input.getKnapsacks().size(); ++i) {
68-
Knapsack knapsack = input.getKnapsacks().get(i);
73+
for (int i = 0; i < knapsacks.size(); ++i) {
74+
Knapsack knapsack = knapsacks.get(i);
6975
GRBLinExpr knapsackExpr = new GRBLinExpr();
70-
for (int j = 0; j < inputItems.size(); ++j) {
71-
knapsackExpr.addTerm(inputItems.get(j).getWeight(), variables.get(i * inputItems.size() + j));
76+
for (int j = 0; j < items.size(); ++j) {
77+
knapsackExpr.addTerm(items.get(j).getWeight(), variables.get(i * items.size() + j));
7278
}
7379
model.addConstr(knapsackExpr, GRB.LESS_EQUAL, knapsack.getCapacity(), "capacity_" + knapsack.getId());
7480
}
7581

7682
// Ensure that each item can only be assigned once.
77-
for (int j = 0; j < inputItems.size(); ++j) {
83+
for (int j = 0; j < items.size(); ++j) {
7884
GRBLinExpr itemExpr = new GRBLinExpr();
79-
for (int i = 0; i < input.getKnapsacks().size(); ++i) {
80-
itemExpr.addTerm(1.0, variables.get(i * inputItems.size() + j));
85+
for (int i = 0; i < knapsacks.size(); ++i) {
86+
itemExpr.addTerm(1.0, variables.get(i * items.size() + j));
8187
}
82-
model.addConstr(itemExpr, GRB.LESS_EQUAL, 1.0, "item_assignment_" + inputItems.get(j).getId());
88+
model.addConstr(itemExpr, GRB.LESS_EQUAL, 1.0, "item_assignment_" + items.get(j).getId());
8389
}
8490

8591
// Create the objective function.
8692
GRBLinExpr objectiveExpr = new GRBLinExpr();
87-
for (int i = 0; i < input.getKnapsacks().size(); ++i) {
88-
for (int j = 0; j < inputItems.size(); ++j) {
89-
objectiveExpr.addTerm(inputItems.get(j).getValue(), variables.get(i * inputItems.size() + j));
93+
for (int i = 0; i < knapsacks.size(); ++i) {
94+
for (int j = 0; j < items.size(); ++j) {
95+
objectiveExpr.addTerm(items.get(j).getValue(), variables.get(i * items.size() + j));
9096
}
9197
}
9298
model.setObjective(objectiveExpr, GRB.MAXIMIZE);
@@ -98,13 +104,13 @@ public static void main(String[] args) {
98104
List<Assignment> assignments = new ArrayList<>();
99105
Set<String> unassignedItems = new HashSet<>();
100106
for (int i = 0; i < variables.size(); ++i) {
101-
int knapsackIndex = i / inputItems.size();
102-
int itemIndex = i % inputItems.size();
107+
int knapsackIndex = i / items.size();
108+
int itemIndex = i % items.size();
103109
if (variables.get(i).get(GRB.DoubleAttr.X) > 0.5) {
104110
assignments
105-
.add(new Assignment(inputItems.get(itemIndex).getId(), input.getKnapsacks().get(knapsackIndex).getId()));
111+
.add(new Assignment(items.get(itemIndex).getId(), knapsacks.get(knapsackIndex).getId()));
106112
} else {
107-
unassignedItems.add(inputItems.get(itemIndex).getId());
113+
unassignedItems.add(items.get(itemIndex).getId());
108114
}
109115
}
110116
Solution solution = new Solution(assignments, new ArrayList<>(unassignedItems));
@@ -125,7 +131,11 @@ public static void main(String[] args) {
125131
"Gurobi",
126132
convertStatus(model.get(GRB.IntAttr.Status)),
127133
model.get(GRB.IntAttr.NumVars),
128-
model.get(GRB.IntAttr.NumConstrs));
134+
model.get(GRB.IntAttr.NumConstrs),
135+
items.size(),
136+
knapsacks.size(),
137+
assignments.size(),
138+
unassignedItems.size());
129139

130140
// Write output.
131141
Output.write(output, options.getOutputPath());
@@ -140,6 +150,11 @@ public static void main(String[] args) {
140150
}
141151
}
142152

153+
/**
154+
* Prepares the output directory by creating necessary subdirectories.
155+
*
156+
* @param outputPath The path to the output directory.
157+
*/
143158
private static void prepareOutputDirectory(String outputPath) {
144159
// Prepare output directory if it does not exist.
145160
Path solutionsPath = Paths.get(outputPath, "solutions");
@@ -164,6 +179,12 @@ private static void prepareOutputDirectory(String outputPath) {
164179
}
165180
}
166181

182+
/**
183+
* Converts Gurobi status codes to human-readable strings.
184+
*
185+
* @param status The Gurobi status code.
186+
* @return A string representation of the status.
187+
*/
167188
public static String convertStatus(int status) {
168189
switch (status) {
169190
case GRB.Status.LOADED:

java-gurobi-multiknapsack-multiexcel/src/main/java/com/nextmv/example/Output.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,59 @@
11
package com.nextmv.example;
22

3-
import java.util.List;
4-
import java.util.ArrayList;
53
import java.nio.file.Files;
64
import java.nio.file.Paths;
75

86
import com.google.gson.Gson;
97

8+
/**
9+
* Output class to wrapping the result of the optimization run.
10+
* Since this app outputs non-JSON data, the output only contains
11+
* the statistics of the run. The solution is written to separate
12+
* files in the output directory.
13+
*/
1014
public class Output {
15+
/**
16+
* StatisticsRun contains more generic metrics about the run.
17+
*/
1118
private final class StatisticsRun {
1219
private double duration;
1320
}
1421

22+
/**
23+
* StatisticsResult contains metrics about the optimization result.
24+
*/
1525
private final class StatisticsResult {
1626
private double value;
1727
private StatisticsResultCustom custom;
1828
}
1929

30+
/**
31+
* StatisticsResultCustom contains custom metrics about the optimization
32+
* result.
33+
*/
2034
private final class StatisticsResultCustom {
2135
private String provider;
2236
private String status;
2337
private int variables;
2438
private int constraints;
39+
private int items;
40+
private int knapsacks;
41+
private int assigned;
42+
private int unassigned;
2543
}
2644

45+
/**
46+
* Statistics is the root object for the metrics/statistics.
47+
*/
2748
private final class Statistics {
2849
private String schema = "v1";
2950
private StatisticsRun run;
3051
private StatisticsResult result;
3152
}
3253

54+
/**
55+
* The statistics object that contains all the metrics.
56+
*/
3357
private final Statistics statistics;
3458

3559
public Output(
@@ -38,7 +62,11 @@ public Output(
3862
String provider,
3963
String status,
4064
int variables,
41-
int constraints) {
65+
int constraints,
66+
int items,
67+
int knapsacks,
68+
int assigned,
69+
int unassigned) {
4270
this.statistics = new Statistics();
4371
this.statistics.run = new StatisticsRun();
4472
this.statistics.run.duration = duration;
@@ -49,6 +77,10 @@ public Output(
4977
this.statistics.result.custom.status = status;
5078
this.statistics.result.custom.constraints = constraints;
5179
this.statistics.result.custom.variables = variables;
80+
this.statistics.result.custom.items = items;
81+
this.statistics.result.custom.knapsacks = knapsacks;
82+
this.statistics.result.custom.assigned = assigned;
83+
this.statistics.result.custom.unassigned = unassigned;
5284
}
5385

5486
public static void write(Output output, String outputPath) {

0 commit comments

Comments
 (0)