diff --git a/ortools/linear_solver/samples/AssignmentMb.cs b/ortools/linear_solver/samples/AssignmentMb.cs index a1213c7ff0..8dbdb59685 100644 --- a/ortools/linear_solver/samples/AssignmentMb.cs +++ b/ortools/linear_solver/samples/AssignmentMb.cs @@ -87,12 +87,9 @@ public class AssignmentMb // [END objective] // [START solver] - // Create the model solver with the SCIP backend. + // Create the solver with the SCIP backend and check it is supported. ModelSolver solver = new ModelSolver("SCIP"); - if (!solver.SolverIsSupported()) - { - return; - } + if (!solver.SolverIsSupported()) return; // [END solver] // Solve @@ -103,7 +100,7 @@ public class AssignmentMb // Print solution. // [START print_solution] // Check that the problem has a feasible solution. - if (resultStatus == SolverStatus.OPTIMAL || resultStatus == SolverStatus.FEASIBLE) + if (resultStatus == SolveStatus.OPTIMAL || resultStatus == SolveStatus.FEASIBLE) { Console.WriteLine($"Total cost: {solver.ObjectiveValue}\n"); for (int i = 0; i < numWorkers; ++i) diff --git a/ortools/linear_solver/samples/AssignmentMb.java b/ortools/linear_solver/samples/AssignmentMb.java new file mode 100644 index 0000000000..0990d9c229 --- /dev/null +++ b/ortools/linear_solver/samples/AssignmentMb.java @@ -0,0 +1,125 @@ +// Copyright 2010-2022 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// [START program] +package com.google.ortools.linearsolver.samples; +// [START import] +import com.google.ortools.Loader; +import com.google.ortools.modelbuilder.LinearConstraint; +import com.google.ortools.modelbuilder.LinearExpr; +import com.google.ortools.modelbuilder.LinearExprBuilder; +import com.google.ortools.modelbuilder.ModelBuilder; +import com.google.ortools.modelbuilder.ModelSolver; +import com.google.ortools.modelbuilder.SolveStatus; +import com.google.ortools.modelbuilder.Variable; +// [END import] + +/** MIP example that solves an assignment problem. */ +public class AssignmentMb { + public static void main(String[] args) { + Loader.loadNativeLibraries(); + // Data + // [START data_model] + double[][] costs = { + {90, 80, 75, 70}, + {35, 85, 55, 65}, + {125, 95, 90, 95}, + {45, 110, 95, 115}, + {50, 100, 90, 100}, + }; + int numWorkers = costs.length; + int numTasks = costs[0].length; + // [END data_model] + + // [START model] + ModelBuilder model = new ModelBuilder(); + // [END model] + + // Variables + // [START variables] + // x[i][j] is an array of 0-1 variables, which will be 1 + // if worker i is assigned to task j. + Variable[][] x = new Variable[numWorkers][numTasks]; + for (int i = 0; i < numWorkers; ++i) { + for (int j = 0; j < numTasks; ++j) { + x[i][j] = model.newBoolVar(""); + } + } + // [END variables] + + // Constraints + // [START constraints] + // Each worker is assigned to at most one task. + for (int i = 0; i < numWorkers; ++i) { + LinearExprBuilder assignedWork = LinearExpr.newBuilder(); + for (int j = 0; j < numTasks; ++j) { + assignedWork.add(x[i][j]); + } + model.addLessOrEqual(assignedWork, 1); + } + + // Each task is assigned to exactly one worker. + for (int j = 0; j < numTasks; ++j) { + LinearExprBuilder assignedWorker = LinearExpr.newBuilder(); + for (int i = 0; i < numWorkers; ++i) { + assignedWorker.add(x[i][j]); + } + model.addEquality(assignedWorker, 1); + } + // [END constraints] + + // Objective + // [START objective] + LinearExprBuilder objective = LinearExpr.newBuilder(); + for (int i = 0; i < numWorkers; ++i) { + for (int j = 0; j < numTasks; ++j) { + objective.addTerm(x[i][j], costs[i][j]); + } + } + model.minimize(objective); + // [END objective] + + // [START solver] + // Create the solver with the SCIP backend and check it is supported. + ModelSolver solver = new ModelSolver("scip"); + if (!solver.solverIsSupported()) return; + // [END solver] + + // [START solve] + final SolveStatus resultStatus = solver.solve(model); + // [END solve] + + // Print solution. + // [START print_solution] + // Check that the problem has a feasible solution. + if (resultStatus == SolveStatus.OPTIMAL || resultStatus == SolveStatus.FEASIBLE) { + System.out.println("Total cost: " + solver.getObjectiveValue() + "\n"); + for (int i = 0; i < numWorkers; ++i) { + for (int j = 0; j < numTasks; ++j) { + // Test if x[i][j] is 0 or 1 (with tolerance for floating point + // arithmetic). + if (solver.getValue(x[i][j]) > 0.9) { + System.out.println( + "Worker " + i + " assigned to task " + j + ". Cost = " + costs[i][j]); + } + } + } + } else { + System.err.println("No solution found."); + } + // [END print_solution] + } + + private AssignmentMb() {} +} +// [END program] diff --git a/ortools/linear_solver/samples/BinPackingMb.cs b/ortools/linear_solver/samples/BinPackingMb.cs index 31fa1a6d4b..9719be46ba 100644 --- a/ortools/linear_solver/samples/BinPackingMb.cs +++ b/ortools/linear_solver/samples/BinPackingMb.cs @@ -84,12 +84,9 @@ public class BinPackingMb // [END objective] // [START solver] - // Create the model solver with the SCIP backend. + // Create the solver with the SCIP backend and check it is supported. ModelSolver solver = new ModelSolver("SCIP"); - if (!solver.SolverIsSupported()) - { - return; - } + if (!solver.SolverIsSupported()) return; // [END solver] // [START solve] diff --git a/ortools/linear_solver/samples/BinPackingMb.java b/ortools/linear_solver/samples/BinPackingMb.java new file mode 100644 index 0000000000..b76369f860 --- /dev/null +++ b/ortools/linear_solver/samples/BinPackingMb.java @@ -0,0 +1,134 @@ +// Copyright 2010-2022 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// MIP example that solves a bin packing problem. +// [START program] +package com.google.ortools.linearsolver.samples; +// [START import] +import com.google.ortools.Loader; +import com.google.ortools.modelbuilder.LinearConstraint; +import com.google.ortools.modelbuilder.LinearExpr; +import com.google.ortools.modelbuilder.LinearExprBuilder; +import com.google.ortools.modelbuilder.ModelBuilder; +import com.google.ortools.modelbuilder.ModelSolver; +import com.google.ortools.modelbuilder.SolveStatus; +import com.google.ortools.modelbuilder.Variable; +// [END import] + +/** Bin packing problem. */ +public class BinPackingMb { + // [START program_part1] + // [START data_model] + static class DataModel { + public final double[] weights = {48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30}; + public final int numItems = weights.length; + public final int numBins = weights.length; + public final int binCapacity = 100; + } + // [END data_model] + + public static void main(String[] args) throws Exception { + Loader.loadNativeLibraries(); + // [START data] + final DataModel data = new DataModel(); + // [END data] + // [END program_part1] + + // [START model] + ModelBuilder model = new ModelBuilder(); + // [END model] + + // [START program_part2] + // [START variables] + Variable[][] x = new Variable[data.numItems][data.numBins]; + for (int i = 0; i < data.numItems; ++i) { + for (int j = 0; j < data.numBins; ++j) { + x[i][j] = model.newBoolVar(""); + } + } + Variable[] y = new Variable[data.numBins]; + for (int j = 0; j < data.numBins; ++j) { + y[j] = model.newBoolVar(""); + } + // [END variables] + + // [START constraints] + for (int i = 0; i < data.numItems; ++i) { + LinearExprBuilder oneCopy = LinearExpr.newBuilder(); + for (int j = 0; j < data.numBins; ++j) { + oneCopy.add(x[i][j]); + } + model.addEquality(oneCopy, 1); + } + + // The bin capacity contraint for bin j is + // sum_i w_i x_ij <= C*y_j + // To define this constraint, first subtract the left side from the right to get + // 0 <= C*y_j - sum_i w_i x_ij + // + // Note: Since sum_i w_i x_ij is positive (and y_j is 0 or 1), the right side must + // be less than or equal to C. But it's not necessary to add this constraint + // because it is forced by the other constraints. + for (int j = 0; j < data.numBins; ++j) { + LinearExprBuilder load = LinearExpr.newBuilder(); + for (int i = 0; i < data.numItems; ++i) { + load.addTerm(x[i][j], data.weights[i]); + } + model.addGreaterOrEqual(LinearExpr.term(y[j], data.binCapacity), load); + } + // [END constraints] + + // [START objective] + model.minimize(LinearExpr.sum(y)); + // [END objective] + + // [START solver] + // Create the solver with the SCIP backend and check it is supported. + ModelSolver solver = new ModelSolver("scip"); + if (!solver.solverIsSupported()) return; + // [END solver] + + // [START solve] + final SolveStatus resultStatus = solver.solve(model); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (resultStatus == SolveStatus.OPTIMAL) { + System.out.println("Number of bins used: " + solver.getObjectiveValue()); + double totalWeight = 0; + for (int j = 0; j < data.numBins; ++j) { + if (solver.getValue(y[j]) == 1) { + System.out.println("\nBin " + j + "\n"); + double binWeight = 0; + for (int i = 0; i < data.numItems; ++i) { + if (solver.getValue(x[i][j]) == 1) { + System.out.println("Item " + i + " - weight: " + data.weights[i]); + binWeight += data.weights[i]; + } + } + System.out.println("Packed bin weight: " + binWeight); + totalWeight += binWeight; + } + } + System.out.println("\nTotal packed weight: " + totalWeight); + } else { + System.err.println("The problem does not have an optimal solution."); + } + // [END print_solution] + } + + private BinPackingMb() {} +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/CloneModelMb.cs b/ortools/linear_solver/samples/CloneModelMb.cs index b4f865cc68..7e68d9a57d 100644 --- a/ortools/linear_solver/samples/CloneModelMb.cs +++ b/ortools/linear_solver/samples/CloneModelMb.cs @@ -66,12 +66,9 @@ public class SimpleMipProgramMb // [END clone] // [START solver] - // Create the model solver with the GLOP backend. + // Create the solver with the SCIP backend and checks it is supported. ModelSolver solver = new ModelSolver("SCIP"); - if (!solver.SolverIsSupported()) - { - return; - } + if (!solver.SolverIsSupported()) return; // [END solver] // [START solve] diff --git a/ortools/linear_solver/samples/CloneModelMb.java b/ortools/linear_solver/samples/CloneModelMb.java index 295875714c..c351cb1de8 100644 --- a/ortools/linear_solver/samples/CloneModelMb.java +++ b/ortools/linear_solver/samples/CloneModelMb.java @@ -74,9 +74,13 @@ public final class CloneModelMb { System.out.println("Number of constraints in the cloned model = " + modelCopy.numConstraints()); // [END clone] - // [START solve] - // Solve with the SCIP MIP solver. + // [START solver] + // Create the solver with the SCIP backend and check it is supported. ModelSolver solver = new ModelSolver("scip"); + if (!solver.solverIsSupported()) return; + // [END solver] + + // [START solve] final SolveStatus status = solver.solve(modelCopy); // [END solve]