diff --git a/ortools/algorithms/java/KnapsackSolverTest.java b/ortools/algorithms/java/KnapsackSolverTest.java index eb480ff340..bc459cc2b4 100644 --- a/ortools/algorithms/java/KnapsackSolverTest.java +++ b/ortools/algorithms/java/KnapsackSolverTest.java @@ -27,12 +27,82 @@ public final class KnapsackSolverTest { Loader.loadNativeLibraries(); } - @Test - public void testKnapsackSolver() { - final KnapsackSolver solver = new KnapsackSolver( - KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "test"); + private long runKnapsackSolver(final KnapsackSolver.SolverType solverType, final long[] profits, + final long[][] weights, final long[] capacities) { + final KnapsackSolver solver = new KnapsackSolver(solverType, "test"); assertNotNull(solver); + solver.init(profits, weights, capacities); + return solver.solve(); + } + + private void solveKnapsackProblem(final long[] profits, final long[][] weights, + final long[] capacities, final long optimalProfit) { + final int maxNumberOfItemsForBruteForce = 20; + final int maxNumberOfItemsForDivideAndConquer = 32; + final int maxNumberOfItemsFor64ItemsSolver = 64; + + { + final long profit = runKnapsackSolver( + KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, profits, + weights, capacities); + assertEquals(optimalProfit, profit); + } + + // Other solvers don't support multidimension models. + if (weights.length > 1) { + return; + } + + final int numOfItems = profits.length; + + if (numOfItems <= maxNumberOfItemsForBruteForce) { + final long profit = runKnapsackSolver( + KnapsackSolver.SolverType.KNAPSACK_BRUTE_FORCE_SOLVER, profits, weights, capacities); + assertEquals(optimalProfit, profit); + } + + if (numOfItems <= maxNumberOfItemsForDivideAndConquer) { + final long profit = + runKnapsackSolver(KnapsackSolver.SolverType.KNAPSACK_DIVIDE_AND_CONQUER_SOLVER, profits, + weights, capacities); + assertEquals(optimalProfit, profit); + } + + { + final long profit = + runKnapsackSolver(KnapsackSolver.SolverType.KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER, profits, + weights, capacities); + assertEquals(optimalProfit, profit); + } + + if (numOfItems <= maxNumberOfItemsFor64ItemsSolver) { + final long profit = runKnapsackSolver( + KnapsackSolver.SolverType.KNAPSACK_64ITEMS_SOLVER, profits, weights, capacities); + assertEquals(optimalProfit, profit); + } + } + + @Test + public void testSolveOneDimension() { + final long[] profits = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + final long[][] weights = {{1, 2, 3, 4, 5, 6, 7, 8, 9}}; + final long[] capacities = {34}; + final long optimalProfit = 34; + solveKnapsackProblem(profits, weights, capacities, optimalProfit); + } + + @Test + public void testSolveTwoDimensions() { + final long[] profits = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + final long[][] weights = {{1, 2, 3, 4, 5, 6, 7, 8, 9}, {1, 1, 1, 1, 1, 1, 1, 1, 1}}; + final long[] capacities = {34, 4}; + final long optimalProfit = 30; + solveKnapsackProblem(profits, weights, capacities, optimalProfit); + } + + @Test + public void testSolveBigOneDimension() { final long[] profits = {360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312}; @@ -40,9 +110,7 @@ public final class KnapsackSolverTest { 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13}}; final long[] capacities = {850}; - solver.init(profits, weights, capacities); - - final long computedProfit = solver.solve(); - assertEquals(7534, computedProfit); + final long optimalProfit = 7534; + solveKnapsackProblem(profits, weights, capacities, optimalProfit); } } diff --git a/ortools/base/dump_vars.h b/ortools/base/dump_vars.h index 2e96d48397..5be3260567 100644 --- a/ortools/base/dump_vars.h +++ b/ortools/base/dump_vars.h @@ -45,6 +45,7 @@ #include #include #include + #include "absl/container/inlined_vector.h" /* need extra level to force extra eval */ diff --git a/ortools/constraint_solver/assignment.proto b/ortools/constraint_solver/assignment.proto index cdd5e4b1c8..3cfcb41093 100644 --- a/ortools/constraint_solver/assignment.proto +++ b/ortools/constraint_solver/assignment.proto @@ -11,10 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. - syntax = "proto3"; - package operations_research; // Storage for IntVars. @@ -63,4 +61,3 @@ message AssignmentProto { WorkerInfo worker_info = 4; bool is_valid = 5; } - diff --git a/ortools/constraint_solver/demon_profiler.proto b/ortools/constraint_solver/demon_profiler.proto index e276faad36..2595a29c35 100644 --- a/ortools/constraint_solver/demon_profiler.proto +++ b/ortools/constraint_solver/demon_profiler.proto @@ -11,10 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. - syntax = "proto3"; - package operations_research; message DemonRuns { diff --git a/ortools/glop/parameters.proto b/ortools/glop/parameters.proto index 629bfb3a17..b1b4ce0763 100644 --- a/ortools/glop/parameters.proto +++ b/ortools/glop/parameters.proto @@ -11,7 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. - // Contains the definitions for all the GLOP algorithm parameters and their // default values. // @@ -28,7 +27,6 @@ option csharp_namespace = "Google.OrTools.Glop"; // next id = 69 message GlopParameters { - // Supported algorithms for scaling: // EQUILIBRATION - progressive scaling by row and column norms until the // marginal difference passes below a threshold. @@ -95,7 +93,6 @@ message GlopParameters { MAROS = 3; } - optional ScalingAlgorithm scaling_method = 57 [default = EQUILIBRATION]; // PricingRule to use during the feasibility phase. @@ -483,5 +480,4 @@ message GlopParameters { // evaluating large constraint with variables at their bound shouldn't cause // any overflow. optional double max_valid_magnitude = 199 [default = 1e30]; - } diff --git a/ortools/init/python/pywrapinit_test.py b/ortools/init/python/pywrapinit_test.py index 10ceee0c17..67aed30ede 100755 --- a/ortools/init/python/pywrapinit_test.py +++ b/ortools/init/python/pywrapinit_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # 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. @@ -16,6 +15,7 @@ import unittest from ortools.init import pywrapinit + class PyWrapInit(unittest.TestCase): def test_logging(self): @@ -26,13 +26,13 @@ class PyWrapInit(unittest.TestCase): def test_flags(self): print('test_cpp_flags') cpp_flags = pywrapinit.CppFlags() - #print(f'{dir(cpp_flags)}') - assert hasattr(cpp_flags, "logtostderr") - assert hasattr(cpp_flags, "log_prefix") - assert hasattr(cpp_flags, "cp_model_dump_prefix") - assert hasattr(cpp_flags, "cp_model_dump_models") - assert hasattr(cpp_flags, "cp_model_dump_lns") - assert hasattr(cpp_flags, "cp_model_dump_response") + # print(f'{dir(cpp_flags)}') + assert hasattr(cpp_flags, 'logtostderr') + assert hasattr(cpp_flags, 'log_prefix') + assert hasattr(cpp_flags, 'cp_model_dump_prefix') + assert hasattr(cpp_flags, 'cp_model_dump_models') + assert hasattr(cpp_flags, 'cp_model_dump_lns') + assert hasattr(cpp_flags, 'cp_model_dump_response') pywrapinit.CppBridge.SetFlags(cpp_flags) def test_version(self): @@ -48,5 +48,6 @@ class PyWrapInit(unittest.TestCase): string = f'{major}.{minor}.{patch}' self.assertEqual(version, string) + if __name__ == '__main__': unittest.main() diff --git a/ortools/linear_solver/linear_solver.proto b/ortools/linear_solver/linear_solver.proto index 3fdc72b864..a7999bbc1b 100644 --- a/ortools/linear_solver/linear_solver.proto +++ b/ortools/linear_solver/linear_solver.proto @@ -34,7 +34,6 @@ option java_multiple_files = true; import "ortools/util/optional_boolean.proto"; - package operations_research; // A variable is always constrained in the form: @@ -423,15 +422,18 @@ message MPModelRequest { GLOP_LINEAR_PROGRAMMING = 2; // Recommended default for LP models. GLPK_LINEAR_PROGRAMMING = 1; GUROBI_LINEAR_PROGRAMMING = 6; // Commercial, needs a valid license. - XPRESS_LINEAR_PROGRAMMING = 101; // Commercial, needs a valid license. NOLINT + XPRESS_LINEAR_PROGRAMMING = + 101; // Commercial, needs a valid license. NOLINT CPLEX_LINEAR_PROGRAMMING = 10; // Commercial, needs a valid license. NOLINT SCIP_MIXED_INTEGER_PROGRAMMING = 3; // Recommended default for MIP models. GLPK_MIXED_INTEGER_PROGRAMMING = 4; CBC_MIXED_INTEGER_PROGRAMMING = 5; GUROBI_MIXED_INTEGER_PROGRAMMING = 7; // Commercial, needs a valid license. - XPRESS_MIXED_INTEGER_PROGRAMMING = 102; // Commercial, needs a valid license. NOLINT - CPLEX_MIXED_INTEGER_PROGRAMMING = 11; // Commercial, needs a valid license. NOLINT + XPRESS_MIXED_INTEGER_PROGRAMMING = + 102; // Commercial, needs a valid license. NOLINT + CPLEX_MIXED_INTEGER_PROGRAMMING = + 11; // Commercial, needs a valid license. NOLINT BOP_INTEGER_PROGRAMMING = 12; // WARNING: This solver will currently interpret all variables as integer, @@ -440,7 +442,6 @@ message MPModelRequest { // variables). SAT_INTEGER_PROGRAMMING = 14; - // In-house linear programming solver based on the primal-dual hybrid // gradient method. Sometimes faster than Glop for medium-size problems and // scales to much larger problems than Glop. @@ -460,7 +461,6 @@ message MPModelRequest { // If not specified, the time limit on the solver is the RPC's deadline_left. optional double solver_time_limit_seconds = 3; - // If this is set, then EnableOutput() will be set on the internal MPSolver // that solves the model. // WARNING: if you set this on a request to prod servers, it will be rejected @@ -484,13 +484,10 @@ message MPModelRequest { optional string solver_specific_parameters = 5; optional bool ignore_solver_specific_parameters_failure = 9 [default = false]; - // Advanced usage: model "delta". If used, "model" must be unset. See the // definition of MPModelDeltaProto. optional MPModelDeltaProto model_delta = 8; - - // Controls the recovery of additional solutions, if any, saved by the // underlying solver back in the MPSolutionResponse.additional_solutions. // The repeated field will be length @@ -499,10 +496,8 @@ message MPModelRequest { // These additional solutions may have a worse objective than the main // solution returned in the response. optional int32 populate_additional_solutions_up_to = 11 [default = 0]; - } - // Status returned by the solver. They follow a hierarchical nomenclature, to // allow us to add more enum values in the future. Clients should use // InCategory() to match these enums, with the following C++ pseudo-code: @@ -585,7 +580,6 @@ enum MPSolverResponseStatus { // solver that doesn't support cancellation. status_str should contain a // description of the issue. MPSOLVER_INCOMPATIBLE_OPTIONS = 0x71; - } message MPSolution { @@ -663,5 +657,4 @@ message MPSolutionResponse { // additional solutions are different than the main solution described by the // above fields `objective_value` and `variable_value`. repeated MPSolution additional_solutions = 8; - } diff --git a/ortools/linear_solver/model_exporter.h b/ortools/linear_solver/model_exporter.h index ca794cf21f..74f961f351 100644 --- a/ortools/linear_solver/model_exporter.h +++ b/ortools/linear_solver/model_exporter.h @@ -27,8 +27,6 @@ namespace operations_research { /// Export options. struct MPModelExportOptions { - MPModelExportOptions() {} - /// Obfuscates variable and constraint names. bool obfuscate = false; /// Whether to log invalid variable and constraint names. @@ -65,7 +63,7 @@ struct MPModelExportOptions { * http://lpsolve.sourceforge.net/5.5/lp-format.htm * The following give a reasonable idea of the CPLEX LP file format: * http://lpsolve.sourceforge.net/5.5/CPLEX-format.htm - * http://tinyurl.com/cplex-lp-format + * https://www.ibm.com/docs/en/icos/12.8.0.0?topic=cplex-lp-file-format-algebraic-representation * http://www.gurobi.com/documentation/5.1/reference-manual/node871 */ absl::StatusOr ExportModelAsLpFormat( diff --git a/ortools/linear_solver/python/model_builder_test.py b/ortools/linear_solver/python/model_builder_test.py index db7fd5c23e..4a713fe4e8 100644 --- a/ortools/linear_solver/python/model_builder_test.py +++ b/ortools/linear_solver/python/model_builder_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # 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. diff --git a/ortools/packing/multiple_dimensions_bin_packing.proto b/ortools/packing/multiple_dimensions_bin_packing.proto index 6cb55110e3..6aa79515ca 100644 --- a/ortools/packing/multiple_dimensions_bin_packing.proto +++ b/ortools/packing/multiple_dimensions_bin_packing.proto @@ -17,7 +17,6 @@ package operations_research.packing; option java_multiple_files = true; - // A Multiple Dimension BinPacking problem. // It supports the following file format: // - 2bp: diff --git a/ortools/scheduling/course_scheduling.proto b/ortools/scheduling/course_scheduling.proto index ffef3037ab..fcb564a0b0 100644 --- a/ortools/scheduling/course_scheduling.proto +++ b/ortools/scheduling/course_scheduling.proto @@ -15,7 +15,6 @@ syntax = "proto3"; package operations_research; - // Information required to create a schedule for a school system. message CourseSchedulingModel { // Schedule name, used only for logging purposes. @@ -48,8 +47,7 @@ message CourseSchedulingResult { string message = 1; // Status of the solver. - CourseSchedulingResultStatus solver_status = 2 -; + CourseSchedulingResultStatus solver_status = 2; // List of the time slot and room assignments for each section of a course. repeated ClassAssignment class_assignments = 3; diff --git a/ortools/util/fp_roundtrip_conv.cc b/ortools/util/fp_roundtrip_conv.cc index 65c3822bcf..072032778a 100644 --- a/ortools/util/fp_roundtrip_conv.cc +++ b/ortools/util/fp_roundtrip_conv.cc @@ -35,7 +35,7 @@ #if defined(__APPLE__) #undef OPERATION_RESEARCH_STD_TO_CHARS_DOUBLE_SUPPORTED #endif -#if defined(__GNUC__) && __GNUC__ < 11 +#if defined(__GNUC__) && !defined(__llvm__) && __GNUC__ < 11 #undef OPERATION_RESEARCH_STD_TO_CHARS_DOUBLE_SUPPORTED #endif diff --git a/ortools/util/fp_roundtrip_conv.h b/ortools/util/fp_roundtrip_conv.h index 4e85486978..324cb1cf44 100644 --- a/ortools/util/fp_roundtrip_conv.h +++ b/ortools/util/fp_roundtrip_conv.h @@ -17,7 +17,6 @@ #ifndef OR_TOOLS_UTIL_FP_ROUNDTRIP_CONV_H_ #define OR_TOOLS_UTIL_FP_ROUNDTRIP_CONV_H_ -#include #include #include @@ -31,7 +30,6 @@ namespace operations_research { // // std::to_chars() for double is not yet supported on Emscripten, Android and // iOS; they only implement std::to_chars() for integers. - ABSL_CONST_INIT extern const bool kStdToCharsDoubleIsSupported; // Formatter using std::to_chars() to print a `double` so that a round trip diff --git a/ortools/util/python/sorted_interval_list_test.py b/ortools/util/python/sorted_interval_list_test.py index 252c766eea..0939ce8978 100755 --- a/ortools/util/python/sorted_interval_list_test.py +++ b/ortools/util/python/sorted_interval_list_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # 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. @@ -13,7 +12,6 @@ # limitations under the License. """Tests for ortools.util.python.sorted_interval_list.""" - import unittest from ortools.util.python import sorted_interval_list