From 4fdb4f559e804d3ec269da520feb40a22059daa8 Mon Sep 17 00:00:00 2001 From: Sebastian Quintero Date: Tue, 10 Sep 2024 17:26:29 -0500 Subject: [PATCH] Add missing Java files --- .gitignore | 1 - .../main/java/com/nextmv/example/Main.java | 63 ++++++++++ .../main/java/com/nextmv/example/Input.java | 66 +++++++++++ .../main/java/com/nextmv/example/Main.java | 109 ++++++++++++++++++ .../main/java/com/nextmv/example/Options.java | 65 +++++++++++ .../main/java/com/nextmv/example/Vehicle.java | 28 +++++ 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 java-hello-world/src/main/java/com/nextmv/example/Main.java create mode 100644 java-ortools-routing/src/main/java/com/nextmv/example/Input.java create mode 100644 java-ortools-routing/src/main/java/com/nextmv/example/Main.java create mode 100644 java-ortools-routing/src/main/java/com/nextmv/example/Options.java create mode 100644 java-ortools-routing/src/main/java/com/nextmv/example/Vehicle.java diff --git a/.gitignore b/.gitignore index 7e747e4..fffc984 100644 --- a/.gitignore +++ b/.gitignore @@ -174,7 +174,6 @@ main.jar *output* # Ignore app binary files -main go-highs-orderfulfillment/go-highs-orderfulfillment go-highs-knapsack/go-highs-knapsack go-highs-shiftscheduling/go-highs-shiftscheduling diff --git a/java-hello-world/src/main/java/com/nextmv/example/Main.java b/java-hello-world/src/main/java/com/nextmv/example/Main.java new file mode 100644 index 0000000..9cd5c5a --- /dev/null +++ b/java-hello-world/src/main/java/com/nextmv/example/Main.java @@ -0,0 +1,63 @@ +package com.nextmv.example; + +import com.google.gson.Gson; +import java.io.FileReader; +import java.io.IOException; +import com.google.gson.JsonObject; + +public class Main { + public static void main(String[] args) { + Gson gson = new Gson(); + + + try (FileReader reader = new FileReader("input.json")) { + // Read from stdin. + Input input = gson.fromJson(reader, Input.class); + + // ##### Insert model here + + // Print logs that render in the run view in Nextmv Console + System.err.println("Hello, " + input.name); + + // Write output and statistics. + Output output = new Output(input.name); + Output.write(output); + } catch (IOException e) { + e.printStackTrace(); + } + } +} + + +class Input { + String name; +} + + +class Output { + JsonObject options = new JsonObject(); + Solution solution; + Statistics statistics; + + public Output(String name) { + this.solution = new Solution(); + this.statistics = new Statistics("Hello, " + name); + } + + public static void write(Output output) { + Gson gson = new Gson(); + System.out.println(gson.toJson(output)); + } +} + +class Solution {} + +class Statistics { + String message; + + public Statistics(String message) { + this.message = message; + } +} + + diff --git a/java-ortools-routing/src/main/java/com/nextmv/example/Input.java b/java-ortools-routing/src/main/java/com/nextmv/example/Input.java new file mode 100644 index 0000000..44ab0d6 --- /dev/null +++ b/java-ortools-routing/src/main/java/com/nextmv/example/Input.java @@ -0,0 +1,66 @@ +package com.nextmv.example; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.stream.Collectors; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +public class Input { + @SerializedName(value = "distance_matrix") + public final long[][] distanceMatrix; + @SerializedName(value = "num_vehicles") + public final int vehicleNumber; + public final int depot; + + public Input(int vehicleNumber, int depot, long[][] distanceMatrix) { + this.distanceMatrix = new long[vehicleNumber+1][vehicleNumber+1]; + this.vehicleNumber = vehicleNumber; + this.depot = depot; + for (int i = 0; i < vehicleNumber+1; i++) { + for (int j = 0; j < vehicleNumber+1; j++) { + this.distanceMatrix[i][j] = distanceMatrix[i][j]; + } + } + } + + public long[][] getDistanceMatrix() { + return this.distanceMatrix; + } + + public int getVehicleNumber() { + return this.vehicleNumber; + } + + public int getDepot() { + return this.depot; + } + + public static Input fromString(String path) { + Gson gson = new Gson(); + // Read stdin if no path is provided. + if (path.isEmpty()) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + return gson.fromJson( + reader.lines().collect(Collectors.joining("\n")), Input.class + ); + } catch (java.io.IOException e) { + System.err.println("Error reading stdin: " + e.getMessage()); + System.exit(1); + return null; + } + } + // Read the path otherwise. + try { + return gson.fromJson( + java.nio.file.Files.readString(java.nio.file.Paths.get(path)), + Input.class + ); + } catch (java.io.IOException e) { + System.err.println("Error reading '" + path + "': " + e.getMessage()); + System.exit(1); + } + return null; + } +} diff --git a/java-ortools-routing/src/main/java/com/nextmv/example/Main.java b/java-ortools-routing/src/main/java/com/nextmv/example/Main.java new file mode 100644 index 0000000..079de69 --- /dev/null +++ b/java-ortools-routing/src/main/java/com/nextmv/example/Main.java @@ -0,0 +1,109 @@ +package com.nextmv.example; + +import com.google.ortools.Loader; +import com.google.ortools.constraintsolver.Assignment; +import com.google.ortools.constraintsolver.FirstSolutionStrategy; +import com.google.ortools.constraintsolver.RoutingIndexManager; +import com.google.ortools.constraintsolver.RoutingModel; +import com.google.ortools.constraintsolver.RoutingSearchParameters; + +import com.google.ortools.constraintsolver.main; +import com.google.protobuf.Duration; + +import java.util.ArrayList; +import java.util.List; + +public final class Main { + public static void main(String[] args) { + // Record start time of the program. + long startTime = System.currentTimeMillis(); + // Parse arguments. Exit on error. + Options options = Options.fromArguments(args); + + // Load input. Exit on error. + Input input = Input.fromString(options.getInputPath()); + + Loader.loadNativeLibraries(); + + // Create Routing Index Manager. + RoutingIndexManager manager = new RoutingIndexManager(input.distanceMatrix.length, input.vehicleNumber, + input.depot); + + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + + // Create and register a transit callback. + final int transitCallbackIndex = routing.registerTransitCallback((long fromIndex, long toIndex) -> { + // Convert from routing variable Index to user NodeIndex. + int fromNode = manager.indexToNode(fromIndex); + int toNode = manager.indexToNode(toIndex); + return input.distanceMatrix[fromNode][toNode]; + }); + + // Define cost of each arc. + routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex); + + // Set the duration of the search. + Duration duration = Duration.newBuilder().setSeconds(options.getDuration()).build(); + + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = main.defaultRoutingSearchParameters() + .toBuilder() + .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC) + .setTimeLimit(duration) + .build(); + + // Solve the problem. + // Record solve start time + long solveStartTime = System.currentTimeMillis(); + Assignment solution = routing.solveWithParameters(searchParameters); + + Output output = getOutput(startTime, input, routing, manager, solution, solveStartTime); + + // Write output. Exit on error. + Output.write(options.getOutputPath(), output); + } + + static Output getOutput( + long startTime, + Input input, + RoutingModel routing, + RoutingIndexManager manager, + Assignment solution, long solveStartTime) { + long maxRouteDistance = 0; + List vehicles = new ArrayList(); + for (int i = 0; i < input.vehicleNumber; ++i) { + List stops = new ArrayList(); + long index = routing.start(i); + long routeDistance = 0; + while (!routing.isEnd(index)) { + stops.add(manager.indexToNode(index)); + long previousIndex = index; + index = solution.value(routing.nextVar(index)); + routeDistance += routing.getArcCostForVehicle(previousIndex, index, i); + } + stops.add(manager.indexToNode(index)); + Vehicle vehicle = new Vehicle(i, routeDistance, stops); + vehicles.add(vehicle); + maxRouteDistance = Math.max(routeDistance, maxRouteDistance); + } + + // Compute solve duration. + long endTime = System.currentTimeMillis(); + double duration = endTime - solveStartTime; + // Convert duration to seconds. + duration = duration / 1000.0; + + // Compute total duration. + endTime = System.currentTimeMillis(); + double runDuration = endTime - startTime; + // Convert duration to seconds. + runDuration = runDuration / 1000.0; + + // Create output. + return new Output( + vehicles, + duration, + runDuration); + } +} diff --git a/java-ortools-routing/src/main/java/com/nextmv/example/Options.java b/java-ortools-routing/src/main/java/com/nextmv/example/Options.java new file mode 100644 index 0000000..ee80cfa --- /dev/null +++ b/java-ortools-routing/src/main/java/com/nextmv/example/Options.java @@ -0,0 +1,65 @@ +package com.nextmv.example; + +public class Options { + private final String inputPath; + private final String outputPath; + private final int duration; + + public Options(String inputPath, String outputPath, int duration) { + this.inputPath = inputPath; + this.outputPath = outputPath; + this.duration = duration; + } + + public String getInputPath() { + return this.inputPath; + } + + public String getOutputPath() { + return this.outputPath; + } + + public int getDuration() { + return this.duration; + } + + public static Options fromArguments(String[] args) { + String inputPath = ""; + String outputPath = ""; + int duration = 30; + + for (int i = 0; i < args.length; ++i) { + switch (args[i]) { + case "-i": + case "--input": + inputPath = args[++i]; + break; + case "-o": + case "--output": + outputPath = args[++i]; + break; + case "-d": + case "--duration": + duration = Integer.parseInt(args[++i]); + break; + case "-h": + case "--help": + System.out.println("Usage: java -jar basic_example.jar [OPTIONS]"); + System.out.println("Solve a simple linear program."); + System.out.println(); + System.out.println("Supported options:"); + System.out.println(" -i, --input: path to the input file"); + System.out.println(" -o, --output: path to the output file"); + System.out.println(" -d, --duration: duration of the search in seconds"); + System.out.println(" -h, --help: print the help"); + System.exit(0); + break; + default: + System.err.println("Unknown argument: '" + args[i] + "'"); + System.exit(1); + } + } + + return new Options(inputPath, outputPath, duration); + } +} diff --git a/java-ortools-routing/src/main/java/com/nextmv/example/Vehicle.java b/java-ortools-routing/src/main/java/com/nextmv/example/Vehicle.java new file mode 100644 index 0000000..0c4118d --- /dev/null +++ b/java-ortools-routing/src/main/java/com/nextmv/example/Vehicle.java @@ -0,0 +1,28 @@ +package com.nextmv.example; + +import java.util.List; + +public class Vehicle { + public final int vehicle; + public final double distance; + public final List stops; + + public Vehicle(int vehicle, double distance, List stops) { + this.vehicle = vehicle; + this.distance = distance; + this.stops = stops; + } + + public int getVehicle() { + return this.vehicle; + } + + public double getDistance() { + return this.distance; + } + + public List getStops() { + return this.stops; + } + +}