diff --git a/makefiles/Makefile.cpp.mk b/makefiles/Makefile.cpp.mk index e23558da48..4a7890e3cd 100644 --- a/makefiles/Makefile.cpp.mk +++ b/makefiles/Makefile.cpp.mk @@ -334,10 +334,13 @@ test_cc_graph_samples: \ .PHONY: test_cc_linear_solver_samples # Build and Run all C++ LP Samples (located in ortools/linear_solver/samples) test_cc_linear_solver_samples: \ - rcc_simple_lp_program \ - rcc_simple_mip_program \ + rcc_bin_packing_mip \ + rcc_integer_programming_example \ rcc_linear_programming_example \ - rcc_integer_programming_example + rcc_mip_var_array \ + rcc_multiple_knapsack_mip \ + rcc_simple_lp_program \ + rcc_simple_mip_program .PHONY: test_cc_constraint_solver_samples # Build and Run all C++ CP Samples (located in ortools/constraint_solver/samples) test_cc_constraint_solver_samples: \ diff --git a/makefiles/Makefile.dotnet.mk b/makefiles/Makefile.dotnet.mk index 6f1df7cbfc..f81ebde3c7 100644 --- a/makefiles/Makefile.dotnet.mk +++ b/makefiles/Makefile.dotnet.mk @@ -520,6 +520,10 @@ test_dotnet_graph_samples: ; .PHONY: test_dotnet_linear_solver_samples # Build and Run all .Net LP Samples (located in ortools/linear_solver/samples) test_dotnet_linear_solver_samples: + $(MAKE) run SOURCE=ortools/linear_solver/samples/BinPackingMip.cs + $(MAKE) run SOURCE=ortools/linear_solver/samples/LinearProgrammingExample.cs + $(MAKE) run SOURCE=ortools/linear_solver/samples/MipVarArray.cs + $(MAKE) run SOURCE=ortools/linear_solver/samples/MultipleKnapsackMip.cs $(MAKE) run SOURCE=ortools/linear_solver/samples/SimpleLpProgram.cs $(MAKE) run SOURCE=ortools/linear_solver/samples/SimpleMipProgram.cs diff --git a/makefiles/Makefile.java.mk b/makefiles/Makefile.java.mk index 536f5e387f..31aa4c9783 100644 --- a/makefiles/Makefile.java.mk +++ b/makefiles/Makefile.java.mk @@ -391,11 +391,46 @@ $(LIB_DIR)/%$J: $(CLASS_DIR)/% | $(LIB_DIR) -$(DEL) $(LIB_DIR)$S$*.jar "$(JAR_BIN)" cvf $(LIB_DIR)$S$*.jar -C $(CLASS_DIR)$S$* . -rjava_%: $(LIB_DIR)/%$J FORCE +rjava_%: $(TEST_DIR)/%.java $(LIB_DIR)/%$J FORCE "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ $* $(ARGS) +rjava_%: $(JAVA_EX_DIR)/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + $* $(ARGS) + +rjava_%: $(CONTRIB_EX_DIR)/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + $* $(ARGS) + +rjava_%: $(SRC_DIR)/ortools/algorithms/samples/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + com.google.ortools.algorithms.samples.$* $(ARGS) + +rjava_%: $(SRC_DIR)/ortools/constraint_solver/samples/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + com.google.ortools.constraintsolver.samples.$* $(ARGS) + +rjava_%: $(SRC_DIR)/ortools/graph/samples/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + com.google.ortools.graph.samples.$* $(ARGS) + +rjava_%: $(SRC_DIR)/ortools/linear_solver/samples/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + com.google.ortools.linearsolver.samples.$* $(ARGS) + +rjava_%: $(SRC_DIR)/ortools/sat/samples/%.java $(LIB_DIR)/%$J FORCE + "$(JAVA_BIN)" -Xss2048k $(JAVAFLAGS) \ + -cp $(LIB_DIR)$S$*$J$(CPSEP)$(LIB_DIR)$Scom.google.ortools.jar$(CPSEP)$(LIB_DIR)$Sprotobuf.jar \ + com.google.ortools.sat.samples.$* $(ARGS) + .PHONY: test_java_algorithms_samples # Build and Run all Java Algorithms Samples (located in ortools/algorithms/samples) test_java_algorithms_samples: \ rjava_Knapsack @@ -426,9 +461,12 @@ test_java_graph_samples: \ .PHONY: test_java_linear_solver_samples # Build and Run all Java LP Samples (located in ortools/linear_solver/samples) test_java_linear_solver_samples: \ + rjava_BinPackingMip \ + rjava_LinearProgrammingExample \ + rjava_MipVarArray \ + rjava_MultipleKnapsackMip \ rjava_SimpleLpProgram \ - rjava_SimpleMipProgram \ - rjava_LinearProgrammingExample + rjava_SimpleMipProgram .PHONY: test_java_sat_samples # Build and Run all Java SAT Samples (located in ortools/sat/samples) test_java_sat_samples: \ @@ -520,7 +558,6 @@ test_java_java: \ rjava_CapacitatedVehicleRoutingProblemWithTimeWindows \ rjava_FlowExample \ rjava_IntegerProgramming \ - rjava_Knapsack \ rjava_LinearAssignmentAPI \ rjava_LinearProgramming \ rjava_RabbitsPheasants \ diff --git a/makefiles/Makefile.python.mk b/makefiles/Makefile.python.mk index ec839e6bca..b2e3073bb1 100644 --- a/makefiles/Makefile.python.mk +++ b/makefiles/Makefile.python.mk @@ -591,10 +591,13 @@ test_python_graph_samples: \ .PHONY: test_python_linear_solver_samples # Run all Python LP Samples (located in ortools/linear_solver/samples) test_python_linear_solver_samples: \ - rpy_simple_lp_program \ - rpy_simple_mip_program \ + rpy_bin_packing_mip \ + rpy_integer_programming_example \ rpy_linear_programming_example \ - rpy_integer_programming_example + rpy_mip_var_array \ + rpy_multiple_knapsack_mip \ + rpy_simple_lp_program \ + rpy_simple_mip_program .PHONY: test_python_sat_samples # Run all Python Sat Samples (located in ortools/sat/samples) test_python_sat_samples: \ diff --git a/ortools/algorithms/samples/Knapsack.java b/ortools/algorithms/samples/Knapsack.java index ed739be465..15524c756e 100644 --- a/ortools/algorithms/samples/Knapsack.java +++ b/ortools/algorithms/samples/Knapsack.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.algorithms.samples; // [START import] import com.google.ortools.algorithms.KnapsackSolver; import java.util.ArrayList; @@ -25,6 +26,7 @@ public class Knapsack { static { System.loadLibrary("jniortools"); } + private Knapsack() {} private static void solve() { // [START solver] @@ -50,8 +52,8 @@ public class Knapsack { // [END solve] // [START print_solution] - ArrayList packedItems = new ArrayList(); - ArrayList packedWeights = new ArrayList(); + ArrayList packedItems = new ArrayList<>(); + ArrayList packedWeights = new ArrayList<>(); int totalWeight = 0; System.out.println("Total value = " + computedValue); for (int i = 0; i < values.length; i++) { diff --git a/ortools/constraint_solver/samples/SimpleCpProgram.java b/ortools/constraint_solver/samples/SimpleCpProgram.java index e026348110..3c1b2c95bf 100644 --- a/ortools/constraint_solver/samples/SimpleCpProgram.java +++ b/ortools/constraint_solver/samples/SimpleCpProgram.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.DecisionBuilder; import com.google.ortools.constraintsolver.IntVar; @@ -24,6 +25,7 @@ public class SimpleCpProgram { static { System.loadLibrary("jniortools"); } + private SimpleCpProgram() {} private static final Logger logger = Logger.getLogger(SimpleCpProgram.class.getName()); diff --git a/ortools/constraint_solver/samples/SimpleRoutingProgram.java b/ortools/constraint_solver/samples/SimpleRoutingProgram.java index aaf0b76fbb..2f6581b558 100644 --- a/ortools/constraint_solver/samples/SimpleRoutingProgram.java +++ b/ortools/constraint_solver/samples/SimpleRoutingProgram.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import static java.lang.Math.abs; diff --git a/ortools/constraint_solver/samples/Tsp.java b/ortools/constraint_solver/samples/Tsp.java index 91e5d24abf..c2ba211185 100644 --- a/ortools/constraint_solver/samples/Tsp.java +++ b/ortools/constraint_solver/samples/Tsp.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import static java.lang.Math.abs; diff --git a/ortools/constraint_solver/samples/TspCircuitBoard.java b/ortools/constraint_solver/samples/TspCircuitBoard.java index 5cd3a0461e..e9371a2106 100644 --- a/ortools/constraint_solver/samples/TspCircuitBoard.java +++ b/ortools/constraint_solver/samples/TspCircuitBoard.java @@ -12,8 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] - import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; import com.google.ortools.constraintsolver.RoutingIndexManager; diff --git a/ortools/constraint_solver/samples/TspCities.java b/ortools/constraint_solver/samples/TspCities.java index 5fd0740ea5..02c4f2631f 100644 --- a/ortools/constraint_solver/samples/TspCities.java +++ b/ortools/constraint_solver/samples/TspCities.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/TspDistanceMatrix.java b/ortools/constraint_solver/samples/TspDistanceMatrix.java index ce66d65b8f..eb18936e28 100644 --- a/ortools/constraint_solver/samples/TspDistanceMatrix.java +++ b/ortools/constraint_solver/samples/TspDistanceMatrix.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/Vrp.java b/ortools/constraint_solver/samples/Vrp.java index d6dd9cbc1c..789a7e08a8 100644 --- a/ortools/constraint_solver/samples/Vrp.java +++ b/ortools/constraint_solver/samples/Vrp.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpCapacity.java b/ortools/constraint_solver/samples/VrpCapacity.java index a5f9f93afc..587875bd30 100644 --- a/ortools/constraint_solver/samples/VrpCapacity.java +++ b/ortools/constraint_solver/samples/VrpCapacity.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpDropNodes.java b/ortools/constraint_solver/samples/VrpDropNodes.java index e61959f001..4b8eb17cb3 100644 --- a/ortools/constraint_solver/samples/VrpDropNodes.java +++ b/ortools/constraint_solver/samples/VrpDropNodes.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpGlobalSpan.java b/ortools/constraint_solver/samples/VrpGlobalSpan.java index 19b0a698b2..b8cfeb1a9f 100644 --- a/ortools/constraint_solver/samples/VrpGlobalSpan.java +++ b/ortools/constraint_solver/samples/VrpGlobalSpan.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpInitialRoutes.java b/ortools/constraint_solver/samples/VrpInitialRoutes.java index de17853edd..caa274c459 100644 --- a/ortools/constraint_solver/samples/VrpInitialRoutes.java +++ b/ortools/constraint_solver/samples/VrpInitialRoutes.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.RoutingDimension; diff --git a/ortools/constraint_solver/samples/VrpPickupDelivery.java b/ortools/constraint_solver/samples/VrpPickupDelivery.java index 615959e765..b7c878e654 100644 --- a/ortools/constraint_solver/samples/VrpPickupDelivery.java +++ b/ortools/constraint_solver/samples/VrpPickupDelivery.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpPickupDeliveryFifo.java b/ortools/constraint_solver/samples/VrpPickupDeliveryFifo.java index 043aab8780..91140437e2 100644 --- a/ortools/constraint_solver/samples/VrpPickupDeliveryFifo.java +++ b/ortools/constraint_solver/samples/VrpPickupDeliveryFifo.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpPickupDeliveryLifo.java b/ortools/constraint_solver/samples/VrpPickupDeliveryLifo.java index 7d30d6b1d5..68c71af31b 100644 --- a/ortools/constraint_solver/samples/VrpPickupDeliveryLifo.java +++ b/ortools/constraint_solver/samples/VrpPickupDeliveryLifo.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpResources.java b/ortools/constraint_solver/samples/VrpResources.java index 63ee57b1fe..15b0570cec 100644 --- a/ortools/constraint_solver/samples/VrpResources.java +++ b/ortools/constraint_solver/samples/VrpResources.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpStartsEnds.java b/ortools/constraint_solver/samples/VrpStartsEnds.java index 11c9bd02cb..f204436943 100644 --- a/ortools/constraint_solver/samples/VrpStartsEnds.java +++ b/ortools/constraint_solver/samples/VrpStartsEnds.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpTimeWindows.java b/ortools/constraint_solver/samples/VrpTimeWindows.java index e91ca9985c..27188bd38c 100644 --- a/ortools/constraint_solver/samples/VrpTimeWindows.java +++ b/ortools/constraint_solver/samples/VrpTimeWindows.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/constraint_solver/samples/VrpWithTimeLimit.java b/ortools/constraint_solver/samples/VrpWithTimeLimit.java index 57416f0882..d8b0dd5e45 100644 --- a/ortools/constraint_solver/samples/VrpWithTimeLimit.java +++ b/ortools/constraint_solver/samples/VrpWithTimeLimit.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.constraintsolver.samples; // [START import] import com.google.ortools.constraintsolver.Assignment; import com.google.ortools.constraintsolver.FirstSolutionStrategy; diff --git a/ortools/linear_solver/samples/BinPackingMip.cs b/ortools/linear_solver/samples/BinPackingMip.cs new file mode 100644 index 0000000000..bc5095b421 --- /dev/null +++ b/ortools/linear_solver/samples/BinPackingMip.cs @@ -0,0 +1,136 @@ +// Copyright 2010-2018 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] +// [START import] +using System; +using Google.OrTools.LinearSolver; +// [END import] + +// [START program_part1] +public class BinPackingMip +{ + // [START data_model] + class DataModel + { + public double[] Weights = {48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30}; + public double[] BinCapacity = 100; + public int NumItems = Weights.Length; + public int NumBins = Weights.Length; + } + // [END data_model] + public static void Main() + { + // [START data] + DataModel data = new DataModel(); + // [END data] + // [END program_part1] + + // [START solver] + // Create the linear solver with the CBC backend. + Solver solver = Solver.CreateSolver("BinPackingMip", "CBC_MIXED_INTEGER_PROGRAMMING"); + // [END solver] + + // [START program_part2] + // [START variables] + MPVariable[,] x = new MPVariable[data.NumItems][data.NumBins]; + for (int i = 0; i < data.NumItems; i++) + { + for (int j = 0; j < data.NumBins; j++) + { + x[i][j] = MakeIntVar(0, 1, String.Format("x_{0}_{1}", i, j)); + } + } + MPVariable[] y = new MPVariable[data.NumBins]; + for (int j = 0; j < data.NumBins; j++) + { + y[j] = MakeIntVar(0, 1, String.Format("y_{0}", j)); + } + // [END variables] + + // [START constraints] + for (int i = 0; i < data.NumItems; ++i) { + LinearExpr sum; + for (int j = 0; j < data.NumBins; ++j) { + sum += x[i][j]; + } + } + solver.MakeRowConstraint(sum == 1.0); + for (int i = 0; i < data.NumConstraints; ++i) + { + MPConstraint constraint = solver.MakeConstraint(0, data.Bounds[i], ""); + for (int j = 0; j < data.NumVars; ++j) + { + constraint.SetCoefficient(x[j], data.ConstraintCoeffs[i][j]); + } + } + for (int j = 0; j < data.NumBins; ++j) + { + LinearExpr Weight; + for (int i = 0; i < data.NumItems; ++i) + { + Weight += data.Weights[i]*LinearExpr(x[i][j]); + } + solver.MakeRowConstraint(Weight <= data.BinCapacities[j]); + } + // [END constraints] + + // [START objective] + objective = solver.Objective(); + LinearExpr NumBinsUsed; + for (int j = 0; j < data.NumBins; ++j) + { + NumBinsUsed += y[j]; + } + } + objective.MinimizeLinearExpr(NumBinsUsed); + // [END objective] + + // [START solve] + Solver.ResultStatus resultStatus = solver.Solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (resultStatus != Solver.ResultStatus.OPTIMAL) + { + Console.WriteLine("The problem does not have an optimal solution!"); + return; + } + Console.WriteLine("Number of bins used: " + solver.Objective().Value()); + int TotalWeight = 0; + for (int j = 0; j < data.NumBins; ++j) + { + int BinWeight = 0; + if (y[j] == 1) + { + Console.WriteLine("Bin " + j); + for (int i = 0; i < data.NumItems; ++i) + { + if (x[i][j].SolutionValue() == 1) + { + Console.WriteLine("Item " + i + " weight: " + data.Weights[i] + + " values: " + data.Values[i]; + BinWeight += data.Weights[i]; + } + } + Console.WriteLine("Packed bin weight: " + BinWeight); + TotalWeight += BinWeight; + } + Console.WriteLine("Total packed weight: " + TotalWeight); + // [END print_solution] + } + } +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/BinPackingMip.csproj b/ortools/linear_solver/samples/BinPackingMip.csproj new file mode 100644 index 0000000000..88d43461d5 --- /dev/null +++ b/ortools/linear_solver/samples/BinPackingMip.csproj @@ -0,0 +1,24 @@ + + + Exe + 7.3 + netcoreapp2.1 + false + + LatestMajor + ../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json + Google.OrTools.BinPackingMip + true + + + + full + true + true + + + + + + + diff --git a/ortools/linear_solver/samples/BinPackingMip.java b/ortools/linear_solver/samples/BinPackingMip.java new file mode 100644 index 0000000000..8ef4318da7 --- /dev/null +++ b/ortools/linear_solver/samples/BinPackingMip.java @@ -0,0 +1,132 @@ +// Copyright 2010-2018 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.linearsolver.MPConstraint; +import com.google.ortools.linearsolver.MPObjective; +import com.google.ortools.linearsolver.MPSolver; +import com.google.ortools.linearsolver.MPVariable; +// [END import] + +/** Bin packing problem. */ +public class BinPackingMip { + static { + System.loadLibrary("jniortools"); + } + + // [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 { + // [START data] + final DataModel data = new DataModel(); + // [END data] + // [END program_part1] + + // [START solver] + // Create the linear solver with the CBC backend. + MPSolver solver = new MPSolver( + "BinPackingMip", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + // [END solver] + + // [START program_part2] + // [START variables] + MPVariable[][] x = new MPVariable[data.numItems][data.numBins]; + for (int i = 0; i < data.numItems; ++i) { + for (int j = 0; j < data.numBins; ++j) { + x[i][j] = solver.makeIntVar(0, 1, ""); + } + } + MPVariable[] y = new MPVariable[data.numBins]; + for (int j = 0; j < data.numBins; ++j) { + y[j] = solver.makeIntVar(0, 1, ""); + } + // [END variables] + + // [START constraints] + double infinity = java.lang.Double.POSITIVE_INFINITY; + for (int i = 0; i < data.numItems; ++i) { + MPConstraint constraint = solver.makeConstraint(1, 1, ""); + for (int j = 0; j < data.numBins; ++j) { + constraint.setCoefficient(x[i][j], 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) { + MPConstraint constraint = solver.makeConstraint(0, infinity, ""); + constraint.setCoefficient(y[j], data.binCapacity); + for (int i = 0; i < data.numItems; ++i) { + constraint.setCoefficient(x[i][j], -data.weights[i]); + } + } + // [END constraints] + + // [START objective] + MPObjective objective = solver.objective(); + for (int j = 0; j < data.numBins; ++j) { + objective.setCoefficient(y[j], 1); + } + objective.setMinimization(); + // [END objective] + + // [START solve] + final MPSolver.ResultStatus resultStatus = solver.solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (resultStatus == MPSolver.ResultStatus.OPTIMAL) { + System.out.println("Number of bins used: " + objective.value()); + double totalWeight = 0; + for (int j = 0; j < data.numBins; ++j) { + if (y[j].solutionValue() == 1) { + System.out.println("\nBin " + j + "\n"); + double binWeight = 0; + for (int i = 0; i < data.numItems; ++i) { + if (x[i][j].solutionValue() == 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 BinPackingMip() {} +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/LinearProgrammingExample.java b/ortools/linear_solver/samples/LinearProgrammingExample.java index 1f3d4b6289..8ccee728a7 100644 --- a/ortools/linear_solver/samples/LinearProgrammingExample.java +++ b/ortools/linear_solver/samples/LinearProgrammingExample.java @@ -12,6 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.linearsolver.samples; + import com.google.ortools.linearsolver.MPConstraint; import com.google.ortools.linearsolver.MPObjective; import com.google.ortools.linearsolver.MPSolver; diff --git a/ortools/linear_solver/samples/MipVarArray.java b/ortools/linear_solver/samples/MipVarArray.java new file mode 100644 index 0000000000..8e5ee11d00 --- /dev/null +++ b/ortools/linear_solver/samples/MipVarArray.java @@ -0,0 +1,110 @@ +// Copyright 2010-2018 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 uses a variable array. +// [START program] +package com.google.ortools.linearsolver.samples; +// [START import] +import com.google.ortools.linearsolver.MPConstraint; +import com.google.ortools.linearsolver.MPObjective; +import com.google.ortools.linearsolver.MPSolver; +import com.google.ortools.linearsolver.MPVariable; +// [END import] + +// [START program_part1] +/** MIP example with a variable array. */ +public class MipVarArray { + static { + System.loadLibrary("jniortools"); + } + // [START data_model] + static class DataModel { + public final double[][] constraintCoeffs = { + {5, 7, 9, 2, 1}, + {18, 4, -9, 10, 12}, + {4, 7, 3, 8, 5}, + {5, 13, 16, 3, -7}, + }; + public final double[] bounds = {250, 285, 211, 315}; + public final double[] objCoeffs = {7, 8, 2, 9, 6}; + public final int numVars = 5; + public final int numConstraints = 4; + } + // [END data_model] + + public static void main(String[] args) throws Exception { + // [START data] + final DataModel data = new DataModel(); + // [END data] + // [END program_part1] + + // [START solver] + // Create the linear solver with the CBC backend. + MPSolver solver = new MPSolver( + "SimpleMipProgram", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + // [END solver] + + // [START program_part2] + // [START variables] + double infinity = java.lang.Double.POSITIVE_INFINITY; + MPVariable[] x = new MPVariable[data.numVars]; + for (int j = 0; j < data.numVars; ++j) { + x[j] = solver.makeIntVar(0.0, infinity, ""); + } + System.out.println("Number of variables = " + solver.numVariables()); + // [END variables] + + // [START constraints] + // Create the constraints. + for (int i = 0; i < data.numConstraints; ++i) { + MPConstraint constraint = solver.makeConstraint(0, data.bounds[i], ""); + for (int j = 0; j < data.numVars; ++j) { + constraint.setCoefficient(x[j], data.constraintCoeffs[i][j]); + } + } + System.out.println("Number of constraints = " + solver.numConstraints()); + // [END constraints] + + // [START objective] + MPObjective objective = solver.objective(); + for (int j = 0; j < data.numVars; ++j) { + objective.setCoefficient(x[j], data.objCoeffs[j]); + } + objective.setMaximization(); + // [END objective] + + // [START solve] + final MPSolver.ResultStatus resultStatus = solver.solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (resultStatus == MPSolver.ResultStatus.OPTIMAL) { + System.out.println("Objective value = " + objective.value()); + for (int j = 0; j < data.numVars; ++j) { + System.out.println("x[" + j + "] = " + x[j].solutionValue()); + } + System.out.println(); + System.out.println("Problem solved in " + solver.wallTime() + " milliseconds"); + System.out.println("Problem solved in " + solver.iterations() + " iterations"); + System.out.println("Problem solved in " + solver.nodes() + " branch-and-bound nodes"); + } else { + System.err.println("The problem does not have an optimal solution."); + } + // [END print_solution] + } + + private MipVarArray() {} +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/MultipleKnapsackMip.cs b/ortools/linear_solver/samples/MultipleKnapsackMip.cs new file mode 100644 index 0000000000..0a332406d0 --- /dev/null +++ b/ortools/linear_solver/samples/MultipleKnapsackMip.cs @@ -0,0 +1,137 @@ +// Copyright 2010-2018 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] +// [START import] +using System; +using Google.OrTools.LinearSolver; +// [END import] + +// [START program_part1] +public class MultipleKnapsackMip +{ + // [START data_model] + class DataModel + { + public double[] Weights = + {48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36}; + public double[] Values = + {10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25}; + public double[] BinCapacities = {100, 100, 100, 100, 100}; + public int NumItems = Weights.Length; + public int NumBins = 5; + } + // [END data_model] + public static void Main() + { + // [START data] + DataModel data = new DataModel(); + // [END data] + // [END program_part1] + + // [START solver] + // Create the linear solver with the CBC backend. + Solver solver = Solver.CreateSolver("MultipleKnapsackMip", "CBC_MIXED_INTEGER_PROGRAMMING"); + // [END solver] + + // [START program_part2] + // [START variables] + MPVariable[,] x = new MPVariable[data.NumItems][data.NumBins]; + for (int i = 0; i < data.NumItems; i++) + { + for (int j = 0; j < data.NumBins; j++) + { + x[i][j] = MakeIntVar(0, 1, String.Format("x_{0}_{1}", i, j)); + } + } + // [END variables] + + // [START constraints] + for (int i = 0; i < data.NumItems; ++i) { + LinearExpr sum; + for (int j = 0; j < data.NumBins; ++j) { + sum += x[i][j]; + } + solver.MakeRowConstraint(sum <= 1.0); + } + + for (int i = 0; i < data.NumConstraints; ++i) + { + MPConstraint constraint = solver.MakeConstraint(0, data.Bounds[i], ""); + for (int j = 0; j < data.NumVars; ++j) + { + constraint.SetCoefficient(x[j], data.ConstraintCoeffs[i][j]); + } + } + for (int j = 0; j < data.NumBins; ++j) + { + LinearExpr Weight; + for (int i = 0; i < data.NumItems; ++i) + { + Weight += data.Weights[i]*LinearExpr(x[i][j]); + } + solver.MakeRowConstraint(Weight <= data.BinCapacities[j]); + } + // [END constraints] + + // [START objective] + objective = solver.Objective(); + LinearExpr Value; + for (int i = 0; i < data.NumItems; ++i) + { + for (int j = 0; j < data.NumBins; ++j) + { + Value += data.Values[i] * LinearExpr(x[i][j]); + } + } + objective.MaximizeLinearExpr(Value); + // [END objective] + + // [START solve] + Solver.ResultStatus resultStatus = solver.Solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (resultStatus != Solver.ResultStatus.OPTIMAL) + { + Console.WriteLine("The problem does not have an optimal solution!"); + return; + } + Console.WriteLine("Total packed value: " + solver.Objective().Value()); + int TotalWeight = 0; + for (int j = 0; j < data.NumBins; ++j) + { + int BinWeight = 0; + int BinValue = 0; + Console.WriteLine("Bin " + j); + for (int i = 0; i < data.NumItems; ++i) + { + if (x[i][j].SolutionValue() == 1) + { + Console.WriteLine("Item " + i + " weight: " + data.Weights[i] + + " values: " + data.Values[i]; + BinWeight += data.Weights[i]; + BinValue += data.Values[i] + } + } + Console.WriteLine("Packed bin weight: " + BinWeight); + Console.WriteLine("Packed bin value: " + BinValue); + TotalWeight += BinWeight; + } + Console.WriteLine("Total packed weight: " + TotalWeight); + // [END print_solution] + } +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/MultipleKnapsackMip.csproj b/ortools/linear_solver/samples/MultipleKnapsackMip.csproj new file mode 100644 index 0000000000..4a01b6f665 --- /dev/null +++ b/ortools/linear_solver/samples/MultipleKnapsackMip.csproj @@ -0,0 +1,24 @@ + + + Exe + 7.3 + netcoreapp2.1 + false + + LatestMajor + ../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json + Google.OrTools.MultipleKnapsackMip + true + + + + full + true + true + + + + + + + diff --git a/ortools/linear_solver/samples/MultipleKnapsackMip.java b/ortools/linear_solver/samples/MultipleKnapsackMip.java new file mode 100644 index 0000000000..95234a5e52 --- /dev/null +++ b/ortools/linear_solver/samples/MultipleKnapsackMip.java @@ -0,0 +1,123 @@ +// Copyright 2010-2018 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 multiple knapsack problem. +// [START program] +package com.google.ortools.linearsolver.samples; +// [START import] +import com.google.ortools.linearsolver.MPConstraint; +import com.google.ortools.linearsolver.MPObjective; +import com.google.ortools.linearsolver.MPSolver; +import com.google.ortools.linearsolver.MPVariable; +// [END import] + +/** Multiple knapsack problem. */ +public class MultipleKnapsackMip { + static { + System.loadLibrary("jniortools"); + } + + // [START program_part1] + // [START data_model] + static class DataModel { + public final double[] weights = {48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36}; + public final double[] values = {10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25}; + public final int numItems = weights.length; + public final int numBins = 5; + public final double[] binCapacities = {100, 100, 100, 100, 100}; + } + // [END data_model] + + public static void main(String[] args) throws Exception { + // [START data] + final DataModel data = new DataModel(); + // [END data] + // [END program_part1] + + // [START solver] + // Create the linear solver with the CBC backend. + MPSolver solver = new MPSolver( + "MultipleKnapsackMip", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + // [END solver] + + // [START program_part2] + // [START variables] + MPVariable[][] x = new MPVariable[data.numItems][data.numBins]; + for (int i = 0; i < data.numItems; ++i) { + for (int j = 0; j < data.numBins; ++j) { + x[i][j] = solver.makeIntVar(0, 1, ""); + } + } + // [END variables] + + // [START constraints] + for (int i = 0; i < data.numItems; ++i) { + MPConstraint constraint = solver.makeConstraint(0, 1, ""); + for (int j = 0; j < data.numBins; ++j) { + constraint.setCoefficient(x[i][j], 1); + } + } + for (int j = 0; j < data.numBins; ++j) { + MPConstraint constraint = solver.makeConstraint(0, data.binCapacities[j], ""); + for (int i = 0; i < data.numItems; ++i) { + constraint.setCoefficient(x[i][j], data.weights[i]); + } + } + // [END constraints] + + // [START objective] + MPObjective objective = solver.objective(); + for (int i = 0; i < data.numItems; ++i) { + for (int j = 0; j < data.numBins; ++j) { + objective.setCoefficient(x[i][j], data.values[i]); + } + } + objective.setMaximization(); + // [END objective] + + // [START solve] + final MPSolver.ResultStatus resultStatus = solver.solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (resultStatus == MPSolver.ResultStatus.OPTIMAL) { + System.out.println("Total packed value: " + objective.value() + "\n"); + double totalWeight = 0; + for (int j = 0; j < data.numBins; ++j) { + double binWeight = 0; + double binValue = 0; + System.out.println("Bin " + j + "\n"); + for (int i = 0; i < data.numItems; ++i) { + if (x[i][j].solutionValue() == 1) { + System.out.println( + "Item " + i + " - weight: " + data.weights[i] + " value: " + data.values[i]); + binWeight += data.weights[i]; + binValue += data.values[i]; + } + } + System.out.println("Packed bin weight: " + binWeight); + System.out.println("Packed bin value: " + binValue + "\n"); + totalWeight += binWeight; + } + System.out.println("Total packed weight: " + totalWeight); + } else { + System.err.println("The problem does not have an optimal solution."); + } + // [END print_solution] + } + + private MultipleKnapsackMip() {} +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/SimpleLpProgram.java b/ortools/linear_solver/samples/SimpleLpProgram.java index ba80f884a6..b0f75f110a 100644 --- a/ortools/linear_solver/samples/SimpleLpProgram.java +++ b/ortools/linear_solver/samples/SimpleLpProgram.java @@ -13,6 +13,7 @@ // Minimal example to call the GLOP solver. // [START program] +package com.google.ortools.linearsolver.samples; // [START import] import com.google.ortools.linearsolver.MPConstraint; import com.google.ortools.linearsolver.MPObjective; diff --git a/ortools/linear_solver/samples/SimpleMipProgram.java b/ortools/linear_solver/samples/SimpleMipProgram.java index 955295d068..767a4a168d 100644 --- a/ortools/linear_solver/samples/SimpleMipProgram.java +++ b/ortools/linear_solver/samples/SimpleMipProgram.java @@ -13,6 +13,7 @@ // Minimal example to call the MIP solver. // [START program] +package com.google.ortools.linearsolver.samples; // [START import] import com.google.ortools.linearsolver.MPConstraint; import com.google.ortools.linearsolver.MPObjective; diff --git a/ortools/linear_solver/samples/bin_packing_mip.cc b/ortools/linear_solver/samples/bin_packing_mip.cc new file mode 100644 index 0000000000..241015a7ee --- /dev/null +++ b/ortools/linear_solver/samples/bin_packing_mip.cc @@ -0,0 +1,134 @@ +// Copyright 2010-2018 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] +// [START import] +#include +#include +#include + +#include "ortools/linear_solver/linear_expr.h" +#include "ortools/linear_solver/linear_solver.h" +// [END import] + +// [START program_part1] +namespace operations_research { +// [START data_model] +struct DataModel { + const std::vector weights = {48, 30, 19, 36, 36, 27, + 42, 42, 36, 24, 30}; + const int num_items = weights.size(); + const int num_bins = weights.size(); + const int bin_capacity = 100; +}; +// [END data_model] + +void BinPackingMip() { + // [START data] + DataModel data; + // [END data] + // [END program_part1] + + // [START solver] + // Create the mip solver with the CBC backend. + MPSolver solver("bin_packing_mip", + MPSolver::CBC_MIXED_INTEGER_PROGRAMMING); + // [END solver] + + // [START program_part2] + // [START variables] + std::vector> x( + data.num_items, std::vector(data.num_bins)); + for (int i = 0; i < data.num_items; ++i) { + for (int j = 0; j < data.num_bins; ++j) { + x[i][j] = solver.MakeIntVar(0.0, 1.0, ""); + } + } + // y[j] = 1 if bin j is used. + std::vector y(data.num_bins); + for (int j = 0; j < data.num_bins; ++j) { + y[j] = solver.MakeIntVar(0.0, 1.0, ""); + } + // [END variables] + + // [START constraints] + // Create the constraints. + // Each item is in exactly one bin. + for (int i = 0; i < data.num_items; ++i) { + LinearExpr sum; + for (int j = 0; j < data.num_bins; ++j) { + sum += x[i][j]; + } + solver.MakeRowConstraint(sum == 1.0); + } + // For each bin that is used, the total packed weight can be at most + // the bin capacity. + for (int j = 0; j < data.num_bins; ++j) { + LinearExpr weight; + for (int i = 0; i < data.num_items; ++i) { + weight += data.weights[i] * LinearExpr(x[i][j]); + } + solver.MakeRowConstraint(weight <= LinearExpr(y[j]) * data.bin_capacity); + } + // [END constraints] + + // [START objective] + // Create the objective function. + MPObjective* const objective = solver.MutableObjective(); + LinearExpr num_bins_used; + for (int j = 0; j < data.num_bins; ++j) { + num_bins_used += y[j]; + } + objective->MinimizeLinearExpr(num_bins_used); + // [END objective] + + // [START solve] + const MPSolver::ResultStatus result_status = solver.Solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (result_status != MPSolver::OPTIMAL) { + std::cerr << "The problem does not have an optimal solution!"; + return; + } + std::cout << "Number of bins used: " << objective->Value() << std::endl + << std::endl; + double total_weight = 0; + for (int j = 0; j < data.num_bins; ++j) { + if (y[j]->solution_value() == 1) { + std::cout << "Bin " << j << std::endl << std::endl; + double bin_weight = 0; + for (int i = 0; i < data.num_items; ++i) { + if (x[i][j]->solution_value() == 1) { + std::cout << "Item " << i << " - Weight: " << data.weights[i] + << std::endl; + bin_weight += data.weights[i]; + } + } + std::cout << "Packed bin weight: " << bin_weight << std::endl + << std::endl; + total_weight += bin_weight; + } + } + std::cout << "Total packed weight: " << total_weight << std::endl; + // [END print_solution] +} +} // namespace operations_research + +int main(int argc, char** argv) { + operations_research::BinPackingMip(); + return EXIT_SUCCESS; +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/bin_packing_mip.py b/ortools/linear_solver/samples/bin_packing_mip.py new file mode 100644 index 0000000000..abf3575f52 --- /dev/null +++ b/ortools/linear_solver/samples/bin_packing_mip.py @@ -0,0 +1,115 @@ +# Copyright 2010-2018 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. +"""Solve a simple bin packing problem using a MIP solver.""" +# [START program] +# [START import] +from __future__ import print_function +from ortools.linear_solver import pywraplp + +# [END import] + + +# [START program_part1] +# [START data_model] +def create_data_model(): + """Create the data for the example.""" + data = {} + weights = [48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30] + data['weights'] = weights + data['items'] = list(range(len(weights))) + data['bins'] = data['items'] + data['bin_capacity'] = 100 + return data + + +# [END data_model] + + +def main(): + # [START data] + data = create_data_model() + # [END data] + # [END program_part1] + + # [START solver] + # Create the mip solver with the CBC backend. + solver = pywraplp.Solver('bin_packing_mip', + pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + # [END solver] + + # [START program_part2] + # [START variables] + # Variables + # x[i, j] = 1 if item i is packed in bin j. + x = {} + for i in data['items']: + for j in data['bins']: + x[(i, j)] = solver.IntVar(0, 1, 'x_%i_%i' % (i, j)) + + # y[j] = 1 if bin j is used. + y = {} + for j in data['bins']: + y[j] = solver.IntVar(0, 1, 'y[%i]' % j) + # [END variables] + + # [START constraints] + # Constraints + # Each item must be in exactly one bin. + for i in data['items']: + solver.Add(sum(x[i, j] for j in data['bins']) == 1) + + # The amount packed in each bin cannot exceed its capacity. + for j in data['bins']: + solver.Add( + sum(x[(i, j)] * data['weights'][i] for i in data['items']) <= y[j] * + data['bin_capacity']) + # [END constraints] + + # [START objective] + # Objective: minimize the number of bins used. + solver.Minimize(solver.Sum([y[j] for j in data['bins']])) + # [END objective] + + # [START solve] + status = solver.Solve() + # [END solve] + + # [START print_solution] + if status == pywraplp.Solver.OPTIMAL: + num_bins = 0. + for j in data['bins']: + if y[j].solution_value() == 1: + bin_items = [] + bin_weight = 0 + for i in data['items']: + if x[i, j].solution_value() > 0: + bin_items.append(i) + bin_weight += data['weights'][i] + if bin_weight > 0: + num_bins += 1 + print('Bin number', j) + print(' Items packed:', bin_items) + print(' Total weight:', bin_weight) + print() + print() + print('Number of bins used:', num_bins) + print('Time = ', solver.WallTime(), ' milliseconds') + else: + print('The problem does not have an optimal solution.') + # [END print_solution] + + +if __name__ == '__main__': + main() +# [END program_part2] +# [END program] diff --git a/ortools/linear_solver/samples/multiple_knapsack_mip.cc b/ortools/linear_solver/samples/multiple_knapsack_mip.cc new file mode 100644 index 0000000000..70e288ee74 --- /dev/null +++ b/ortools/linear_solver/samples/multiple_knapsack_mip.cc @@ -0,0 +1,132 @@ +// Copyright 2010-2018 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] +// [START import] +#include +#include +#include + +#include "ortools/linear_solver/linear_expr.h" +#include "ortools/linear_solver/linear_solver.h" +// [END import] + +// [START program_part1] +namespace operations_research { +// [START data_model] +struct DataModel { + const std::vector weights = {48, 30, 42, 36, 36, 48, 42, 42, + 36, 24, 30, 30, 42, 36, 36}; + const std::vector values = {10, 30, 25, 50, 35, 30, 15, 40, + 30, 35, 45, 10, 20, 30, 25}; + const int num_items = weights.size(); + const int total_value = std::accumulate(values.begin(), values.end(), 0); + const std::vector bin_capacities = {{100, 100, 100, 100, 100}}; + const int num_bins = 5; +}; +// [END data_model] + +void MultipleKnapsackMip() { + // [START data] + DataModel data; + // [END data] + // [END program_part1] + + // [START solver] + // Create the mip solver with the CBC backend. + MPSolver solver("multiple_knapsack_mip", + MPSolver::CBC_MIXED_INTEGER_PROGRAMMING); + // [END solver] + + // [START program_part2] + // [START variables] + std::vector> x( + data.num_items, std::vector(data.num_bins)); + for (int i = 0; i < data.num_items; ++i) { + for (int j = 0; j < data.num_bins; ++j) { + x[i][j] = solver.MakeIntVar(0.0, 1.0, ""); + } + } + // [END variables] + + // [START constraints] + // Create the constraints. + // Each item is in at most one bin. + for (int i = 0; i < data.num_items; ++i) { + LinearExpr sum; + for (int j = 0; j < data.num_bins; ++j) { + sum += x[i][j]; + } + solver.MakeRowConstraint(sum <= 1.0); + } + // For each bin that is used, the total packed weight can be at most + // the bin capacity. + for (int j = 0; j < data.num_bins; ++j) { + LinearExpr weight; + for (int i = 0; i < data.num_items; ++i) { + weight += data.weights[i] * LinearExpr(x[i][j]); + } + solver.MakeRowConstraint(weight <= data.bin_capacities[j]); + } + // [END constraints] + + // [START objective] + // Create the objective function. + MPObjective* const objective = solver.MutableObjective(); + LinearExpr value; + for (int i = 0; i < data.num_items; ++i) { + for (int j = 0; j < data.num_bins; ++j) { + value += data.values[i] * LinearExpr(x[i][j]); + } + } + objective->MaximizeLinearExpr(value); + // [END objective] + + // [START solve] + const MPSolver::ResultStatus result_status = solver.Solve(); + // [END solve] + + // [START print_solution] + // Check that the problem has an optimal solution. + if (result_status != MPSolver::OPTIMAL) { + std::cerr << "The problem does not have an optimal solution!"; + } + std::cout << "Total packed value: " << objective->Value() << "\n\n"; + double total_weight = 0; + for (int j = 0; j < data.num_bins; ++j) { + double bin_weight = 0; + double bin_value = 0; + std::cout << "Bin " << j << std::endl << std::endl; + for (int i = 0; i < data.num_items; ++i) { + if (x[i][j]->solution_value() == 1) { + std::cout << "Item " << i << " - weight: " << data.weights[i] + << " value: " << data.values[i] << std::endl; + bin_weight += data.weights[i]; + bin_value += data.values[i]; + } + } + std::cout << "Packed bin weight: " << bin_weight << std::endl; + std::cout << "Packed bin value: " << bin_value << std::endl << std::endl; + total_weight += bin_weight; + } + std::cout << "Total packed weight: " << total_weight << std::endl; + // [END print_solution] +} +} // namespace operations_research + +int main(int argc, char** argv) { + operations_research::MultipleKnapsackMip(); + return EXIT_SUCCESS; +} +// [END program_part2] +// [END program] diff --git a/ortools/linear_solver/samples/multiple_knapsack_mip.py b/ortools/linear_solver/samples/multiple_knapsack_mip.py new file mode 100644 index 0000000000..b0d0b8b6d8 --- /dev/null +++ b/ortools/linear_solver/samples/multiple_knapsack_mip.py @@ -0,0 +1,117 @@ +# Copyright 2010-2018 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. +"""Solve a multiple knapsack problem using a MIP solver.""" +# [START program] +# [START import] +from __future__ import print_function +from ortools.linear_solver import pywraplp + +# [END import] + + +# [START program_part1] +# [START data_model] +def create_data_model(): + """Create the data for the example.""" + data = {} + weights = [48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36] + values = [10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25] + data['weights'] = weights + data['values'] = values + data['items'] = list(range(len(weights))) + data['num_items'] = len(weights) + num_bins = 5 + data['bins'] = list(range(num_bins)) + data['bin_capacities'] = [100, 100, 100, 100, 100] + return data + + +# [END data_model] + + +def main(): + # [START data] + data = create_data_model() + # [END data] + # [END program_part1] + + # [START solver] + # Create the mip solver with the CBC backend. + solver = pywraplp.Solver('multiple_knapsack_mip', + pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + # [END solver] + + # [START program_part2] + # [START variables] + # Variables + # x[i, j] = 1 if item i is packed in bin j. + x = {} + for i in data['items']: + for j in data['bins']: + x[(i, j)] = solver.IntVar(0, 1, 'x_%i_%i' % (i, j)) + # [END variables] + + # [START constraints] + # Constraints + # Each item can be in at most one bin. + for i in data['items']: + solver.Add(sum(x[i, j] for j in data['bins']) <= 1) + # The amount packed in each bin cannot exceed its capacity. + for j in data['bins']: + solver.Add( + sum(x[(i, j)] * data['weights'][i] + for i in data['items']) <= data['bin_capacities'][j]) + # [END constraints] + + # [START objective] + # Objective + objective = solver.Objective() + + for i in data['items']: + for j in data['bins']: + objective.SetCoefficient(x[(i, j)], data['values'][i]) + objective.SetMaximization() + # [END objective] + + # [START solve] + status = solver.Solve() + # [END solve] + + # [START print_solution] + if status == pywraplp.Solver.OPTIMAL: + print('Total packed value:', objective.Value()) + total_weight = 0 + for j in data['bins']: + bin_weight = 0 + bin_value = 0 + print('Bin ', j, '\n') + for i in data['items']: + if x[i, j].solution_value() > 0: + print('Item', i, '- weight:', data['weights'][i], ' value:', + data['values'][i]) + bin_weight += data['weights'][i] + bin_value += data['values'][i] + print('Packed bin weight:', bin_weight) + print('Packed bin value:', bin_value) + print() + total_weight += bin_weight + print('Total packed weight:', total_weight) + else: + print('The problem does not have an optimal solution.') + # [END print_solution] + + +if __name__ == '__main__': + main() +# [END program_part2] +# [END program] diff --git a/ortools/sat/samples/BinPackingProblemSat.java b/ortools/sat/samples/BinPackingProblemSat.java index 170b372156..c79d0222df 100644 --- a/ortools/sat/samples/BinPackingProblemSat.java +++ b/ortools/sat/samples/BinPackingProblemSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverStatus; diff --git a/ortools/sat/samples/BoolOrSampleSat.java b/ortools/sat/samples/BoolOrSampleSat.java index eb498fc7e3..9a29f8c37e 100644 --- a/ortools/sat/samples/BoolOrSampleSat.java +++ b/ortools/sat/samples/BoolOrSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.IntVar; import com.google.ortools.sat.Literal; diff --git a/ortools/sat/samples/ChannelingSampleSat.java b/ortools/sat/samples/ChannelingSampleSat.java index d3b4fed8b4..815179146c 100644 --- a/ortools/sat/samples/ChannelingSampleSat.java +++ b/ortools/sat/samples/ChannelingSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/CpIsFunSat.java b/ortools/sat/samples/CpIsFunSat.java index 83da0be8fd..962079e25c 100644 --- a/ortools/sat/samples/CpIsFunSat.java +++ b/ortools/sat/samples/CpIsFunSat.java @@ -12,6 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/EarlinessTardinessCostSampleSat.java b/ortools/sat/samples/EarlinessTardinessCostSampleSat.java index cffd7d856e..a5cdbea7e8 100644 --- a/ortools/sat/samples/EarlinessTardinessCostSampleSat.java +++ b/ortools/sat/samples/EarlinessTardinessCostSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/IntervalSampleSat.java b/ortools/sat/samples/IntervalSampleSat.java index b5de23eb43..2c297d2241 100644 --- a/ortools/sat/samples/IntervalSampleSat.java +++ b/ortools/sat/samples/IntervalSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.IntVar; import com.google.ortools.sat.IntervalVar; diff --git a/ortools/sat/samples/LiteralSampleSat.java b/ortools/sat/samples/LiteralSampleSat.java index 21270fb89d..d000af8d90 100644 --- a/ortools/sat/samples/LiteralSampleSat.java +++ b/ortools/sat/samples/LiteralSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.IntVar; import com.google.ortools.sat.Literal; diff --git a/ortools/sat/samples/MultipleKnapsackSat.java b/ortools/sat/samples/MultipleKnapsackSat.java index 108032cb2d..6d05f124f7 100644 --- a/ortools/sat/samples/MultipleKnapsackSat.java +++ b/ortools/sat/samples/MultipleKnapsackSat.java @@ -12,6 +12,7 @@ // limitations under the License. // [START program] +package com.google.ortools.sat.samples; // [START import] import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; diff --git a/ortools/sat/samples/NoOverlapSampleSat.java b/ortools/sat/samples/NoOverlapSampleSat.java index 480884b15b..b0a763082b 100644 --- a/ortools/sat/samples/NoOverlapSampleSat.java +++ b/ortools/sat/samples/NoOverlapSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverStatus; diff --git a/ortools/sat/samples/OptionalIntervalSampleSat.java b/ortools/sat/samples/OptionalIntervalSampleSat.java index a9be344c8d..9d90346e70 100644 --- a/ortools/sat/samples/OptionalIntervalSampleSat.java +++ b/ortools/sat/samples/OptionalIntervalSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.IntVar; import com.google.ortools.sat.IntervalVar; diff --git a/ortools/sat/samples/RabbitsAndPheasantsSat.java b/ortools/sat/samples/RabbitsAndPheasantsSat.java index 9b8c4c08b7..579ba1a39c 100644 --- a/ortools/sat/samples/RabbitsAndPheasantsSat.java +++ b/ortools/sat/samples/RabbitsAndPheasantsSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverStatus; diff --git a/ortools/sat/samples/RankingSampleSat.java b/ortools/sat/samples/RankingSampleSat.java index 5216555fb9..f24c9effd4 100644 --- a/ortools/sat/samples/RankingSampleSat.java +++ b/ortools/sat/samples/RankingSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverStatus; diff --git a/ortools/sat/samples/ReifiedSampleSat.java b/ortools/sat/samples/ReifiedSampleSat.java index 1d70fe8fec..6a999d9602 100644 --- a/ortools/sat/samples/ReifiedSampleSat.java +++ b/ortools/sat/samples/ReifiedSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.IntVar; import com.google.ortools.sat.Literal; diff --git a/ortools/sat/samples/SearchForAllSolutionsSampleSat.java b/ortools/sat/samples/SearchForAllSolutionsSampleSat.java index ebd1f3daeb..c803d6732f 100644 --- a/ortools/sat/samples/SearchForAllSolutionsSampleSat.java +++ b/ortools/sat/samples/SearchForAllSolutionsSampleSat.java @@ -12,6 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/SimpleSatProgram.java b/ortools/sat/samples/SimpleSatProgram.java index 49bd59aa53..9aff75c33b 100644 --- a/ortools/sat/samples/SimpleSatProgram.java +++ b/ortools/sat/samples/SimpleSatProgram.java @@ -12,6 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverStatus; diff --git a/ortools/sat/samples/SolutionHintingSampleSat.java b/ortools/sat/samples/SolutionHintingSampleSat.java index 965f110107..3a414f0684 100644 --- a/ortools/sat/samples/SolutionHintingSampleSat.java +++ b/ortools/sat/samples/SolutionHintingSampleSat.java @@ -12,6 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/SolveAndPrintIntermediateSolutionsSampleSat.java b/ortools/sat/samples/SolveAndPrintIntermediateSolutionsSampleSat.java index 8255eebfd6..5cda9146b0 100644 --- a/ortools/sat/samples/SolveAndPrintIntermediateSolutionsSampleSat.java +++ b/ortools/sat/samples/SolveAndPrintIntermediateSolutionsSampleSat.java @@ -12,6 +12,8 @@ // limitations under the License. // [START program] +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/SolveWithTimeLimitSampleSat.java b/ortools/sat/samples/SolveWithTimeLimitSampleSat.java index bbe7489701..995ba51ccc 100644 --- a/ortools/sat/samples/SolveWithTimeLimitSampleSat.java +++ b/ortools/sat/samples/SolveWithTimeLimitSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverStatus; diff --git a/ortools/sat/samples/StepFunctionSampleSat.java b/ortools/sat/samples/StepFunctionSampleSat.java index f6ddfc0354..227bf7f5f9 100644 --- a/ortools/sat/samples/StepFunctionSampleSat.java +++ b/ortools/sat/samples/StepFunctionSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback; diff --git a/ortools/sat/samples/StopAfterNSolutionsSampleSat.java b/ortools/sat/samples/StopAfterNSolutionsSampleSat.java index 25586f1e01..09a657f230 100644 --- a/ortools/sat/samples/StopAfterNSolutionsSampleSat.java +++ b/ortools/sat/samples/StopAfterNSolutionsSampleSat.java @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +package com.google.ortools.sat.samples; + import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.CpSolverSolutionCallback;