diff --git a/examples/cpp/BUILD b/examples/cpp/BUILD index 505de76f27..82ad0aca31 100644 --- a/examples/cpp/BUILD +++ b/examples/cpp/BUILD @@ -1,524 +1,282 @@ -cc_binary( - name = "constraint_programming_cp", - srcs = ["constraint_programming_cp.cc"], - deps = [ - "//ortools/base", - "//ortools/constraint_solver:cp", - ], -) +cc_binary(name = "constraint_programming_cp", + srcs = ["constraint_programming_cp.cc"], + deps = ["//ortools/base", "//ortools/constraint_solver:cp", ], ) -cc_binary( - name = "costas_array_sat", - srcs = ["costas_array_sat.cc"], - deps = [ - "//ortools/base", - "//ortools/base:random", - "//ortools/sat:cp_model", - "//ortools/sat:model", - ], -) +cc_binary(name = "costas_array_sat", srcs = ["costas_array_sat.cc"], + deps = ["//ortools/base", + "//ortools/base:random", "//ortools/sat:cp_model", + "//ortools/sat:model", + ], ) cc_library( - name = "cvrptw_lib", - hdrs = ["cvrptw_lib.h"], - deps = [ - "//ortools/base", - "//ortools/base:random", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) + name = "cvrptw_lib", hdrs = ["cvrptw_lib.h"], + deps = ["//ortools/base", + "//ortools/base:random", "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "cvrptw", - srcs = ["cvrptw.cc"], - deps = [ - ":cvrptw_lib", - "//ortools/base", - "//ortools/base:random", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) +cc_binary(name = "cvrptw", srcs = ["cvrptw.cc"], + deps = [":cvrptw_lib", + "//ortools/base", "//ortools/base:random", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "cvrp_disjoint_tw", - srcs = ["cvrp_disjoint_tw.cc"], - deps = [ - ":cvrptw_lib", - "//ortools/base", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) +cc_binary(name = "cvrp_disjoint_tw", srcs = ["cvrp_disjoint_tw.cc"], + deps = [":cvrptw_lib", + "//ortools/base", "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "cvrptw_with_breaks", - srcs = ["cvrptw_with_breaks.cc"], - deps = [ - ":cvrptw_lib", - "//ortools/base", - "//ortools/base:random", - "@com_google_absl//absl/strings", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_enums_cc_proto", - "//ortools/constraint_solver:routing_flags", - ], -) +cc_binary(name = "cvrptw_with_breaks", srcs = ["cvrptw_with_breaks.cc"], + deps = [":cvrptw_lib", + "//ortools/base", "//ortools/base:random", + "@com_google_absl//absl/strings", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_enums_cc_proto", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "cvrptw_with_resources", - srcs = ["cvrptw_with_resources.cc"], - deps = [ - ":cvrptw_lib", - "//ortools/base", - "//ortools/base:random", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) +cc_binary(name = "cvrptw_with_resources", srcs = ["cvrptw_with_resources.cc"], + deps = [":cvrptw_lib", + "//ortools/base", "//ortools/base:random", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "cvrptw_with_stop_times_and_resources", - srcs = ["cvrptw_with_stop_times_and_resources.cc"], - deps = [ - ":cvrptw_lib", - "//ortools/base", - "//ortools/base:random", - "@com_google_absl//absl/strings", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) +cc_binary(name = "cvrptw_with_stop_times_and_resources", + srcs = ["cvrptw_with_stop_times_and_resources.cc"], + deps = [":cvrptw_lib", + "//ortools/base", "//ortools/base:random", + "@com_google_absl//absl/strings", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "cvrptw_with_refueling", - srcs = ["cvrptw_with_refueling.cc"], - deps = [ - ":cvrptw_lib", - "//ortools/base", - "//ortools/base:random", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) +cc_binary(name = "cvrptw_with_refueling", srcs = ["cvrptw_with_refueling.cc"], + deps = [":cvrptw_lib", + "//ortools/base", "//ortools/base:random", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) cc_library( - name = "print_dimacs_assignment", - hdrs = ["print_dimacs_assignment.h"], - deps = [ - "//ortools/base", - "//ortools/base:file", - "@com_google_absl//absl/status", - "//ortools/graph:ebert_graph", - "//ortools/graph:linear_assignment", - ], -) + name = "print_dimacs_assignment", hdrs = ["print_dimacs_assignment.h"], + deps = ["//ortools/base", + "//ortools/base:file", "@com_google_absl//absl/status", + "//ortools/graph:ebert_graph", "//ortools/graph:linear_assignment", + ], ) -cc_library( - name = "parse_dimacs_assignment", - hdrs = ["parse_dimacs_assignment.h"], - deps = [ - "//ortools/base", - "//ortools/base:filelineiter", - "//ortools/graph:ebert_graph", - "//ortools/graph:linear_assignment", - ], -) +cc_library(name = "parse_dimacs_assignment", + hdrs = ["parse_dimacs_assignment.h"], + deps = ["//ortools/base", + "//ortools/base:filelineiter", "//ortools/graph:ebert_graph", + "//ortools/graph:linear_assignment", + ], ) cc_binary( - name = "dimacs_assignment", - srcs = ["dimacs_assignment.cc"], - deps = [ - ":parse_dimacs_assignment", - ":print_dimacs_assignment", - "//ortools/algorithms:hungarian", - "//ortools/base", - "//ortools/base:timer", - "//ortools/graph:ebert_graph", - "//ortools/graph:linear_assignment", - ], -) + name = "dimacs_assignment", srcs = ["dimacs_assignment.cc"], + deps = [":parse_dimacs_assignment", + ":print_dimacs_assignment", "//ortools/algorithms:hungarian", + "//ortools/base", "//ortools/base:timer", + "//ortools/graph:ebert_graph", "//ortools/graph:linear_assignment", + ], ) + +cc_binary(name = "dobble_ls", srcs = ["dobble_ls.cc"], + deps = ["//ortools/base", + "//ortools/base:map_util", "//ortools/base:random", + "//ortools/constraint_solver:cp", "//ortools/util:bitset", + ], ) + +cc_binary(name = "flow_api", srcs = ["flow_api.cc"], + deps = ["//ortools/base", + "//ortools/graph:ebert_graph", "//ortools/graph:max_flow", + "//ortools/graph:min_cost_flow", + ], ) + +cc_library(name = "fap_parser", hdrs = ["fap_parser.h"], + deps = ["//ortools/base", + "//ortools/base:file", "//ortools/base:hash", + "//ortools/base:map_util", "@com_google_absl//absl/strings", + ], ) + +cc_library(name = "fap_model_printer", hdrs = ["fap_model_printer.h"], + deps = [":fap_parser", + "//ortools/base", "//ortools/base:file", + "@com_google_absl//absl/strings", + ], ) + +cc_library(name = "fap_utilities", hdrs = ["fap_utilities.h"], + deps = [":fap_parser", + "//ortools/base", "//ortools/base:map_util", + "//ortools/constraint_solver:cp", + ], ) + +cc_binary(name = "frequency_assignment_problem", + srcs = ["frequency_assignment_problem.cc"], + deps = [":fap_model_printer", + ":fap_parser", ":fap_utilities", "//ortools/base", + "//ortools/base:map_util", "//ortools/constraint_solver:cp", + ], ) + +cc_binary(name = "golomb_sat", srcs = ["golomb_sat.cc"], + deps = ["//ortools/base", + "@com_google_absl//absl/strings", "//ortools/sat:cp_model", + "//ortools/sat:model", + ], ) + +cc_binary(name = "integer_programming", srcs = ["integer_programming.cc"], + deps = ["//ortools/base", "//ortools/linear_solver", ], ) + +cc_binary(name = "jobshop_sat", srcs = ["jobshop_sat.cc", ], + deps = ["//ortools/base", + "//ortools/base:file", "@com_google_absl//absl/strings", + "//ortools/base:timer", + "//ortools/data:jobshop_scheduling_cc_proto", + "//ortools/data:jobshop_scheduling_parser", + "//ortools/sat:cp_model", "//ortools/sat:cp_model_solver", + "//ortools/sat:disjunctive", "//ortools/sat:integer", + "//ortools/sat:intervals", "//ortools/sat:model", + "//ortools/sat:optimization", "//ortools/sat:precedences", + "//ortools/sat:sat_solver", + ], ) cc_binary( - name = "dobble_ls", - srcs = ["dobble_ls.cc"], - deps = [ - "//ortools/base", - "//ortools/base:map_util", - "//ortools/base:random", - "//ortools/constraint_solver:cp", - "//ortools/util:bitset", - ], -) + name = "linear_assignment_api", srcs = ["linear_assignment_api.cc"], + deps = ["//ortools/base", + "//ortools/graph:ebert_graph", "//ortools/graph:linear_assignment", + ], ) + +cc_binary(name = "linear_programming", srcs = ["linear_programming.cc"], + deps = ["//ortools/base", + "//ortools/linear_solver", + "//ortools/linear_solver:linear_solver_cc_proto", + ], ) + +cc_binary(name = "linear_solver_protocol_buffers", + srcs = ["linear_solver_protocol_buffers.cc"], + deps = ["//ortools/base", + "//ortools/linear_solver", + "//ortools/linear_solver:linear_solver_cc_proto", + ], ) + +cc_binary(name = "magic_square_sat", srcs = ["magic_square_sat.cc"], + deps = ["//ortools/base", + "@com_google_absl//absl/strings", "//ortools/sat:cp_model", + "//ortools/sat:model", + ], ) + +cc_binary(name = "max_flow", srcs = ["max_flow.cc"], + deps = ["//ortools/base", "//ortools/graph:max_flow", ], ) + +cc_binary(name = "min_cost_flow", srcs = ["min_cost_flow.cc"], + deps = ["//ortools/base", "//ortools/graph:min_cost_flow", ], ) cc_binary( - name = "flow_api", - srcs = ["flow_api.cc"], - deps = [ - "//ortools/base", - "//ortools/graph:ebert_graph", - "//ortools/graph:max_flow", - "//ortools/graph:min_cost_flow", - ], -) + name = "mps_driver", srcs = ["mps_driver.cc"], + deps = ["//ortools/base", + "@com_google_absl//absl/strings", "//ortools/base:timer", + "//ortools/glop:lp_solver", "//ortools/glop:parameters_cc_proto", + "//ortools/lp_data:mps_reader", "//ortools/util:proto_tools", + "@com_google_protobuf//:protobuf", + ], ) -cc_library( - name = "fap_parser", - hdrs = ["fap_parser.h"], - deps = [ - "//ortools/base", - "//ortools/base:file", - "//ortools/base:hash", - "//ortools/base:map_util", - "@com_google_absl//absl/strings", - ], -) +cc_binary(name = "network_routing_sat", srcs = ["network_routing_sat.cc"], + deps = ["//ortools/base", + "//ortools/base:hash", "//ortools/base:map_util", + "//ortools/base:random", "@com_google_absl//absl/strings", + "//ortools/graph:shortestpaths", "//ortools/sat:cp_model", + "//ortools/sat:model", "//ortools/util:tuple_set", + ], ) -cc_library( - name = "fap_model_printer", - hdrs = ["fap_model_printer.h"], - deps = [ - ":fap_parser", - "//ortools/base", - "//ortools/base:file", - "@com_google_absl//absl/strings", - ], -) +cc_binary(name = "nqueens", srcs = ["nqueens.cc"], + deps = ["//ortools/base", + "//ortools/base:map_util", "//ortools/constraint_solver:cp", + ], ) -cc_library( - name = "fap_utilities", - hdrs = ["fap_utilities.h"], - deps = [ - ":fap_parser", - "//ortools/base", - "//ortools/base:map_util", - "//ortools/constraint_solver:cp", - ], -) +cc_binary(name = "pdptw", srcs = ["pdptw.cc"], + deps = ["//ortools/base", + "//ortools/base:file", "//ortools/base:mathutil", + "@com_google_absl//absl/strings", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + ], ) -cc_binary( - name = "frequency_assignment_problem", - srcs = ["frequency_assignment_problem.cc"], - deps = [ - ":fap_model_printer", - ":fap_parser", - ":fap_utilities", - "//ortools/base", - "//ortools/base:map_util", - "//ortools/constraint_solver:cp", - ], -) - -cc_binary( - name = "golomb_sat", - srcs = ["golomb_sat.cc"], - deps = [ - "//ortools/base", - "@com_google_absl//absl/strings", - "//ortools/sat:cp_model", - "//ortools/sat:model", - ], -) - -cc_binary( - name = "integer_programming", - srcs = ["integer_programming.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - ], -) - -cc_binary( - name = "jobshop_sat", - srcs = [ - "jobshop_sat.cc", - ], - deps = [ - "//ortools/base", - "//ortools/base:file", - "@com_google_absl//absl/strings", - "//ortools/base:timer", - "//ortools/data:jobshop_scheduling_cc_proto", - "//ortools/data:jobshop_scheduling_parser", - "//ortools/sat:cp_model", - "//ortools/sat:cp_model_solver", - "//ortools/sat:disjunctive", - "//ortools/sat:integer", - "//ortools/sat:intervals", - "//ortools/sat:model", - "//ortools/sat:optimization", - "//ortools/sat:precedences", - "//ortools/sat:sat_solver", - ], -) - -cc_binary( - name = "linear_assignment_api", - srcs = ["linear_assignment_api.cc"], - deps = [ - "//ortools/base", - "//ortools/graph:ebert_graph", - "//ortools/graph:linear_assignment", - ], -) - -cc_binary( - name = "linear_programming", - srcs = ["linear_programming.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - "//ortools/linear_solver:linear_solver_cc_proto", - ], -) - -cc_binary( - name = "linear_solver_protocol_buffers", - srcs = ["linear_solver_protocol_buffers.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - "//ortools/linear_solver:linear_solver_cc_proto", - ], -) - -cc_binary( - name = "magic_square_sat", - srcs = ["magic_square_sat.cc"], - deps = [ - "//ortools/base", - "@com_google_absl//absl/strings", - "//ortools/sat:cp_model", - "//ortools/sat:model", - ], -) - -cc_binary( - name = "max_flow", - srcs = ["max_flow.cc"], - deps = [ - "//ortools/base", - "//ortools/graph:max_flow", - ], -) - -cc_binary( - name = "min_cost_flow", - srcs = ["min_cost_flow.cc"], - deps = [ - "//ortools/base", - "//ortools/graph:min_cost_flow", - ], -) - -cc_binary( - name = "mps_driver", - srcs = ["mps_driver.cc"], - deps = [ - "//ortools/base", - "@com_google_absl//absl/strings", - "//ortools/base:timer", - "//ortools/glop:lp_solver", - "//ortools/glop:parameters_cc_proto", - "//ortools/lp_data:mps_reader", - "//ortools/util:proto_tools", - "@com_google_protobuf//:protobuf", - ], -) - -cc_binary( - name = "network_routing_sat", - srcs = ["network_routing_sat.cc"], - deps = [ - "//ortools/base", - "//ortools/base:hash", - "//ortools/base:map_util", - "//ortools/base:random", - "@com_google_absl//absl/strings", - "//ortools/graph:shortestpaths", - "//ortools/sat:cp_model", - "//ortools/sat:model", - "//ortools/util:tuple_set", - ], -) - -cc_binary( - name = "nqueens", - srcs = ["nqueens.cc"], - deps = [ - "//ortools/base", - "//ortools/base:map_util", - "//ortools/constraint_solver:cp", - ], -) - -cc_binary( - name = "pdptw", - srcs = ["pdptw.cc"], - deps = [ - "//ortools/base", - "//ortools/base:file", - "//ortools/base:mathutil", - "@com_google_absl//absl/strings", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - ], -) - -cc_binary( - name = "random_tsp", - srcs = ["random_tsp.cc"], - deps = [ - "//ortools/base", - "//ortools/base:random", - "@com_google_absl//absl/strings", - "//ortools/constraint_solver:routing", - "//ortools/constraint_solver:routing_flags", - "@com_google_protobuf//:protobuf", - ], -) +cc_binary(name = "random_tsp", srcs = ["random_tsp.cc"], + deps = ["//ortools/base", + "//ortools/base:random", "@com_google_absl//absl/strings", + "//ortools/constraint_solver:routing", + "//ortools/constraint_solver:routing_flags", + "@com_google_protobuf//:protobuf", + ], ) cc_binary( name = "sat_runner", - srcs = [ - "opb_reader.h", - "sat_cnf_reader.h", - "sat_runner.cc", - ], - deps = [ - "//ortools/algorithms:sparse_permutation", - "//ortools/base", - "//ortools/base:file", - "//ortools/base:filelineiter", - "//ortools/base:random", - "@com_google_absl//absl/status", - "@com_google_absl//absl/strings", - "//ortools/base:threadpool", - "//ortools/lp_data:mps_reader", - "//ortools/lp_data:proto_utils", - "//ortools/sat:boolean_problem", - "//ortools/sat:boolean_problem_cc_proto", - "//ortools/sat:cp_model_cc_proto", - "//ortools/sat:cp_model_solver", - "//ortools/sat:drat_proof_handler", - "//ortools/sat:lp_utils", - "//ortools/sat:optimization", - "//ortools/sat:sat_solver", - "//ortools/sat:simplification", - "//ortools/sat:symmetry", - "//ortools/util:sigint", - "//ortools/util:time_limit", - "@com_google_protobuf//:protobuf", - ], -) + srcs = ["opb_reader.h", "sat_cnf_reader.h", "sat_runner.cc", ], + deps = ["//ortools/algorithms:sparse_permutation", + "//ortools/base", "//ortools/base:file", + "//ortools/base:filelineiter", "//ortools/base:random", + "@com_google_absl//absl/status", "@com_google_absl//absl/strings", + "//ortools/base:threadpool", "//ortools/lp_data:mps_reader", + "//ortools/lp_data:proto_utils", "//ortools/sat:boolean_problem", + "//ortools/sat:boolean_problem_cc_proto", + "//ortools/sat:cp_model_cc_proto", "//ortools/sat:cp_model_solver", + "//ortools/sat:drat_proof_handler", "//ortools/sat:lp_utils", + "//ortools/sat:optimization", "//ortools/sat:sat_solver", + "//ortools/sat:simplification", "//ortools/sat:symmetry", + "//ortools/util:sigint", "//ortools/util:time_limit", + "@com_google_protobuf//:protobuf", + ], ) + +cc_binary(name = "shift_minimization_sat", + srcs = ["shift_minimization_sat.cc", ], + deps = ["//ortools/base", + "//ortools/base:file", "//ortools/base:filelineiter", + "@com_google_absl//absl/strings", "//ortools/sat:cp_model", + "//ortools/sat:model", + ], ) cc_binary( - name = "shift_minimization_sat", - srcs = [ - "shift_minimization_sat.cc", - ], - deps = [ - "//ortools/base", - "//ortools/base:file", - "//ortools/base:filelineiter", - "@com_google_absl//absl/strings", - "//ortools/sat:cp_model", - "//ortools/sat:model", - ], -) + name = "slitherlink_sat", srcs = ["slitherlink_sat.cc"], + deps = + ["//ortools/base", "//ortools/sat:cp_model", "//ortools/sat:model", ], ) cc_binary( - name = "slitherlink_sat", - srcs = ["slitherlink_sat.cc"], - deps = [ - "//ortools/base", - "//ortools/sat:cp_model", - "//ortools/sat:model", - ], -) + name = "solve", srcs = ["solve.cc"], + deps = ["//ortools/base", + "//ortools/linear_solver", + "//ortools/linear_solver:linear_solver_cc_proto", + "//ortools/lp_data:model_reader", "//ortools/lp_data:mps_reader", + ], ) -cc_binary( - name = "solve", - srcs = ["solve.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - "//ortools/linear_solver:linear_solver_cc_proto", - "//ortools/lp_data:model_reader", - "//ortools/lp_data:mps_reader", - ], -) +cc_binary(name = "sports_scheduling_sat", srcs = ["sports_scheduling_sat.cc"], + deps = ["//ortools/base", + "@com_google_absl//absl/strings", "//ortools/sat:cp_model", + "//ortools/sat:model", + ], ) -cc_binary( - name = "sports_scheduling_sat", - srcs = ["sports_scheduling_sat.cc"], - deps = [ - "//ortools/base", - "@com_google_absl//absl/strings", - "//ortools/sat:cp_model", - "//ortools/sat:model", - ], -) +cc_binary(name = "stigler_diet", srcs = ["stigler_diet.cc"], + deps = ["//ortools/base", "//ortools/linear_solver", ], ) -cc_binary( - name = "stigler_diet", - srcs = ["stigler_diet.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - ], -) +cc_binary(name = "strawberry_fields_with_column_generation", + srcs = ["strawberry_fields_with_column_generation.cc"], + deps = ["//ortools/base", "//ortools/linear_solver", ], ) -cc_binary( - name = "strawberry_fields_with_column_generation", - srcs = ["strawberry_fields_with_column_generation.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - ], -) +cc_binary(name = "uncapacitated_facility_location", + srcs = ["uncapacitated_facility_location.cc"], + deps = ["//ortools/base", "//ortools/linear_solver", ], ) -cc_binary( - name = "uncapacitated_facility_location", - srcs = ["uncapacitated_facility_location.cc"], - deps = [ - "//ortools/base", - "//ortools/linear_solver", - ], -) +cc_binary(name = "variable_intervals_sat", srcs = ["variable_intervals_sat.cc"], + deps = ["//ortools/sat:cp_model", "//ortools/util:time_limit", ], ) - -cc_binary( - name = "variable_intervals_sat", - srcs = ["variable_intervals_sat.cc"], - deps = [ - "//ortools/sat:cp_model", - "//ortools/util:time_limit", - ], -) - -cc_binary( - name = "weighted_tardiness_sat", - srcs = [ - "weighted_tardiness_sat.cc", - ], - deps = [ - "//ortools/base", - "//ortools/base:file", - "//ortools/base:filelineiter", - "@com_google_absl//absl/strings", - "//ortools/sat:cp_model", - "//ortools/sat:cp_model_solver", - "//ortools/sat:disjunctive", - "//ortools/sat:integer", - "//ortools/sat:integer_expr", - "//ortools/sat:intervals", - "//ortools/sat:model", - "//ortools/sat:optimization", - "//ortools/sat:precedences", - "//ortools/sat:sat_solver", - "@com_google_protobuf//:protobuf", - ], -) +cc_binary(name = "weighted_tardiness_sat", + srcs = ["weighted_tardiness_sat.cc", ], + deps = ["//ortools/base", + "//ortools/base:file", "//ortools/base:filelineiter", + "@com_google_absl//absl/strings", "//ortools/sat:cp_model", + "//ortools/sat:cp_model_solver", "//ortools/sat:disjunctive", + "//ortools/sat:integer", "//ortools/sat:integer_expr", + "//ortools/sat:intervals", "//ortools/sat:model", + "//ortools/sat:optimization", "//ortools/sat:precedences", + "//ortools/sat:sat_solver", "@com_google_protobuf//:protobuf", + ], ) diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index 504916de5b..503c82e1d7 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -1,91 +1,66 @@ -if(NOT BUILD_CXX_EXAMPLES) - return() -endif() - -if(APPLE) - set(CMAKE_INSTALL_RPATH - "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") -elseif(UNIX) - set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN") -endif() - -include(GNUInstallDirs) -foreach(EXECUTABLE IN ITEMS - constraint_programming_cp - costas_array_sat - cvrp_disjoint_tw - cvrptw - cvrptw_with_breaks - cvrptw_with_refueling - cvrptw_with_resources - cvrptw_with_stop_times_and_resources - dimacs_assignment - dobble_ls - flow_api - frequency_assignment_problem - golomb_sat - integer_programming - jobshop_sat - linear_assignment_api - linear_programming - linear_solver_protocol_buffers - magic_square_sat - max_flow - min_cost_flow - mps_driver - network_routing_sat - nqueens - pdptw - random_tsp - shift_minimization_sat - slitherlink_sat - solve - sports_scheduling_sat - stigler_diet - strawberry_fields_with_column_generation - uncapacitated_facility_location - variable_intervals_sat - weighted_tardiness_sat) - add_executable(${EXECUTABLE} ${EXECUTABLE}.cc) - target_include_directories(${EXECUTABLE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_features(${EXECUTABLE} PRIVATE cxx_std_17) - target_link_libraries(${EXECUTABLE} PRIVATE ortools::ortools) - install(TARGETS ${EXECUTABLE}) -endforeach() - -foreach(TEST IN ITEMS - costas_array_sat - cvrp_disjoint_tw - cvrptw - #cvrptw_with_breaks # Too long - #cvrptw_with_refueling # Too long - cvrptw_with_resources - cvrptw_with_stop_times_and_resources - #dimacs_assignment - #dobble_ls # Too long - flow_api - #frequency_assignment_problem - golomb_sat - integer_programming - #jobshop_sat - knapsack - linear_assignment_api - linear_programming - linear_solver_protocol_buffers - magic_square_sat - #mps_driver - #network_routing_sat - nqueens - #pdptw - #rcpsp_sat - #shift_minimization_sat - #solve - #sports_scheduling_sat # Too long - #stigler_diet - #strawberry_fields_with_column_generation # Too long - uncapacitated_facility_location - #variable_intervals_sat - #weighted_tardiness_sat - ) - add_test(NAME cxx_${TEST} COMMAND ${TEST}) -endforeach() +if (NOT BUILD_CXX_EXAMPLES) +return () endif() if (APPLE) + set(CMAKE_INSTALL_RPATH + "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") elseif(UNIX) + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN") + endif() include(GNUInstallDirs) foreach( + EXECUTABLE IN ITEMS constraint_programming_cp costas_array_sat cvrp_disjoint_tw + cvrptw cvrptw_with_breaks cvrptw_with_refueling cvrptw_with_resources + cvrptw_with_stop_times_and_resources dimacs_assignment dobble_ls + flow_api frequency_assignment_problem golomb_sat + integer_programming jobshop_sat linear_assignment_api + linear_programming linear_solver_protocol_buffers + magic_square_sat max_flow min_cost_flow mps_driver + network_routing_sat nqueens pdptw random_tsp + shift_minimization_sat slitherlink_sat + solve sports_scheduling_sat stigler_diet + strawberry_fields_with_column_generation + uncapacitated_facility_location + variable_intervals_sat + weighted_tardiness_sat) + add_executable($ { + EXECUTABLE +} $ { + EXECUTABLE +} + .cc) target_include_directories($ { + EXECUTABLE +} PUBLIC $ { + CMAKE_CURRENT_SOURCE_DIR +}) target_compile_features($ { + EXECUTABLE +} PRIVATE cxx_std_17) target_link_libraries($ { + EXECUTABLE +} PRIVATE ortools::ortools) install(TARGETS $ { + EXECUTABLE +}) endforeach() + foreach(TEST IN ITEMS costas_array_sat cvrp_disjoint_tw cvrptw +#cvrptw_with_breaks #Too long +#cvrptw_with_refueling #Too long + cvrptw_with_resources cvrptw_with_stop_times_and_resources +#dimacs_assignment +#dobble_ls #Too long + flow_api +#frequency_assignment_problem + golomb_sat integer_programming +#jobshop_sat + knapsack linear_assignment_api linear_programming + linear_solver_protocol_buffers magic_square_sat +#mps_driver +#network_routing_sat + nqueens +#pdptw +#rcpsp_sat +#shift_minimization_sat +#solve +#sports_scheduling_sat #Too long +#stigler_diet +#strawberry_fields_with_column_generation #Too long + uncapacitated_facility_location +#variable_intervals_sat +#weighted_tardiness_sat + ) add_test(NAME cxx_$ { + TEST +} COMMAND $ { + TEST +}) endforeach() diff --git a/examples/cpp/README.md b/examples/cpp/README.md index f4aa1d0b88..eb129860c7 100644 --- a/examples/cpp/README.md +++ b/examples/cpp/README.md @@ -1,4 +1,4 @@ -# C++ examples +#C++ examples The following examples showcase how to use the different Operations Research libraries. ## Examples list @@ -55,10 +55,9 @@ The following examples showcase how to use the different Operations Research lib - model_util.cc A utility to manipulate model files (.cp) dumped by the solver. -# Execution +#Execution Running the examples will involve building them, then running them. You can run the following command from the **top** directory: ```shell make build SOURCE=examples/cpp/.cc make run SOURCE=examples/cpp/.cc -``` diff --git a/examples/cpp/constraint_programming_cp.cc b/examples/cpp/constraint_programming_cp.cc index ce47960c1c..324acff1f3 100644 --- a/examples/cpp/constraint_programming_cp.cc +++ b/examples/cpp/constraint_programming_cp.cc @@ -23,19 +23,19 @@ void RunConstraintProgrammingExample() { const int64 numVals = 3; // Define decision variables. - IntVar* const x = solver.MakeIntVar(0, numVals - 1, "x"); - IntVar* const y = solver.MakeIntVar(0, numVals - 1, "y"); - IntVar* const z = solver.MakeIntVar(0, numVals - 1, "z"); + IntVar *const x = solver.MakeIntVar(0, numVals - 1, "x"); + IntVar *const y = solver.MakeIntVar(0, numVals - 1, "y"); + IntVar *const z = solver.MakeIntVar(0, numVals - 1, "z"); // Define constraints. - std::vector xyvars = {x, y}; + std::vector xyvars = { x, y }; solver.AddConstraint(solver.MakeAllDifferent(xyvars)); LOG(INFO) << "Number of constraints: " << solver.constraints(); // Create decision builder to search for solutions. - std::vector allvars = {x, y, z}; - DecisionBuilder* const db = solver.MakePhase( + std::vector allvars = { x, y, z }; + DecisionBuilder *const db = solver.MakePhase( allvars, Solver::CHOOSE_FIRST_UNBOUND, Solver::ASSIGN_MIN_VALUE); solver.NewSearch(db); @@ -51,11 +51,11 @@ void RunConstraintProgrammingExample() { LOG(INFO) << "Problem solved in " << solver.wall_time() << "ms"; LOG(INFO) << "Memory usage: " << Solver::MemoryUsage() << " bytes"; } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - FLAGS_logtostderr = 1; + absl::GetFlag(FLAGS_logtostderr) = 1; operations_research::RunConstraintProgrammingExample(); return EXIT_SUCCESS; } diff --git a/examples/cpp/costas_array_sat.cc b/examples/cpp/costas_array_sat.cc index 352858b890..e2dc85dcd6 100644 --- a/examples/cpp/costas_array_sat.cc +++ b/examples/cpp/costas_array_sat.cc @@ -93,8 +93,8 @@ void CostasHard(const int dim) { std::vector vars; Domain domain(1, dim); for (int i = 0; i < dim; ++i) { - vars.push_back( - cp_model.NewIntVar(domain).WithName(absl::StrCat("var_", i))); + vars.push_back(cp_model.NewIntVar(domain) + .WithName(absl::StrCat("var_", i))); } cp_model.AddAllDifferent(vars); @@ -106,15 +106,18 @@ void CostasHard(const int dim) { for (int j = 0; j < dim - i; ++j) { subset.push_back(cp_model.NewIntVar(diff)); - cp_model.AddEquality(LinearExpr::Sum({subset[j], vars[j]}), vars[j + i]); + cp_model.AddEquality(LinearExpr::Sum({ + subset[j], vars[j] + }), + vars[j + i]); } cp_model.AddAllDifferent(subset); } Model model; - if (!FLAGS_params.empty()) { - model.Add(NewSatParameters(FLAGS_params)); + if (!absl::GetFlag(FLAGS_params).empty()) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); } const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model); @@ -142,8 +145,8 @@ void CostasBool(const int dim) { CpModelBuilder cp_model; // create the variables - std::vector> vars(dim); - std::vector> transposed_vars(dim); + std::vector > vars(dim); + std::vector > transposed_vars(dim); for (int i = 0; i < dim; ++i) { for (int j = 0; j < dim; ++j) { const BoolVar var = cp_model.NewBoolVar(); @@ -168,10 +171,12 @@ void CostasBool(const int dim) { const BoolVar neg = cp_model.NewBoolVar(); positive_diffs.push_back(pos); negative_diffs.push_back(neg); - cp_model.AddBoolOr({Not(vars[var][value]), - Not(vars[var + step][value + diff]), pos}); - cp_model.AddBoolOr({Not(vars[var][value + diff]), - Not(vars[var + step][value]), neg}); + cp_model.AddBoolOr({ + Not(vars[var][value]), Not(vars[var + step][value + diff]), pos + }); + cp_model.AddBoolOr({ + Not(vars[var][value + diff]), Not(vars[var + step][value]), neg + }); } } cp_model.AddLessOrEqual(LinearExpr::BooleanSum(positive_diffs), 1); @@ -180,8 +185,8 @@ void CostasBool(const int dim) { } Model model; - if (!FLAGS_params.empty()) { - model.Add(NewSatParameters(FLAGS_params)); + if (!absl::GetFlag(FLAGS_params).empty()) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); } const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model); @@ -213,8 +218,8 @@ void CostasBoolSoft(const int dim) { CpModelBuilder cp_model; // create the variables - std::vector> vars(dim); - std::vector> transposed_vars(dim); + std::vector > vars(dim); + std::vector > transposed_vars(dim); for (int i = 0; i < dim; ++i) { for (int j = 0; j < dim; ++j) { const BoolVar var = cp_model.NewBoolVar(); @@ -240,10 +245,12 @@ void CostasBoolSoft(const int dim) { const BoolVar neg = cp_model.NewBoolVar(); positive_diffs.push_back(pos); negative_diffs.push_back(neg); - cp_model.AddBoolOr({Not(vars[var][value]), - Not(vars[var + step][value + diff]), pos}); - cp_model.AddBoolOr({Not(vars[var][value + diff]), - Not(vars[var + step][value]), neg}); + cp_model.AddBoolOr({ + Not(vars[var][value]), Not(vars[var + step][value + diff]), pos + }); + cp_model.AddBoolOr({ + Not(vars[var][value + diff]), Not(vars[var + step][value]), neg + }); } } const IntVar pos_var = @@ -262,8 +269,8 @@ void CostasBoolSoft(const int dim) { cp_model.Minimize(LinearExpr::Sum(all_violations)); Model model; - if (!FLAGS_params.empty()) { - model.Add(NewSatParameters(FLAGS_params)); + if (!absl::GetFlag(FLAGS_params).empty()) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); } const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model); @@ -290,19 +297,19 @@ void CostasBoolSoft(const int dim) { } } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); int min = 1; int max = 10; - if (FLAGS_minsize != 0) { - min = FLAGS_minsize; + if (absl::GetFlag(FLAGS_minsize) != 0) { + min = absl::GetFlag(FLAGS_minsize); - if (FLAGS_maxsize != 0) { - max = FLAGS_maxsize; + if (absl::GetFlag(FLAGS_maxsize) != 0) { + max = absl::GetFlag(FLAGS_maxsize); } else { max = min; } @@ -310,11 +317,11 @@ int main(int argc, char **argv) { for (int size = min; size <= max; ++size) { LOG(INFO) << "Computing Costas Array for dim = " << size; - if (FLAGS_model == 1) { + if (absl::GetFlag(FLAGS_model) == 1) { operations_research::sat::CostasHard(size); - } else if (FLAGS_model == 2) { + } else if (absl::GetFlag(FLAGS_model) == 2) { operations_research::sat::CostasBool(size); - } else if (FLAGS_model == 3) { + } else if (absl::GetFlag(FLAGS_model) == 3) { operations_research::sat::CostasBoolSoft(size); } } diff --git a/examples/cpp/cvrp_disjoint_tw.cc b/examples/cpp/cvrp_disjoint_tw.cc index aef1eb2f3f..e69079f687 100644 --- a/examples/cpp/cvrp_disjoint_tw.cc +++ b/examples/cpp/cvrp_disjoint_tw.cc @@ -59,75 +59,81 @@ DEFINE_string(routing_search_parameters, "", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); -const char* kTime = "Time"; -const char* kCapacity = "Capacity"; +const char *kTime = "Time"; +const char *kCapacity = "Capacity"; const int64 kMaxNodesPerGroup = 10; const int64 kSameVehicleCost = 1000; -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; - // VRP of size FLAGS_vrp_size. - // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_orders)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_vehicles)) + << "Specify a non-null vehicle fleet size."; + // VRP of size absl::GetFlag(FLAGS_vrp_size). + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_vrp_orders), the starts and + // ends of // the routes are at node 0. const RoutingIndexManager::NodeIndex kDepot(0); - RoutingIndexManager manager(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles, kDepot); + RoutingIndexManager manager(absl::GetFlag(FLAGS_vrp_orders) + 1, + absl::GetFlag(FLAGS_vrp_vehicles), kDepot); RoutingModel routing(manager); // Setting up locations. const int64 kXMax = 100000; const int64 kYMax = 100000; const int64 kSpeed = 10; - LocationContainer locations(kSpeed, FLAGS_vrp_use_deterministic_random_seed); - for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + LocationContainer locations( + kSpeed, absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); + for (int location = 0; location <= absl::GetFlag(FLAGS_vrp_orders); + ++location) { locations.AddRandomLocation(kXMax, kYMax); } - // Setting the cost function. + // Setting the cost function. const int vehicle_cost = routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.ManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return locations.ManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); // Adding capacity dimension constraints. const int64 kVehicleCapacity = 40; const int64 kNullCapacitySlack = 0; RandomDemand demand(manager.num_nodes(), kDepot, - FLAGS_vrp_use_deterministic_random_seed); + absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); demand.Initialize(); routing.AddDimension( routing.RegisterTransitCallback([&demand, &manager](int64 i, int64 j) { - return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kNullCapacitySlack, kVehicleCapacity, - /*fix_start_cumul_to_zero=*/true, kCapacity); + return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kNullCapacitySlack, kVehicleCapacity, /*fix_start_cumul_to_zero=*/ true, + kCapacity); // Adding time dimension constraints. const int64 kTimePerDemandUnit = 300; const int64 kHorizon = 24 * 3600; ServiceTimePlusTransition time( - kTimePerDemandUnit, - [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { - return demand.Demand(i, j); - }, + kTimePerDemandUnit, [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { + return demand.Demand(i, j); + }, [&locations](RoutingNodeIndex i, RoutingNodeIndex j) { - return locations.ManhattanTime(i, j); - }); + return locations.ManhattanTime(i, j); + }); routing.AddDimension( routing.RegisterTransitCallback([&time, &manager](int64 i, int64 j) { - return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/false, kTime); - const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/ false, kTime); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie(kTime); // Adding disjoint time windows. - Solver* solver = routing.solver(); - ACMRandom randomizer(GetSeed(FLAGS_vrp_use_deterministic_random_seed)); + Solver *solver = routing.solver(); + ACMRandom randomizer( + GetSeed(absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed))); for (int order = 1; order < manager.num_nodes(); ++order) { - std::vector forbid_points(2 * FLAGS_vrp_windows, 0); + std::vector forbid_points(2 * absl::GetFlag(FLAGS_vrp_windows), 0); for (int i = 0; i < forbid_points.size(); ++i) { forbid_points[i] = randomizer.Uniform(kHorizon); } @@ -153,7 +159,7 @@ int main(int argc, char** argv) { } // Adding same vehicle constraint costs for consecutive nodes. - if (FLAGS_vrp_use_same_vehicle_costs) { + if (absl::GetFlag(FLAGS_vrp_use_same_vehicle_costs)) { std::vector group; for (RoutingIndexManager::NodeIndex order = kFirstNodeAfterDepot; order < manager.num_nodes(); ++order) { @@ -171,10 +177,11 @@ int main(int argc, char** argv) { // Solve, returns a solution if any (owned by RoutingModel). RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); - const Assignment* solution = routing.SolveWithParameters(parameters); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { - DisplayPlan(manager, routing, *solution, FLAGS_vrp_use_same_vehicle_costs, + DisplayPlan(manager, routing, *solution, + absl::GetFlag(FLAGS_vrp_use_same_vehicle_costs), kMaxNodesPerGroup, kSameVehicleCost, routing.GetDimensionOrDie(kCapacity), routing.GetDimensionOrDie(kTime)); diff --git a/examples/cpp/cvrptw.cc b/examples/cpp/cvrptw.cc index 9696115f7e..b5fe03435d 100644 --- a/examples/cpp/cvrptw.cc +++ b/examples/cpp/cvrptw.cc @@ -57,72 +57,78 @@ DEFINE_string(routing_search_parameters, "", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); -const char* kTime = "Time"; -const char* kCapacity = "Capacity"; +const char *kTime = "Time"; +const char *kCapacity = "Capacity"; const int64 kMaxNodesPerGroup = 10; const int64 kSameVehicleCost = 1000; -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; - // VRP of size FLAGS_vrp_size. - // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_orders)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_vehicles)) + << "Specify a non-null vehicle fleet size."; + // VRP of size absl::GetFlag(FLAGS_vrp_size). + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_vrp_orders), the starts and + // ends of // the routes are at node 0. const RoutingIndexManager::NodeIndex kDepot(0); - RoutingIndexManager manager(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles, kDepot); + RoutingIndexManager manager(absl::GetFlag(FLAGS_vrp_orders) + 1, + absl::GetFlag(FLAGS_vrp_vehicles), kDepot); RoutingModel routing(manager); // Setting up locations. const int64 kXMax = 100000; const int64 kYMax = 100000; const int64 kSpeed = 10; - LocationContainer locations(kSpeed, FLAGS_vrp_use_deterministic_random_seed); - for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + LocationContainer locations( + kSpeed, absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); + for (int location = 0; location <= absl::GetFlag(FLAGS_vrp_orders); + ++location) { locations.AddRandomLocation(kXMax, kYMax); } - // Setting the cost function. + // Setting the cost function. const int vehicle_cost = routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.ManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return locations.ManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); // Adding capacity dimension constraints. const int64 kVehicleCapacity = 40; const int64 kNullCapacitySlack = 0; RandomDemand demand(manager.num_nodes(), kDepot, - FLAGS_vrp_use_deterministic_random_seed); + absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); demand.Initialize(); routing.AddDimension( routing.RegisterTransitCallback([&demand, &manager](int64 i, int64 j) { - return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kNullCapacitySlack, kVehicleCapacity, - /*fix_start_cumul_to_zero=*/true, kCapacity); + return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kNullCapacitySlack, kVehicleCapacity, /*fix_start_cumul_to_zero=*/ true, + kCapacity); // Adding time dimension constraints. const int64 kTimePerDemandUnit = 300; const int64 kHorizon = 24 * 3600; ServiceTimePlusTransition time( - kTimePerDemandUnit, - [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { - return demand.Demand(i, j); - }, + kTimePerDemandUnit, [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { + return demand.Demand(i, j); + }, [&locations](RoutingNodeIndex i, RoutingNodeIndex j) { - return locations.ManhattanTime(i, j); - }); + return locations.ManhattanTime(i, j); + }); routing.AddDimension( routing.RegisterTransitCallback([&time, &manager](int64 i, int64 j) { - return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/true, kTime); - const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/ true, kTime); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie(kTime); // Adding time windows. - ACMRandom randomizer(GetSeed(FLAGS_vrp_use_deterministic_random_seed)); + ACMRandom randomizer( + GetSeed(absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed))); const int64 kTWDuration = 5 * 3600; for (int order = 1; order < manager.num_nodes(); ++order) { const int64 start = randomizer.Uniform(kHorizon - kTWDuration); @@ -139,7 +145,7 @@ int main(int argc, char** argv) { } // Adding same vehicle constraint costs for consecutive nodes. - if (FLAGS_vrp_use_same_vehicle_costs) { + if (absl::GetFlag(FLAGS_vrp_use_same_vehicle_costs)) { std::vector group; for (RoutingIndexManager::NodeIndex order = kFirstNodeAfterDepot; order < manager.num_nodes(); ++order) { @@ -157,10 +163,11 @@ int main(int argc, char** argv) { // Solve, returns a solution if any (owned by RoutingModel). RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); - const Assignment* solution = routing.SolveWithParameters(parameters); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { - DisplayPlan(manager, routing, *solution, FLAGS_vrp_use_same_vehicle_costs, + DisplayPlan(manager, routing, *solution, + absl::GetFlag(FLAGS_vrp_use_same_vehicle_costs), kMaxNodesPerGroup, kSameVehicleCost, routing.GetDimensionOrDie(kCapacity), routing.GetDimensionOrDie(kTime)); diff --git a/examples/cpp/cvrptw_lib.h b/examples/cpp/cvrptw_lib.h index c6c14ca721..35e039fe06 100644 --- a/examples/cpp/cvrptw_lib.h +++ b/examples/cpp/cvrptw_lib.h @@ -35,7 +35,7 @@ int32 GetSeed(bool deterministic); // Location container, contains positions of orders and can be used to obtain // Manhattan distances/times between locations. class LocationContainer { - public: +public: LocationContainer(int64 speed, bool use_deterministic_seed); void AddLocation(int64 x, int64 y) { locations_.push_back(Location(x, y)); } void AddRandomLocation(int64 x_max, int64 y_max); @@ -51,15 +51,15 @@ class LocationContainer { RoutingIndexManager::NodeIndex node2) const; int64 SameLocationFromIndex(int64 node1, int64 node2) const; - private: +private: class Location { - public: + public: Location(); Location(int64 x, int64 y); - int64 DistanceTo(const Location& location) const; - bool IsAtSameLocation(const Location& location) const; + int64 DistanceTo(const Location &location) const; + bool IsAtSameLocation(const Location &location) const; - private: + private: static int64 Abs(int64 value); int64 x_; @@ -73,14 +73,14 @@ class LocationContainer { // Random demand. class RandomDemand { - public: +public: RandomDemand(int size, RoutingIndexManager::NodeIndex depot, bool use_deterministic_seed); void Initialize(); int64 Demand(RoutingIndexManager::NodeIndex from, RoutingIndexManager::NodeIndex to) const; - private: +private: std::unique_ptr demand_; const int size_; const RoutingIndexManager::NodeIndex depot_; @@ -89,14 +89,14 @@ class RandomDemand { // Service time (proportional to demand) + transition time callback. class ServiceTimePlusTransition { - public: +public: ServiceTimePlusTransition(int64 time_per_demand_unit, RoutingNodeEvaluator2 demand, RoutingNodeEvaluator2 transition_time); int64 Compute(RoutingIndexManager::NodeIndex from, RoutingIndexManager::NodeIndex to) const; - private: +private: const int64 time_per_demand_unit_; RoutingNodeEvaluator2 demand_; RoutingNodeEvaluator2 transition_time_; @@ -104,29 +104,30 @@ class ServiceTimePlusTransition { // Stop service time + transition time callback. class StopServiceTimePlusTransition { - public: +public: StopServiceTimePlusTransition(int64 stop_time, - const LocationContainer& location_container, + const LocationContainer &location_container, RoutingNodeEvaluator2 transition_time); int64 Compute(RoutingIndexManager::NodeIndex from, RoutingIndexManager::NodeIndex to) const; - private: +private: const int64 stop_time_; - const LocationContainer& location_container_; + const LocationContainer &location_container_; RoutingNodeEvaluator2 demand_; RoutingNodeEvaluator2 transition_time_; }; // Route plan displayer. // TODO(user): Move the display code to the routing library. -void DisplayPlan( - const operations_research::RoutingIndexManager& manager, - const operations_research::RoutingModel& routing, - const operations_research::Assignment& plan, bool use_same_vehicle_costs, - int64 max_nodes_per_group, int64 same_vehicle_cost, - const operations_research::RoutingDimension& capacity_dimension, - const operations_research::RoutingDimension& time_dimension); +void + DisplayPlan(const operations_research::RoutingIndexManager &manager, + const operations_research::RoutingModel &routing, + const operations_research::Assignment &plan, + bool use_same_vehicle_costs, int64 max_nodes_per_group, + int64 same_vehicle_cost, + const operations_research::RoutingDimension &capacity_dimension, + const operations_research::RoutingDimension &time_dimension); using NodeIndex = RoutingIndexManager::NodeIndex; @@ -186,12 +187,12 @@ LocationContainer::Location::Location() : x_(0), y_(0) {} LocationContainer::Location::Location(int64 x, int64 y) : x_(x), y_(y) {} -int64 LocationContainer::Location::DistanceTo(const Location& location) const { +int64 LocationContainer::Location::DistanceTo(const Location &location) const { return Abs(x_ - location.x_) + Abs(y_ - location.y_); } -bool LocationContainer::Location::IsAtSameLocation( - const Location& location) const { +bool +LocationContainer::Location::IsAtSameLocation(const Location &location) const { return x_ == location.x_ && y_ == location.y_; } @@ -201,8 +202,7 @@ int64 LocationContainer::Location::Abs(int64 value) { RandomDemand::RandomDemand(int size, NodeIndex depot, bool use_deterministic_seed) - : size_(size), - depot_(depot), + : size_(size), depot_(depot), use_deterministic_seed_(use_deterministic_seed) { CHECK_LT(0, size_); } @@ -229,8 +229,7 @@ int64 RandomDemand::Demand(NodeIndex from, NodeIndex /*to*/) const { ServiceTimePlusTransition::ServiceTimePlusTransition( int64 time_per_demand_unit, RoutingNodeEvaluator2 demand, RoutingNodeEvaluator2 transition_time) - : time_per_demand_unit_(time_per_demand_unit), - demand_(std::move(demand)), + : time_per_demand_unit_(time_per_demand_unit), demand_(std::move(demand)), transition_time_(std::move(transition_time)) {} int64 ServiceTimePlusTransition::Compute(NodeIndex from, NodeIndex to) const { @@ -238,10 +237,9 @@ int64 ServiceTimePlusTransition::Compute(NodeIndex from, NodeIndex to) const { } StopServiceTimePlusTransition::StopServiceTimePlusTransition( - int64 stop_time, const LocationContainer& location_container, + int64 stop_time, const LocationContainer &location_container, RoutingNodeEvaluator2 transition_time) - : stop_time_(stop_time), - location_container_(location_container), + : stop_time_(stop_time), location_container_(location_container), transition_time_(std::move(transition_time)) {} int64 StopServiceTimePlusTransition::Compute(NodeIndex from, @@ -251,19 +249,21 @@ int64 StopServiceTimePlusTransition::Compute(NodeIndex from, : stop_time_ + transition_time_(from, to); } -void DisplayPlan( - const RoutingIndexManager& manager, const RoutingModel& routing, - const operations_research::Assignment& plan, bool use_same_vehicle_costs, - int64 max_nodes_per_group, int64 same_vehicle_cost, - const operations_research::RoutingDimension& capacity_dimension, - const operations_research::RoutingDimension& time_dimension) { +void +DisplayPlan(const RoutingIndexManager &manager, const RoutingModel &routing, + const operations_research::Assignment &plan, + bool use_same_vehicle_costs, int64 max_nodes_per_group, + int64 same_vehicle_cost, + const operations_research::RoutingDimension &capacity_dimension, + const operations_research::RoutingDimension &time_dimension) { // Display plan cost. std::string plan_output = absl::StrFormat("Cost %d\n", plan.ObjectiveValue()); // Display dropped orders. std::string dropped; for (int64 order = 0; order < routing.Size(); ++order) { - if (routing.IsStart(order) || routing.IsEnd(order)) continue; + if (routing.IsStart(order) || routing.IsEnd(order)) + continue; if (plan.Value(routing.NextVar(order)) == order) { if (dropped.empty()) { absl::StrAppendFormat(&dropped, " %d", @@ -283,7 +283,8 @@ void DisplayPlan( int64 group_same_vehicle_cost = 0; std::set visited; for (int64 order = 0; order < routing.Size(); ++order) { - if (routing.IsStart(order) || routing.IsEnd(order)) continue; + if (routing.IsStart(order) || routing.IsEnd(order)) + continue; ++group_size; visited.insert(plan.Value(routing.VehicleVar(order))); if (group_size == max_nodes_per_group) { @@ -309,11 +310,11 @@ void DisplayPlan( plan_output += "Empty\n"; } else { while (true) { - operations_research::IntVar* const load_var = + operations_research::IntVar *const load_var = capacity_dimension.CumulVar(order); - operations_research::IntVar* const time_var = + operations_research::IntVar *const time_var = time_dimension.CumulVar(order); - operations_research::IntVar* const slack_var = + operations_research::IntVar *const slack_var = routing.IsEnd(order) ? nullptr : time_dimension.SlackVar(order); if (slack_var != nullptr && plan.Contains(slack_var)) { absl::StrAppendFormat( @@ -327,7 +328,8 @@ void DisplayPlan( plan.Value(load_var), plan.Min(time_var), plan.Max(time_var)); } - if (routing.IsEnd(order)) break; + if (routing.IsEnd(order)) + break; plan_output += " -> "; order = plan.Value(routing.NextVar(order)); } @@ -336,6 +338,6 @@ void DisplayPlan( } LOG(INFO) << plan_output; } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_EXAMPLES_CVRPTW_LIB_H_ +#endif // OR_TOOLS_EXAMPLES_CVRPTW_LIB_H_ diff --git a/examples/cpp/cvrptw_with_breaks.cc b/examples/cpp/cvrptw_with_breaks.cc index 0c5ac3af21..e3c4248335 100644 --- a/examples/cpp/cvrptw_with_breaks.cc +++ b/examples/cpp/cvrptw_with_breaks.cc @@ -64,22 +64,26 @@ DEFINE_string(routing_search_parameters, "", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); -const char* kTime = "Time"; -const char* kCapacity = "Capacity"; +const char *kTime = "Time"; +const char *kCapacity = "Capacity"; -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; - // VRP of size FLAGS_vrp_size. - // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_orders)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_vehicles)) + << "Specify a non-null vehicle fleet size."; + // VRP of size absl::GetFlag(FLAGS_vrp_size). + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_vrp_orders), the starts and + // ends of // the routes are at node 0. const RoutingIndexManager::NodeIndex kDepot(0); - RoutingIndexManager manager(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles, kDepot); + RoutingIndexManager manager(absl::GetFlag(FLAGS_vrp_orders) + 1, + absl::GetFlag(FLAGS_vrp_vehicles), kDepot); RoutingModel routing(manager); RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); parameters.set_first_solution_strategy( FirstSolutionStrategy::PARALLEL_CHEAPEST_INSERTION); @@ -87,52 +91,54 @@ int main(int argc, char** argv) { const int64 kXMax = 100000; const int64 kYMax = 100000; const int64 kSpeed = 10; - LocationContainer locations(kSpeed, FLAGS_vrp_use_deterministic_random_seed); - for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + LocationContainer locations( + kSpeed, absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); + for (int location = 0; location <= absl::GetFlag(FLAGS_vrp_orders); + ++location) { locations.AddRandomLocation(kXMax, kYMax); } - // Setting the cost function. + // Setting the cost function. const int vehicle_cost = routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.ManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return locations.ManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); // Adding capacity dimension constraints. const int64 kVehicleCapacity = 40; const int64 kNullCapacitySlack = 0; RandomDemand demand(manager.num_nodes(), kDepot, - FLAGS_vrp_use_deterministic_random_seed); + absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); demand.Initialize(); routing.AddDimension( routing.RegisterTransitCallback([&demand, &manager](int64 i, int64 j) { - return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kNullCapacitySlack, kVehicleCapacity, - /*fix_start_cumul_to_zero=*/true, kCapacity); + return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kNullCapacitySlack, kVehicleCapacity, /*fix_start_cumul_to_zero=*/ true, + kCapacity); // Adding time dimension constraints. const int64 kTimePerDemandUnit = 300; const int64 kHorizon = 24 * 3600; ServiceTimePlusTransition time( - kTimePerDemandUnit, - [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { - return demand.Demand(i, j); - }, + kTimePerDemandUnit, [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { + return demand.Demand(i, j); + }, [&locations](RoutingNodeIndex i, RoutingNodeIndex j) { - return locations.ManhattanTime(i, j); - }); + return locations.ManhattanTime(i, j); + }); routing.AddDimension( routing.RegisterTransitCallback([&time, &manager](int64 i, int64 j) { - return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/false, kTime); - RoutingDimension* const time_dimension = routing.GetMutableDimension(kTime); + return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/ false, kTime); + RoutingDimension *const time_dimension = routing.GetMutableDimension(kTime); // Adding time windows. - ACMRandom randomizer(GetSeed(FLAGS_vrp_use_deterministic_random_seed)); + ACMRandom randomizer( + GetSeed(absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed))); const int64 kTWDuration = 5 * 3600; for (int order = 1; order < manager.num_nodes(); ++order) { const int64 start = randomizer.Uniform(kHorizon - kTWDuration); @@ -144,7 +150,7 @@ int main(int argc, char** argv) { for (int i = 0; i < routing.Size(); ++i) { routing.AddVariableMinimizedByFinalizer(time_dimension->CumulVar(i)); } - for (int j = 0; j < FLAGS_vrp_vehicles; ++j) { + for (int j = 0; j < absl::GetFlag(FLAGS_vrp_vehicles); ++j) { routing.AddVariableMinimizedByFinalizer( time_dimension->CumulVar(routing.Start(j))); routing.AddVariableMinimizedByFinalizer( @@ -165,15 +171,17 @@ int main(int argc, char** argv) { service_times[node] = kTimePerDemandUnit * demand.Demand(index, index); } } - const std::vector> break_data = { - {/*start_min*/ 11, /*start_max*/ 13, /*duration*/ 2400}, - {/*start_min*/ 10, /*start_max*/ 15, /*duration*/ 1800}, - {/*start_min*/ 10, /*start_max*/ 15, /*duration*/ 1800}}; - Solver* const solver = routing.solver(); - for (int vehicle = 0; vehicle < FLAGS_vrp_vehicles; ++vehicle) { - std::vector breaks; + const std::vector > break_data = { + { /*start_min*/ 11, /*start_max*/ 13, /*duration*/ 2400 }, + { /*start_min*/ 10, /*start_max*/ 15, /*duration*/ 1800 }, + { /*start_min*/ 10, /*start_max*/ 15, /*duration*/ 1800 } + }; + Solver *const solver = routing.solver(); + for (int vehicle = 0; vehicle < absl::GetFlag(FLAGS_vrp_vehicles); + ++vehicle) { + std::vector breaks; for (int i = 0; i < break_data.size(); ++i) { - IntervalVar* const break_interval = solver->MakeFixedDurationIntervalVar( + IntervalVar *const break_interval = solver->MakeFixedDurationIntervalVar( break_data[i][0] * 3600, break_data[i][1] * 3600, break_data[i][2], true, absl::StrCat("Break ", i, " on vehicle ", vehicle)); breaks.push_back(break_interval); @@ -202,10 +210,10 @@ int main(int argc, char** argv) { } // Solve, returns a solution if any (owned by RoutingModel). - const Assignment* solution = routing.SolveWithParameters(parameters); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { LOG(INFO) << "Breaks: "; - for (const auto& break_interval : + for (const auto &break_interval : solution->IntervalVarContainer().elements()) { if (break_interval.PerformedValue() == 1) { LOG(INFO) << break_interval.Var()->name() << " " diff --git a/examples/cpp/cvrptw_with_refueling.cc b/examples/cpp/cvrptw_with_refueling.cc index 9eb02136d0..97021f346a 100644 --- a/examples/cpp/cvrptw_with_refueling.cc +++ b/examples/cpp/cvrptw_with_refueling.cc @@ -53,9 +53,9 @@ DEFINE_string(routing_search_parameters, "", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); -const char* kTime = "Time"; -const char* kCapacity = "Capacity"; -const char* kFuel = "Fuel"; +const char *kTime = "Time"; +const char *kCapacity = "Capacity"; +const char *kFuel = "Fuel"; // Returns true if node is a refueling node (based on node / refuel node ratio). bool IsRefuelNode(int64 node) { @@ -63,66 +63,72 @@ bool IsRefuelNode(int64 node) { return (node % kRefuelNodeRatio == 0); } -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; - // VRP of size FLAGS_vrp_size. - // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_orders)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_vehicles)) + << "Specify a non-null vehicle fleet size."; + // VRP of size absl::GetFlag(FLAGS_vrp_size). + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_vrp_orders), the starts and + // ends of // the routes are at node 0. const RoutingIndexManager::NodeIndex kDepot(0); - RoutingIndexManager manager(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles, kDepot); + RoutingIndexManager manager(absl::GetFlag(FLAGS_vrp_orders) + 1, + absl::GetFlag(FLAGS_vrp_vehicles), kDepot); RoutingModel routing(manager); // Setting up locations. const int64 kXMax = 100000; const int64 kYMax = 100000; const int64 kSpeed = 10; - LocationContainer locations(kSpeed, FLAGS_vrp_use_deterministic_random_seed); - for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + LocationContainer locations( + kSpeed, absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); + for (int location = 0; location <= absl::GetFlag(FLAGS_vrp_orders); + ++location) { locations.AddRandomLocation(kXMax, kYMax); } - // Setting the cost function. + // Setting the cost function. const int vehicle_cost = routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.ManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return locations.ManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); // Adding capacity dimension constraints. const int64 kVehicleCapacity = 40; const int64 kNullCapacitySlack = 0; RandomDemand demand(manager.num_nodes(), kDepot, - FLAGS_vrp_use_deterministic_random_seed); + absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); demand.Initialize(); routing.AddDimension( routing.RegisterTransitCallback([&demand, &manager](int64 i, int64 j) { - return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kNullCapacitySlack, kVehicleCapacity, - /*fix_start_cumul_to_zero=*/true, kCapacity); + return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kNullCapacitySlack, kVehicleCapacity, /*fix_start_cumul_to_zero=*/ true, + kCapacity); // Adding time dimension constraints. const int64 kTimePerDemandUnit = 300; const int64 kHorizon = 24 * 3600; ServiceTimePlusTransition time( - kTimePerDemandUnit, - [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { - return demand.Demand(i, j); - }, + kTimePerDemandUnit, [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { + return demand.Demand(i, j); + }, [&locations](RoutingNodeIndex i, RoutingNodeIndex j) { - return locations.ManhattanTime(i, j); - }); + return locations.ManhattanTime(i, j); + }); routing.AddDimension( routing.RegisterTransitCallback([&time, &manager](int64 i, int64 j) { - return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/true, kTime); - const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/ true, kTime); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie(kTime); // Adding time windows. - ACMRandom randomizer(GetSeed(FLAGS_vrp_use_deterministic_random_seed)); + ACMRandom randomizer( + GetSeed(absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed))); const int64 kTWDuration = 5 * 3600; for (int order = 1; order < manager.num_nodes(); ++order) { if (!IsRefuelNode(order)) { @@ -137,11 +143,11 @@ int main(int argc, char** argv) { const int64 kFuelCapacity = kXMax + kYMax; routing.AddDimension( routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.NegManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }), - kFuelCapacity, kFuelCapacity, /*fix_start_cumul_to_zero=*/false, kFuel); - const RoutingDimension& fuel_dimension = routing.GetDimensionOrDie(kFuel); + return locations.NegManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }), + kFuelCapacity, kFuelCapacity, /*fix_start_cumul_to_zero=*/ false, kFuel); + const RoutingDimension &fuel_dimension = routing.GetDimensionOrDie(kFuel); for (int order = 0; order < routing.Size(); ++order) { // Only let slack free for refueling nodes. if (!IsRefuelNode(order) || routing.IsStart(order)) { @@ -163,11 +169,11 @@ int main(int argc, char** argv) { // Solve, returns a solution if any (owned by RoutingModel). RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); - const Assignment* solution = routing.SolveWithParameters(parameters); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { - DisplayPlan(manager, routing, *solution, /*use_same_vehicle_costs=*/false, - /*max_nodes_per_group=*/0, /*same_vehicle_cost=*/0, + DisplayPlan(manager, routing, *solution, /*use_same_vehicle_costs=*/ false, + /*max_nodes_per_group=*/ 0, /*same_vehicle_cost=*/ 0, routing.GetDimensionOrDie(kCapacity), routing.GetDimensionOrDie(kTime)); } else { diff --git a/examples/cpp/cvrptw_with_resources.cc b/examples/cpp/cvrptw_with_resources.cc index 93bc87c898..09b378c9dd 100644 --- a/examples/cpp/cvrptw_with_resources.cc +++ b/examples/cpp/cvrptw_with_resources.cc @@ -58,70 +58,76 @@ DEFINE_string(routing_search_parameters, "", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); -const char* kTime = "Time"; -const char* kCapacity = "Capacity"; +const char *kTime = "Time"; +const char *kCapacity = "Capacity"; -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; - // VRP of size FLAGS_vrp_size. - // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_orders)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_vehicles)) + << "Specify a non-null vehicle fleet size."; + // VRP of size absl::GetFlag(FLAGS_vrp_size). + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_vrp_orders), the starts and + // ends of // the routes are at node 0. const RoutingIndexManager::NodeIndex kDepot(0); - RoutingIndexManager manager(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles, kDepot); + RoutingIndexManager manager(absl::GetFlag(FLAGS_vrp_orders) + 1, + absl::GetFlag(FLAGS_vrp_vehicles), kDepot); RoutingModel routing(manager); // Setting up locations. const int64 kXMax = 100000; const int64 kYMax = 100000; const int64 kSpeed = 10; - LocationContainer locations(kSpeed, FLAGS_vrp_use_deterministic_random_seed); - for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + LocationContainer locations( + kSpeed, absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); + for (int location = 0; location <= absl::GetFlag(FLAGS_vrp_orders); + ++location) { locations.AddRandomLocation(kXMax, kYMax); } - // Setting the cost function. + // Setting the cost function. const int vehicle_cost = routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.ManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return locations.ManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); // Adding capacity dimension constraints. const int64 kVehicleCapacity = 40; const int64 kNullCapacitySlack = 0; RandomDemand demand(manager.num_nodes(), kDepot, - FLAGS_vrp_use_deterministic_random_seed); + absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); demand.Initialize(); routing.AddDimension( routing.RegisterTransitCallback([&demand, &manager](int64 i, int64 j) { - return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kNullCapacitySlack, kVehicleCapacity, - /*fix_start_cumul_to_zero=*/true, kCapacity); + return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kNullCapacitySlack, kVehicleCapacity, /*fix_start_cumul_to_zero=*/ true, + kCapacity); // Adding time dimension constraints. const int64 kTimePerDemandUnit = 300; const int64 kHorizon = 24 * 3600; ServiceTimePlusTransition time( - kTimePerDemandUnit, - [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { - return demand.Demand(i, j); - }, + kTimePerDemandUnit, [&demand](RoutingNodeIndex i, RoutingNodeIndex j) { + return demand.Demand(i, j); + }, [&locations](RoutingNodeIndex i, RoutingNodeIndex j) { - return locations.ManhattanTime(i, j); - }); + return locations.ManhattanTime(i, j); + }); routing.AddDimension( routing.RegisterTransitCallback([&time, &manager](int64 i, int64 j) { - return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/false, kTime); - const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/ false, kTime); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie(kTime); // Adding time windows. - ACMRandom randomizer(GetSeed(FLAGS_vrp_use_deterministic_random_seed)); + ACMRandom randomizer( + GetSeed(absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed))); const int64 kTWDuration = 5 * 3600; for (int order = 1; order < manager.num_nodes(); ++order) { const int64 start = randomizer.Uniform(kHorizon - kTWDuration); @@ -130,15 +136,15 @@ int main(int argc, char** argv) { // Adding resource constraints at the depot (start and end location of // routes). - std::vector start_end_times; - for (int i = 0; i < FLAGS_vrp_vehicles; ++i) { + std::vector start_end_times; + for (int i = 0; i < absl::GetFlag(FLAGS_vrp_vehicles); ++i) { start_end_times.push_back(time_dimension.CumulVar(routing.End(i))); start_end_times.push_back(time_dimension.CumulVar(routing.Start(i))); } // Build corresponding time intervals. const int64 kVehicleSetup = 180; - Solver* const solver = routing.solver(); - std::vector intervals; + Solver *const solver = routing.solver(); + std::vector intervals; solver->MakeFixedDurationIntervalVarArray(start_end_times, kVehicleSetup, "depot_interval", &intervals); // Constrain the number of maximum simultaneous intervals at depot. @@ -163,11 +169,11 @@ int main(int argc, char** argv) { // Solve, returns a solution if any (owned by RoutingModel). RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); - const Assignment* solution = routing.SolveWithParameters(parameters); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { - DisplayPlan(manager, routing, *solution, /*use_same_vehicle_costs=*/false, - /*max_nodes_per_group=*/0, /*same_vehicle_cost=*/0, + DisplayPlan(manager, routing, *solution, /*use_same_vehicle_costs=*/ false, + /*max_nodes_per_group=*/ 0, /*same_vehicle_cost=*/ 0, routing.GetDimensionOrDie(kCapacity), routing.GetDimensionOrDie(kTime)); } else { diff --git a/examples/cpp/cvrptw_with_stop_times_and_resources.cc b/examples/cpp/cvrptw_with_stop_times_and_resources.cc index 1020afc992..af767b4be7 100644 --- a/examples/cpp/cvrptw_with_stop_times_and_resources.cc +++ b/examples/cpp/cvrptw_with_stop_times_and_resources.cc @@ -58,52 +58,58 @@ DEFINE_string(routing_search_parameters, "", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); -const char* kTime = "Time"; -const char* kCapacity = "Capacity"; +const char *kTime = "Time"; +const char *kCapacity = "Capacity"; -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_vrp_stops) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_orders_per_stop) + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_stops)) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; - const int vrp_orders = FLAGS_vrp_stops * FLAGS_vrp_orders_per_stop; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_orders_per_stop)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_vrp_vehicles)) + << "Specify a non-null vehicle fleet size."; + const int vrp_orders = + absl::GetFlag(FLAGS_vrp_stops) * absl::GetFlag(FLAGS_vrp_orders_per_stop); // Nodes are indexed from 0 to vrp_orders, the starts and ends of the routes // are at node 0. const RoutingIndexManager::NodeIndex kDepot(0); - RoutingIndexManager manager(vrp_orders + 1, FLAGS_vrp_vehicles, kDepot); + RoutingIndexManager manager(vrp_orders + 1, absl::GetFlag(FLAGS_vrp_vehicles), + kDepot); RoutingModel routing(manager); // Setting up locations. const int64 kXMax = 100000; const int64 kYMax = 100000; const int64 kSpeed = 10; - LocationContainer locations(kSpeed, FLAGS_vrp_use_deterministic_random_seed); - for (int stop = 0; stop <= FLAGS_vrp_stops; ++stop) { - const int num_orders = stop == 0 ? 1 : FLAGS_vrp_orders_per_stop; + LocationContainer locations( + kSpeed, absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); + for (int stop = 0; stop <= absl::GetFlag(FLAGS_vrp_stops); ++stop) { + const int num_orders = + stop == 0 ? 1 : absl::GetFlag(FLAGS_vrp_orders_per_stop); locations.AddRandomLocation(kXMax, kYMax, num_orders); } - // Setting the cost function. + // Setting the cost function. const int vehicle_cost = routing.RegisterTransitCallback([&locations, &manager](int64 i, int64 j) { - return locations.ManhattanDistance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return locations.ManhattanDistance(manager.IndexToNode(i), + manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); // Adding capacity dimension constraints. const int64 kVehicleCapacity = 40; const int64 kNullCapacitySlack = 0; RandomDemand demand(manager.num_nodes(), kDepot, - FLAGS_vrp_use_deterministic_random_seed); + absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed)); demand.Initialize(); routing.AddDimension( routing.RegisterTransitCallback([&demand, &manager](int64 i, int64 j) { - return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kNullCapacitySlack, kVehicleCapacity, - /*fix_start_cumul_to_zero=*/true, kCapacity); + return demand.Demand(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kNullCapacitySlack, kVehicleCapacity, /*fix_start_cumul_to_zero=*/ true, + kCapacity); // Adding time dimension constraints. const int64 kStopTime = 300; @@ -111,55 +117,55 @@ int main(int argc, char** argv) { StopServiceTimePlusTransition time( kStopTime, locations, [&locations](RoutingNodeIndex i, RoutingNodeIndex j) { - return locations.ManhattanTime(i, j); - }); + return locations.ManhattanTime(i, j); + }); routing.AddDimension( routing.RegisterTransitCallback([&time, &manager](int64 i, int64 j) { - return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); - }), - kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/false, kTime); - const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + return time.Compute(manager.IndexToNode(i), manager.IndexToNode(j)); + }), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/ false, kTime); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie(kTime); // Adding time windows, for the sake of simplicty same for each stop. - ACMRandom randomizer(GetSeed(FLAGS_vrp_use_deterministic_random_seed)); + ACMRandom randomizer( + GetSeed(absl::GetFlag(FLAGS_vrp_use_deterministic_random_seed))); const int64 kTWDuration = 5 * 3600; - for (int stop = 0; stop < FLAGS_vrp_stops; ++stop) { + for (int stop = 0; stop < absl::GetFlag(FLAGS_vrp_stops); ++stop) { const int64 start = randomizer.Uniform(kHorizon - kTWDuration); - for (int stop_order = 0; stop_order < FLAGS_vrp_orders_per_stop; - ++stop_order) { - const int order = stop * FLAGS_vrp_orders_per_stop + stop_order + 1; + for (int stop_order = 0; + stop_order < absl::GetFlag(FLAGS_vrp_orders_per_stop); ++stop_order) { + const int order = + stop * absl::GetFlag(FLAGS_vrp_orders_per_stop) + stop_order + 1; time_dimension.CumulVar(order)->SetRange(start, start + kTWDuration); } } // Adding resource constraints at order locations. - Solver* const solver = routing.solver(); - std::vector intervals; - for (int stop = 0; stop < FLAGS_vrp_stops; ++stop) { - std::vector stop_intervals; - for (int stop_order = 0; stop_order < FLAGS_vrp_orders_per_stop; - ++stop_order) { - const int order = stop * FLAGS_vrp_orders_per_stop + stop_order + 1; - IntervalVar* const interval = solver->MakeFixedDurationIntervalVar( + Solver *const solver = routing.solver(); + std::vector intervals; + for (int stop = 0; stop < absl::GetFlag(FLAGS_vrp_stops); ++stop) { + std::vector stop_intervals; + for (int stop_order = 0; + stop_order < absl::GetFlag(FLAGS_vrp_orders_per_stop); ++stop_order) { + const int order = + stop * absl::GetFlag(FLAGS_vrp_orders_per_stop) + stop_order + 1; + IntervalVar *const interval = solver->MakeFixedDurationIntervalVar( 0, kHorizon, kStopTime, true, absl::StrCat("Order", order)); intervals.push_back(interval); stop_intervals.push_back(interval); // Link order and interval. - IntVar* const order_start = time_dimension.CumulVar(order); + IntVar *const order_start = time_dimension.CumulVar(order); solver->AddConstraint( solver->MakeIsEqualCt(interval->SafeStartExpr(0), order_start, interval->PerformedExpr()->Var())); - // Make interval performed iff corresponding order has service time. - // An order has no service time iff it is at the same location as the - // next order on the route. - IntVar* const is_null_duration = - solver - ->MakeElement( - [&locations, order](int64 index) { - return locations.SameLocationFromIndex(order, index); - }, - routing.NextVar(order)) - ->Var(); + // Make interval performed iff corresponding order has service time. + // An order has no service time iff it is at the same location as the + // next order on the route. + IntVar *const is_null_duration = + solver->MakeElement([&locations, order](int64 index) { + return locations.SameLocationFromIndex(order, index); + }, + routing.NextVar(order))->Var(); solver->AddConstraint( solver->MakeNonEquality(interval->PerformedExpr(), is_null_duration)); routing.AddIntervalToAssignment(interval); @@ -190,15 +196,15 @@ int main(int argc, char** argv) { // Solve, returns a solution if any (owned by RoutingModel). RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); - const Assignment* solution = routing.SolveWithParameters(parameters); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { - DisplayPlan(manager, routing, *solution, /*use_same_vehicle_costs=*/false, - /*max_nodes_per_group=*/0, /*same_vehicle_cost=*/0, + DisplayPlan(manager, routing, *solution, /*use_same_vehicle_costs=*/ false, + /*max_nodes_per_group=*/ 0, /*same_vehicle_cost=*/ 0, routing.GetDimensionOrDie(kCapacity), routing.GetDimensionOrDie(kTime)); LOG(INFO) << "Stop intervals:"; - for (IntervalVar* const interval : intervals) { + for (IntervalVar *const interval : intervals) { if (solution->PerformedValue(interval)) { LOG(INFO) << interval->name() << ": " << solution->StartValue(interval); } diff --git a/examples/cpp/dimacs_assignment.cc b/examples/cpp/dimacs_assignment.cc index e7c77682e0..e0356205d6 100644 --- a/examples/cpp/dimacs_assignment.cc +++ b/examples/cpp/dimacs_assignment.cc @@ -47,8 +47,8 @@ typedef ForwardStarStaticGraph GraphType; template CostValue BuildAndSolveHungarianInstance( - const LinearSumAssignment& assignment) { - const GraphType& graph = assignment.Graph(); + const LinearSumAssignment &assignment) { + const GraphType &graph = assignment.Graph(); typedef std::vector HungarianRow; typedef std::vector HungarianProblem; HungarianProblem hungarian_cost; @@ -106,7 +106,7 @@ CostValue BuildAndSolveHungarianInstance( } template -void DisplayAssignment(const LinearSumAssignment& assignment) { +void DisplayAssignment(const LinearSumAssignment &assignment) { for (typename LinearSumAssignment::BipartiteLeftNodeIterator node_it(assignment); node_it.Ok(); node_it.Next()) { @@ -119,18 +119,18 @@ void DisplayAssignment(const LinearSumAssignment& assignment) { } template -int SolveDimacsAssignment(int argc, char* argv[]) { +int SolveDimacsAssignment(int argc, char *argv[]) { std::string error_message; // Handle on the graph we will need to delete because the // LinearSumAssignment object does not take ownership of it. - GraphType* graph = nullptr; + GraphType *graph = nullptr; DimacsAssignmentParser parser(argv[1]); - LinearSumAssignment* assignment = + LinearSumAssignment *assignment = parser.Parse(&error_message, &graph); if (assignment == nullptr) { LOG(FATAL) << error_message; } - if (!FLAGS_assignment_problem_output_file.empty()) { + if (!absl::GetFlag(FLAGS_assignment_problem_output_file).empty()) { // The following tail array management stuff is done in a generic // way so we can plug in different types of graphs for which the // TailArrayManager template can be instantiated, even though we @@ -139,12 +139,13 @@ int SolveDimacsAssignment(int argc, char* argv[]) { // this file and making no other changes to the code. TailArrayManager tail_array_manager(graph); PrintDimacsAssignmentProblem( - *assignment, tail_array_manager, FLAGS_assignment_problem_output_file); + *assignment, tail_array_manager, + absl::GetFlag(FLAGS_assignment_problem_output_file)); tail_array_manager.ReleaseTailArrayIfForwardGraph(); } CostValue hungarian_cost = 0.0; bool hungarian_solved = false; - if (FLAGS_assignment_compare_hungarian) { + if (absl::GetFlag(FLAGS_assignment_compare_hungarian)) { hungarian_cost = BuildAndSolveHungarianInstance(*assignment); hungarian_solved = true; } @@ -169,16 +170,16 @@ int SolveDimacsAssignment(int argc, char* argv[]) { delete graph; return EXIT_SUCCESS; } -} // namespace operations_research +} // namespace operations_research -static const char* const kUsageTemplate = "usage: %s "; +static const char *const kUsageTemplate = "usage: %s "; using ::operations_research::ForwardStarGraph; using ::operations_research::ForwardStarStaticGraph; using ::operations_research::SolveDimacsAssignment; using ::operations_research::StarGraph; -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { std::string usage; if (argc < 1) { usage = absl::StrFormat(kUsageTemplate, "solve_dimacs_assignment"); @@ -192,9 +193,9 @@ int main(int argc, char* argv[]) { LOG(FATAL) << usage; } - if (FLAGS_assignment_static_graph) { + if (absl::GetFlag(FLAGS_assignment_static_graph)) { return SolveDimacsAssignment(argc, argv); - } else if (FLAGS_assignment_reverse_arcs) { + } else if (absl::GetFlag(FLAGS_assignment_reverse_arcs)) { return SolveDimacsAssignment(argc, argv); } else { return SolveDimacsAssignment(argc, argv); diff --git a/examples/cpp/dobble_ls.cc b/examples/cpp/dobble_ls.cc index 4768f02734..6d3d831850 100644 --- a/examples/cpp/dobble_ls.cc +++ b/examples/cpp/dobble_ls.cc @@ -41,9 +41,8 @@ #include "ortools/util/bitset.h" DEFINE_int32(symbols_per_card, 8, "Number of symbols per card."); -DEFINE_int32(ls_seed, 1, - "Seed for the random number generator (used by " - "the Local Neighborhood Search)."); +DEFINE_int32(ls_seed, 1, "Seed for the random number generator (used by " + "the Local Neighborhood Search)."); DEFINE_bool(use_filter, true, "Use filter in the local search to prune moves."); DEFINE_int32(num_swaps, 4, "If num_swap > 0, the search for an optimal " @@ -61,14 +60,13 @@ namespace operations_research { // sum_i(card1_symbol_vars[i]*card2_symbol_vars[i]) == count_var. // with all card_symbol_vars[i] being boolean variables. class SymbolsSharedByTwoCardsConstraint : public Constraint { - public: +public: // This constructor does not take any ownership on its arguments. SymbolsSharedByTwoCardsConstraint( - Solver* const solver, const std::vector& card1_symbol_vars, - const std::vector& card2_symbol_vars, - IntVar* const num_symbols_in_common_var) - : Constraint(solver), - card1_symbol_vars_(card1_symbol_vars), + Solver *const solver, const std::vector &card1_symbol_vars, + const std::vector &card2_symbol_vars, + IntVar *const num_symbols_in_common_var) + : Constraint(solver), card1_symbol_vars_(card1_symbol_vars), card2_symbol_vars_(card2_symbol_vars), num_symbols_(card1_symbol_vars.size()), num_symbols_in_common_var_(num_symbols_in_common_var) { @@ -96,7 +94,7 @@ class SymbolsSharedByTwoCardsConstraint : public Constraint { // such, InitialPropagate will be called after all normal demons // and constraints have reached a fixed point. Note // that ownership of the 'global_demon' belongs to the solver. - Demon* const global_demon = + Demon *const global_demon = solver()->MakeDelayedConstraintInitialPropagateCallback(this); // Attach to all variables. for (int i = 0; i < num_symbols_; ++i) { @@ -177,11 +175,11 @@ class SymbolsSharedByTwoCardsConstraint : public Constraint { } } - private: - std::vector card1_symbol_vars_; - std::vector card2_symbol_vars_; +private: + std::vector card1_symbol_vars_; + std::vector card2_symbol_vars_; const int num_symbols_; - IntVar* const num_symbols_in_common_var_; + IntVar *const num_symbols_in_common_var_; }; // Creates two integer variables: one that counts the number of @@ -189,11 +187,11 @@ class SymbolsSharedByTwoCardsConstraint : public Constraint { // difference between the first var and 1 (i.e. the violation of the // objective). Returns the latter (both vars are owned by the Solver // anyway). -IntVar* CreateViolationVar(Solver* const solver, - const std::vector& card1_symbol_vars, - const std::vector& card2_symbol_vars, +IntVar *CreateViolationVar(Solver *const solver, + const std::vector &card1_symbol_vars, + const std::vector &card2_symbol_vars, int num_symbols_per_card) { - IntVar* const num_symbols_in_common_var = + IntVar *const num_symbols_in_common_var = solver->MakeIntVar(0, num_symbols_per_card); // RevAlloc transfers the ownership of the constraint to the solver. solver->AddConstraint(solver->RevAlloc(new SymbolsSharedByTwoCardsConstraint( @@ -233,13 +231,11 @@ IntVar* CreateViolationVar(Solver* const solver, // parent class below, which contains some shared code to store a // compact representation of which symbols appeal on each cards. class DobbleOperator : public IntVarLocalSearchOperator { - public: - DobbleOperator(const std::vector& card_symbol_vars, int num_cards, +public: + DobbleOperator(const std::vector &card_symbol_vars, int num_cards, int num_symbols, int num_symbols_per_card) - : IntVarLocalSearchOperator(card_symbol_vars), - num_cards_(num_cards), - num_symbols_(num_symbols), - num_symbols_per_card_(num_symbols_per_card), + : IntVarLocalSearchOperator(card_symbol_vars), num_cards_(num_cards), + num_symbols_(num_symbols), num_symbols_per_card_(num_symbols_per_card), symbols_per_card_(num_cards) { CHECK_GT(num_cards, 0); CHECK_GT(num_symbols, 0); @@ -251,7 +247,7 @@ class DobbleOperator : public IntVarLocalSearchOperator { ~DobbleOperator() override {} - protected: +protected: // OnStart() simply stores the current symbols per card in // symbols_per_card_, and defers further initialization to the // subclass's InitNeighborhoodSearch() method. @@ -298,14 +294,12 @@ class DobbleOperator : public IntVarLocalSearchOperator { // symbol to a card that already had it); see the DobbleFilter class // below to see how we filter those out. class SwapSymbols : public DobbleOperator { - public: - SwapSymbols(const std::vector& card_symbol_vars, int num_cards, +public: + SwapSymbols(const std::vector &card_symbol_vars, int num_cards, int num_symbols, int num_symbols_per_card) : DobbleOperator(card_symbol_vars, num_cards, num_symbols, num_symbols_per_card), - current_card1_(-1), - current_card2_(-1), - current_symbol1_(-1), + current_card1_(-1), current_card2_(-1), current_symbol1_(-1), current_symbol2_(-1) {} ~SwapSymbols() override {} @@ -323,7 +317,7 @@ class SwapSymbols : public DobbleOperator { return true; } - private: +private: // Reinit the exploration loop. void InitNeighborhoodSearch() override { current_card1_ = 0; @@ -368,20 +362,19 @@ class SwapSymbols : public DobbleOperator { // randomized "infinite" version instead of an iterative, exhaustive // one. class SwapSymbolsOnCardPairs : public DobbleOperator { - public: - SwapSymbolsOnCardPairs(const std::vector& card_symbol_vars, +public: + SwapSymbolsOnCardPairs(const std::vector &card_symbol_vars, int num_cards, int num_symbols, int num_symbols_per_card, int max_num_swaps) : DobbleOperator(card_symbol_vars, num_cards, num_symbols, num_symbols_per_card), - rand_(FLAGS_ls_seed), - max_num_swaps_(max_num_swaps) { + rand_(absl::GetFlag(FLAGS_ls_seed)), max_num_swaps_(max_num_swaps) { CHECK_GE(max_num_swaps, 2); } ~SwapSymbolsOnCardPairs() override {} - protected: +protected: bool MakeOneNeighbor() override { const int num_swaps = absl::Uniform(rand_, 0, max_num_swaps_ - 1) + 2; @@ -401,7 +394,7 @@ class SwapSymbolsOnCardPairs : public DobbleOperator { void InitNeighborhoodSearch() override {} - private: +private: std::mt19937 rand_; const int max_num_swaps_; }; @@ -434,20 +427,17 @@ class SwapSymbolsOnCardPairs : public DobbleOperator { // effectively limits the number of cards to 63, and thus the number // of symbols per card to 8. class DobbleFilter : public IntVarLocalSearchFilter { - public: - DobbleFilter(const std::vector& card_symbol_vars, int num_cards, +public: + DobbleFilter(const std::vector &card_symbol_vars, int num_cards, int num_symbols, int num_symbols_per_card) - : IntVarLocalSearchFilter(card_symbol_vars), - num_cards_(num_cards), - num_symbols_(num_symbols), - num_symbols_per_card_(num_symbols_per_card), - temporary_bitset_(0), - symbol_bitmask_per_card_(num_cards, 0), + : IntVarLocalSearchFilter(card_symbol_vars), num_cards_(num_cards), + num_symbols_(num_symbols), num_symbols_per_card_(num_symbols_per_card), + temporary_bitset_(0), symbol_bitmask_per_card_(num_cards, 0), violation_costs_(num_cards_, std::vector(num_cards_, 0)) {} // We build the current bitmap and the matrix of violation cost // between any two cards. - void OnSynchronize(const Assignment* delta) override { + void OnSynchronize(const Assignment *delta) override { symbol_bitmask_per_card_.assign(num_cards_, 0); for (int card = 0; card < num_cards_; ++card) { for (int symbol = 0; symbol < num_symbols_; ++symbol) { @@ -468,9 +458,9 @@ class DobbleFilter : public IntVarLocalSearchFilter { // The LocalSearchFilter::Accept() API also takes a deltadelta, // which is the difference between the current delta and the last // delta that was given to Accept() -- but we don't use it here. - bool Accept(const Assignment* delta, const Assignment* unused_deltadelta, + bool Accept(const Assignment *delta, const Assignment *unused_deltadelta, int64 objective_min, int64 objective_max) override { - const Assignment::IntContainer& solution_delta = delta->IntVarContainer(); + const Assignment::IntContainer &solution_delta = delta->IntVarContainer(); const int solution_delta_size = solution_delta.Size(); // The input const Assignment* delta given to Accept() may @@ -528,7 +518,7 @@ class DobbleFilter : public IntVarLocalSearchFilter { return cost_delta < 0; } - private: +private: // Undo information after an evaluation. struct UndoChange { UndoChange(int c, uint64 b) : card(c), bitset(b) {} @@ -543,14 +533,14 @@ class DobbleFilter : public IntVarLocalSearchFilter { // For each touched card, compare against all others to compute the // delta in term of cost. We use an bitset to avoid counting twice // between two cards appearing in the local search move. - int ComputeNewCost(const std::vector& touched_cards) { + int ComputeNewCost(const std::vector &touched_cards) { ClearBitset(); int cost_delta = 0; for (int i = 0; i < touched_cards.size(); ++i) { const int touched = touched_cards[i]; SetBit64(&temporary_bitset_, touched); const uint64 card_bitset = symbol_bitmask_per_card_[touched]; - const std::vector& row_cost = violation_costs_[touched]; + const std::vector &row_cost = violation_costs_[touched]; for (int other_card = 0; other_card < num_cards_; ++other_card) { if (!IsBitSet64(&temporary_bitset_, other_card)) { cost_delta += ViolationCost( @@ -563,8 +553,8 @@ class DobbleFilter : public IntVarLocalSearchFilter { } // Collects all card indices appearing in the local search move. - void ComputeTouchedCards(const Assignment::IntContainer& solution_delta, - std::vector* const touched_cards) { + void ComputeTouchedCards(const Assignment::IntContainer &solution_delta, + std::vector *const touched_cards) { ClearBitset(); const int solution_delta_size = solution_delta.Size(); const int kUnassigned = -1; @@ -640,8 +630,8 @@ void SolveDobble(int num_cards, int num_symbols, int num_symbols_per_card) { // Creates the solver. Solver solver("dobble"); // Creates the matrix of boolean variables (cards * symbols). - std::vector > card_symbol_vars(num_cards); - std::vector all_card_symbol_vars; + std::vector > card_symbol_vars(num_cards); + std::vector all_card_symbol_vars; for (int card_index = 0; card_index < num_cards; ++card_index) { solver.MakeBoolVarArray(num_symbols, absl::StrFormat("card_%i_", card_index), @@ -653,7 +643,7 @@ void SolveDobble(int num_cards, int num_symbols, int num_symbols_per_card) { } // Creates cardinality intersection variables and remember the // violation variables. - std::vector violation_vars; + std::vector violation_vars; for (int card1 = 0; card1 < num_cards; ++card1) { for (int card2 = 0; card2 < num_cards; ++card2) { if (card1 != card2) { @@ -664,7 +654,7 @@ void SolveDobble(int num_cards, int num_symbols, int num_symbols_per_card) { } } // Create the objective variable. - IntVar* const objective_var = solver.MakeSum(violation_vars)->Var(); + IntVar *const objective_var = solver.MakeSum(violation_vars)->Var(); // Add constraint: there must be exactly num_symbols_per_card // symbols per card. @@ -680,7 +670,7 @@ void SolveDobble(int num_cards, int num_symbols, int num_symbols_per_card) { // is a (non-trivial) consequence of the other constraints and of // the model. But adding it makes the search go faster. for (int symbol_index = 0; symbol_index < num_symbols; ++symbol_index) { - std::vector tmp; + std::vector tmp; for (int card_index = 0; card_index < num_cards; ++card_index) { tmp.push_back(card_symbol_vars[card_index][symbol_index]); } @@ -689,33 +679,35 @@ void SolveDobble(int num_cards, int num_symbols, int num_symbols_per_card) { // Search. LOG(INFO) << "Solving with Local Search"; - LOG(INFO) << " - time limit = " << FLAGS_time_limit_in_ms << " ms"; + LOG(INFO) << " - time limit = " << absl::GetFlag(FLAGS_time_limit_in_ms) + << " ms"; // Start a DecisionBuilder phase to find a first solution, using the // strategy "Pick some random, yet unassigned card symbol variable // and set its value to 1". - DecisionBuilder* const build_db = solver.MakePhase( - all_card_symbol_vars, Solver::CHOOSE_RANDOM, // Solver::IntVarStrategy - Solver::ASSIGN_MAX_VALUE); // Solver::IntValueStrategy + DecisionBuilder *const build_db = solver.MakePhase( + all_card_symbol_vars, Solver::CHOOSE_RANDOM, // Solver::IntVarStrategy + Solver::ASSIGN_MAX_VALUE); // Solver::IntValueStrategy // Creates local search operators. - std::vector operators; - LocalSearchOperator* const switch_operator = solver.RevAlloc(new SwapSymbols( + std::vector operators; + LocalSearchOperator *const switch_operator = solver.RevAlloc(new SwapSymbols( all_card_symbol_vars, num_cards, num_symbols, num_symbols_per_card)); operators.push_back(switch_operator); LOG(INFO) << " - add switch operator"; - if (FLAGS_num_swaps > 0) { - LocalSearchOperator* const swaps_operator = solver.RevAlloc( - new SwapSymbolsOnCardPairs(all_card_symbol_vars, num_cards, num_symbols, - num_symbols_per_card, FLAGS_num_swaps)); + if (absl::GetFlag(FLAGS_num_swaps) > 0) { + LocalSearchOperator *const swaps_operator = + solver.RevAlloc(new SwapSymbolsOnCardPairs( + all_card_symbol_vars, num_cards, num_symbols, num_symbols_per_card, + absl::GetFlag(FLAGS_num_swaps))); operators.push_back(swaps_operator); - LOG(INFO) << " - add swaps operator with at most " << FLAGS_num_swaps - << " swaps"; + LOG(INFO) << " - add swaps operator with at most " + << absl::GetFlag(FLAGS_num_swaps) << " swaps"; } // Creates filter. - std::vector filters; - if (FLAGS_use_filter) { + std::vector filters; + if (absl::GetFlag(FLAGS_use_filter)) { filters.push_back(solver.RevAlloc(new DobbleFilter( all_card_symbol_vars, num_cards, num_symbols, num_symbols_per_card))); } @@ -723,42 +715,42 @@ void SolveDobble(int num_cards, int num_symbols, int num_symbols_per_card) { // Main decision builder that regroups the first solution decision // builder and the combination of local search operators and // filters. - LocalSearchFilterManager* filter_manager = + LocalSearchFilterManager *filter_manager = solver.RevAlloc(new LocalSearchFilterManager(filters)); - DecisionBuilder* const final_db = solver.MakeLocalSearchPhase( + DecisionBuilder *const final_db = solver.MakeLocalSearchPhase( all_card_symbol_vars, build_db, solver.MakeLocalSearchPhaseParameters( objective_var, solver.ConcatenateOperators(operators, true), - nullptr, // Sub decision builder, not needed here. - nullptr, // Limit the search for improving move, we will stop - // the exploration of the local search at the first - // improving solution (first accept). + nullptr, // Sub decision builder, not needed here. + nullptr, // Limit the search for improving move, we will stop + // the exploration of the local search at the first + // improving solution (first accept). filter_manager)); - std::vector monitors; + std::vector monitors; // Optimize var search monitor. - OptimizeVar* const optimize = solver.MakeMinimize(objective_var, 1); + OptimizeVar *const optimize = solver.MakeMinimize(objective_var, 1); monitors.push_back(optimize); // Search log. - SearchMonitor* const log = solver.MakeSearchLog(100000, optimize); + SearchMonitor *const log = solver.MakeSearchLog(100000, optimize); monitors.push_back(log); // Search limit. - SearchLimit* const time_limit = - solver.MakeLimit(FLAGS_time_limit_in_ms, kint64max, kint64max, kint64max); + SearchLimit *const time_limit = solver.MakeLimit( + absl::GetFlag(FLAGS_time_limit_in_ms), kint64max, kint64max, kint64max); monitors.push_back(time_limit); // And solve! solver.Solve(final_db, monitors); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); // These constants comes directly from the dobble game. // There are actually 55 cards, but we can create up to 57 cards. - const int kSymbolsPerCard = FLAGS_symbols_per_card; + const int kSymbolsPerCard = absl::GetFlag(FLAGS_symbols_per_card); const int kCards = kSymbolsPerCard * (kSymbolsPerCard - 1) + 1; const int kSymbols = kCards; operations_research::SolveDobble(kCards, kSymbols, kSymbolsPerCard); diff --git a/examples/cpp/fap_model_printer.h b/examples/cpp/fap_model_printer.h index 7528da83cd..e8b1b40f9e 100644 --- a/examples/cpp/fap_model_printer.h +++ b/examples/cpp/fap_model_printer.h @@ -30,10 +30,10 @@ namespace operations_research { // Prints the instance of the Frequency Assignment Problem. class FapModelPrinter { - public: - FapModelPrinter(const std::map& variables, - const std::vector& constraints, - const std::string& objective, const std::vector& values); +public: + FapModelPrinter(const std::map &variables, + const std::vector &constraints, + const std::string &objective, const std::vector &values); ~FapModelPrinter(); void PrintFapObjective(); @@ -41,7 +41,7 @@ class FapModelPrinter { void PrintFapConstraints(); void PrintFapValues(); - private: +private: const std::map variables_; const std::vector constraints_; const std::string objective_; @@ -49,20 +49,18 @@ class FapModelPrinter { DISALLOW_COPY_AND_ASSIGN(FapModelPrinter); }; -FapModelPrinter::FapModelPrinter(const std::map& variables, - const std::vector& constraints, - const std::string& objective, - const std::vector& values) - : variables_(variables), - constraints_(constraints), - objective_(objective), +FapModelPrinter::FapModelPrinter(const std::map &variables, + const std::vector &constraints, + const std::string &objective, + const std::vector &values) + : variables_(variables), constraints_(constraints), objective_(objective), values_(values) {} FapModelPrinter::~FapModelPrinter() {} void FapModelPrinter::PrintFapVariables() { LOG(INFO) << "Variable File:"; - for (const auto& it : variables_) { + for (const auto &it : variables_) { std::string domain = "{"; for (const int value : it.second.domain) { absl::StrAppendFormat(&domain, "%d ", value); @@ -87,7 +85,7 @@ void FapModelPrinter::PrintFapVariables() { void FapModelPrinter::PrintFapConstraints() { LOG(INFO) << "Constraint File:"; - for (const FapConstraint& ct : constraints_) { + for (const FapConstraint &ct : constraints_) { std::string hard = " "; if (ct.hard) { hard = " hard"; @@ -114,5 +112,5 @@ void FapModelPrinter::PrintFapValues() { LOG(INFO) << domain; } -} // namespace operations_research -#endif // OR_TOOLS_EXAMPLES_FAP_MODEL_PRINTER_H_ +} // namespace operations_research +#endif // OR_TOOLS_EXAMPLES_FAP_MODEL_PRINTER_H_ diff --git a/examples/cpp/fap_parser.h b/examples/cpp/fap_parser.h index dc88312128..fc36776acc 100644 --- a/examples/cpp/fap_parser.h +++ b/examples/cpp/fap_parser.h @@ -34,20 +34,15 @@ namespace operations_research { // Takes a filename and a buffer and fills the lines buffer // with the lines of the file corresponding to the filename. -void ParseFileByLines(const std::string& filename, - std::vector* lines); +void ParseFileByLines(const std::string &filename, + std::vector *lines); // The FapVariable struct represents a radio link of the // frequency assignment problem. struct FapVariable { FapVariable() - : domain_index(-1), - domain_size(0), - domain(), - degree(0), - initial_position(-1), - mobility_index(-1), - mobility_cost(-1), + : domain_index(-1), domain_size(0), domain(), degree(0), + initial_position(-1), mobility_index(-1), mobility_cost(-1), hard(false) {} ~FapVariable() {} @@ -84,15 +79,8 @@ struct FapVariable { // radio links of the frequency assignment problem. struct FapConstraint { FapConstraint() - : variable1(-1), - variable2(-1), - impact(0), - type(""), - operation(""), - value(-1), - weight_index(-1), - weight_cost(-1), - hard(false) {} + : variable1(-1), variable2(-1), impact(0), type(""), operation(""), + value(-1), weight_index(-1), weight_cost(-1), hard(false) {} ~FapConstraint() {} // Fields: @@ -147,15 +135,15 @@ struct FapComponent { // This file describes all the variables in the instance. // Each line corresponds to one variable. class VariableParser { - public: - explicit VariableParser(const std::string& data_directory); +public: + explicit VariableParser(const std::string &data_directory); ~VariableParser(); - const std::map& variables() const { return variables_; } + const std::map &variables() const { return variables_; } void Parse(); - private: +private: const std::string filename_; // A map is used because in the model, the variables have ids which may not // be consecutive, may be very sparse and don't have a specific upper-bound. @@ -169,15 +157,15 @@ class VariableParser { // This file describes the domains used by the variables of the problem. // Each line describes one domain. class DomainParser { - public: - explicit DomainParser(const std::string& data_directory); +public: + explicit DomainParser(const std::string &data_directory); ~DomainParser(); - const std::map >& domains() const { return domains_; } + const std::map > &domains() const { return domains_; } void Parse(); - private: +private: const std::string filename_; // A map is used because in the model, the ids of the different available // domains may be random values, since they are used as names. The key of the @@ -191,15 +179,15 @@ class DomainParser { // This file describes the constraints of the instance. // Each line defines a binary constraint. class ConstraintParser { - public: - explicit ConstraintParser(const std::string& data_directory); +public: + explicit ConstraintParser(const std::string &data_directory); ~ConstraintParser(); - const std::vector& constraints() const { return constraints_; } + const std::vector &constraints() const { return constraints_; } void Parse(); - private: +private: const std::string filename_; std::vector constraints_; @@ -211,19 +199,19 @@ class ConstraintParser { // It may also contain 8 coefficients: 4 for different constraint violation // costs and 4 for different variable mobility costs. class ParametersParser { - public: - explicit ParametersParser(const std::string& data_directory); +public: + explicit ParametersParser(const std::string &data_directory); ~ParametersParser(); std::string objective() const { return objective_; } - const std::vector& constraint_weights() const { + const std::vector &constraint_weights() const { return constraint_weights_; } - const std::vector& variable_weights() const { return variable_weights_; } + const std::vector &variable_weights() const { return variable_weights_; } void Parse(); - private: +private: const std::string filename_; static const int constraint_coefficient_no_ = 4; static const int variable_coefficient_no_ = 4; @@ -234,33 +222,33 @@ class ParametersParser { }; namespace { -int strtoint32(const std::string& word) { +int strtoint32(const std::string &word) { int result; CHECK(absl::SimpleAtoi(word, &result)); return result; } -} // namespace +} // namespace // Function that finds the disjoint sub-graphs of the graph of the instance. -void FindComponents(const std::vector& constraints, - const std::map& variables, +void FindComponents(const std::vector &constraints, + const std::map &variables, const int maximum_variable_id, - absl::flat_hash_map* components); + absl::flat_hash_map *components); // Function that computes the impact of a constraint. -int EvaluateConstraintImpact(const std::map& variables, +int EvaluateConstraintImpact(const std::map &variables, const int max_weight_cost, const FapConstraint constraint); // Function that parses an instance of frequency assignment problem. -void ParseInstance(const std::string& data_directory, bool find_components, - std::map* variables, - std::vector* constraints, - std::string* objective, std::vector* frequencies, - absl::flat_hash_map* components); +void ParseInstance(const std::string &data_directory, bool find_components, + std::map *variables, + std::vector *constraints, + std::string *objective, std::vector *frequencies, + absl::flat_hash_map *components); -void ParseFileByLines(const std::string& filename, - std::vector* lines) { +void ParseFileByLines(const std::string &filename, + std::vector *lines) { CHECK(lines != nullptr); std::string result; CHECK_OK(file::GetContents(filename, &result, file::Defaults())); @@ -268,7 +256,7 @@ void ParseFileByLines(const std::string& filename, } // VariableParser Implementation -VariableParser::VariableParser(const std::string& data_directory) +VariableParser::VariableParser(const std::string &data_directory) : filename_(data_directory + "/var.txt") {} VariableParser::~VariableParser() {} @@ -276,7 +264,7 @@ VariableParser::~VariableParser() {} void VariableParser::Parse() { std::vector lines; ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { + for (const std::string &line : lines) { std::vector tokens = absl::StrSplit(line, ' ', absl::SkipEmpty()); if (tokens.empty()) { @@ -295,7 +283,7 @@ void VariableParser::Parse() { } // DomainParser Implementation -DomainParser::DomainParser(const std::string& data_directory) +DomainParser::DomainParser(const std::string &data_directory) : filename_(data_directory + "/dom.txt") {} DomainParser::~DomainParser() {} @@ -303,7 +291,7 @@ DomainParser::~DomainParser() {} void DomainParser::Parse() { std::vector lines; ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { + for (const std::string &line : lines) { std::vector tokens = absl::StrSplit(line, ' ', absl::SkipEmpty()); if (tokens.empty()) { @@ -326,7 +314,7 @@ void DomainParser::Parse() { } // ConstraintParser Implementation -ConstraintParser::ConstraintParser(const std::string& data_directory) +ConstraintParser::ConstraintParser(const std::string &data_directory) : filename_(data_directory + "/ctr.txt") {} ConstraintParser::~ConstraintParser() {} @@ -334,7 +322,7 @@ ConstraintParser::~ConstraintParser() {} void ConstraintParser::Parse() { std::vector lines; ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { + for (const std::string &line : lines) { std::vector tokens = absl::StrSplit(line, ' ', absl::SkipEmpty()); if (tokens.empty()) { @@ -361,9 +349,8 @@ const int ParametersParser::constraint_coefficient_no_; const int ParametersParser::variable_coefficient_no_; const int ParametersParser::coefficient_no_; -ParametersParser::ParametersParser(const std::string& data_directory) - : filename_(data_directory + "/cst.txt"), - objective_(""), +ParametersParser::ParametersParser(const std::string &data_directory) + : filename_(data_directory + "/cst.txt"), objective_(""), constraint_weights_(constraint_coefficient_no_, 0), variable_weights_(variable_coefficient_no_, 0) {} @@ -380,7 +367,7 @@ void ParametersParser::Parse() { std::vector lines; ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { + for (const std::string &line : lines) { if (objective) { largest_token = largest_token || (line.find("largest") != std::string::npos); @@ -426,17 +413,17 @@ void ParametersParser::Parse() { } // TODO(user): Make FindComponents linear instead of quadratic. -void FindComponents(const std::vector& constraints, - const std::map& variables, +void FindComponents(const std::vector &constraints, + const std::map &variables, const int maximum_variable_id, - absl::flat_hash_map* components) { + absl::flat_hash_map *components) { std::vector in_component(maximum_variable_id + 1, -1); int constraint_index = 0; - for (const FapConstraint& constraint : constraints) { + for (const FapConstraint &constraint : constraints) { const int variable_id1 = constraint.variable1; const int variable_id2 = constraint.variable2; - const FapVariable& variable1 = gtl::FindOrDie(variables, variable_id1); - const FapVariable& variable2 = gtl::FindOrDie(variables, variable_id2); + const FapVariable &variable1 = gtl::FindOrDie(variables, variable_id1); + const FapVariable &variable2 = gtl::FindOrDie(variables, variable_id2); CHECK_LT(variable_id1, in_component.size()); CHECK_LT(variable_id2, in_component.size()); if (in_component[variable_id1] < 0 && in_component[variable_id2] < 0) { @@ -482,24 +469,22 @@ void FindComponents(const std::vector& constraints, CHECK(gtl::ContainsKey(*components, max_component_index)); if (min_component_index != max_component_index) { // Update the component_index of maximum indexed component's variables. - for (const auto& variable : + for (const auto &variable : (*components)[max_component_index].variables) { int variable_id = variable.first; in_component[variable_id] = min_component_index; } // Insert all the variables of the maximum indexed component to the // variables of the minimum indexed component. - ((*components)[min_component_index]) - .variables.insert( - ((*components)[max_component_index]).variables.begin(), - ((*components)[max_component_index]).variables.end()); + ((*components)[min_component_index]).variables + .insert(((*components)[max_component_index]).variables.begin(), + ((*components)[max_component_index]).variables.end()); // Insert all the constraints of the maximum indexed component to the // constraints of the minimum indexed component. - ((*components)[min_component_index]) - .constraints.insert( - ((*components)[min_component_index]).constraints.end(), - ((*components)[max_component_index]).constraints.begin(), - ((*components)[max_component_index]).constraints.end()); + ((*components)[min_component_index]).constraints + .insert(((*components)[min_component_index]).constraints.end(), + ((*components)[max_component_index]).constraints.begin(), + ((*components)[max_component_index]).constraints.end()); (*components)[min_component_index].constraints.push_back(constraint); // Delete the maximum indexed component from the components set. components->erase(max_component_index); @@ -512,12 +497,12 @@ void FindComponents(const std::vector& constraints, } } -int EvaluateConstraintImpact(const std::map& variables, +int EvaluateConstraintImpact(const std::map &variables, const int max_weight_cost, const FapConstraint constraint) { - const FapVariable& variable1 = + const FapVariable &variable1 = gtl::FindOrDie(variables, constraint.variable1); - const FapVariable& variable2 = + const FapVariable &variable2 = gtl::FindOrDie(variables, constraint.variable2); const int degree1 = variable1.degree; const int degree2 = variable2.degree; @@ -535,11 +520,11 @@ int EvaluateConstraintImpact(const std::map& variables, return max_degree + min_degree + operator_impact + hardness_impact; } -void ParseInstance(const std::string& data_directory, bool find_components, - std::map* variables, - std::vector* constraints, - std::string* objective, std::vector* frequencies, - absl::flat_hash_map* components) { +void ParseInstance(const std::string &data_directory, bool find_components, + std::map *variables, + std::vector *constraints, + std::string *objective, std::vector *frequencies, + absl::flat_hash_map *components) { CHECK(variables != nullptr); CHECK(constraints != nullptr); CHECK(objective != nullptr); @@ -564,7 +549,7 @@ void ParseInstance(const std::string& data_directory, bool find_components, (cst.constraint_weights()).begin(), (cst.constraint_weights()).end()); // Make the variables of the instance. - for (auto& it : *variables) { + for (auto &it : *variables) { it.second.domain = gtl::FindOrDie(dom.domains(), it.second.domain_index); it.second.domain_size = it.second.domain.size(); @@ -579,7 +564,7 @@ void ParseInstance(const std::string& data_directory, bool find_components, } } // Make the constraints of the instance. - for (FapConstraint& ct : *constraints) { + for (FapConstraint &ct : *constraints) { if ((ct.weight_index == -1) || (ct.weight_index == 0)) { ct.weight_cost = -1; ct.hard = true; @@ -599,18 +584,18 @@ void ParseInstance(const std::string& data_directory, bool find_components, CHECK(components != nullptr); FindComponents(*constraints, *variables, maximum_variable_id, components); // Evaluate each components's constraints impacts. - for (auto& component : *components) { - for (auto& constraint : component.second.constraints) { + for (auto &component : *components) { + for (auto &constraint : component.second.constraints) { constraint.impact = EvaluateConstraintImpact( *variables, maximum_weight_cost, constraint); } } } else { - for (FapConstraint& constraint : *constraints) { + for (FapConstraint &constraint : *constraints) { constraint.impact = EvaluateConstraintImpact(*variables, maximum_weight_cost, constraint); } } } -} // namespace operations_research -#endif // OR_TOOLS_EXAMPLES_FAP_PARSER_H_ +} // namespace operations_research +#endif // OR_TOOLS_EXAMPLES_FAP_PARSER_H_ diff --git a/examples/cpp/fap_utilities.h b/examples/cpp/fap_utilities.h index 9c6232edc6..5fc343592d 100644 --- a/examples/cpp/fap_utilities.h +++ b/examples/cpp/fap_utilities.h @@ -33,48 +33,48 @@ namespace operations_research { // Checks if the solution given from the Solver satisfies all // the hard binary constraints specified in the ctr.txt. bool CheckConstraintSatisfaction( - const std::vector& data_constraints, - const std::vector& variables, - const std::map& index_from_key); + const std::vector &data_constraints, + const std::vector &variables, + const std::map &index_from_key); // Checks if the solution given from the Solver has not modified the values of // the variables that were initially assigned and denoted as hard in var.txt. -bool CheckVariablePosition(const std::map& data_variables, - const std::vector& variables, - const std::map& index_from_key); +bool CheckVariablePosition(const std::map &data_variables, + const std::vector &variables, + const std::map &index_from_key); // Counts the number of different values in the variable vector. -int NumberOfAssignedValues(const std::vector& variables); +int NumberOfAssignedValues(const std::vector &variables); // Prints the duration of the solving process. void PrintElapsedTime(const int64 time1, const int64 time2); // Prints the solution found by the Hard Solver for feasible instances. -void PrintResultsHard(SolutionCollector* const collector, - const std::vector& variables, - IntVar* const objective_var, - const std::map& data_variables, - const std::vector& data_constraints, - const std::map& index_from_key, - const std::vector& key_from_index); +void PrintResultsHard(SolutionCollector *const collector, + const std::vector &variables, + IntVar *const objective_var, + const std::map &data_variables, + const std::vector &data_constraints, + const std::map &index_from_key, + const std::vector &key_from_index); // Prints the solution found by the Soft Solver for unfeasible instances. -void PrintResultsSoft(SolutionCollector* const collector, - const std::vector& variables, - IntVar* const total_cost, - const std::map& hard_variables, - const std::vector& hard_constraints, - const std::map& soft_variables, - const std::vector& soft_constraints, - const std::map& index_from_key, - const std::vector& key_from_index); +void PrintResultsSoft(SolutionCollector *const collector, + const std::vector &variables, + IntVar *const total_cost, + const std::map &hard_variables, + const std::vector &hard_constraints, + const std::map &soft_variables, + const std::vector &soft_constraints, + const std::map &index_from_key, + const std::vector &key_from_index); -bool CheckConstraintSatisfaction( - const std::vector& data_constraints, - const std::vector& variables, - const std::map& index_from_key) { +bool +CheckConstraintSatisfaction(const std::vector &data_constraints, + const std::vector &variables, + const std::map &index_from_key) { bool status = true; - for (const FapConstraint& ct : data_constraints) { + for (const FapConstraint &ct : data_constraints) { const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); CHECK_LT(index1, variables.size()); @@ -100,11 +100,11 @@ bool CheckConstraintSatisfaction( return status; } -bool CheckVariablePosition(const std::map& data_variables, - const std::vector& variables, - const std::map& index_from_key) { +bool CheckVariablePosition(const std::map &data_variables, + const std::vector &variables, + const std::map &index_from_key) { bool status = true; - for (const auto& it : data_variables) { + for (const auto &it : data_variables) { const int index = gtl::FindOrDie(index_from_key, it.first); CHECK_LT(index, variables.size()); const int var = variables[index]; @@ -120,7 +120,7 @@ bool CheckVariablePosition(const std::map& data_variables, return status; } -int NumberOfAssignedValues(const std::vector& variables) { +int NumberOfAssignedValues(const std::vector &variables) { std::set assigned(variables.begin(), variables.end()); return static_cast(assigned.size()); } @@ -131,18 +131,18 @@ void PrintElapsedTime(const int64 time1, const int64 time2) { << " seconds."; } -void PrintResultsHard(SolutionCollector* const collector, - const std::vector& variables, - IntVar* const objective_var, - const std::map& data_variables, - const std::vector& data_constraints, - const std::map& index_from_key, - const std::vector& key_from_index) { +void PrintResultsHard(SolutionCollector *const collector, + const std::vector &variables, + IntVar *const objective_var, + const std::map &data_variables, + const std::vector &data_constraints, + const std::map &index_from_key, + const std::vector &key_from_index) { LOG(INFO) << "Printing..."; LOG(INFO) << "Number of Solutions: " << collector->solution_count(); for (int solution_index = 0; solution_index < collector->solution_count(); ++solution_index) { - Assignment* const solution = collector->solution(solution_index); + Assignment *const solution = collector->solution(solution_index); std::vector results(variables.size()); LOG(INFO) << "------------------------------------------------------------"; LOG(INFO) << "Solution " << solution_index + 1; @@ -164,27 +164,27 @@ void PrintResultsHard(SolutionCollector* const collector, } LOG(INFO) << "Values used: " << NumberOfAssignedValues(results); - LOG(INFO) << "Maximum value used: " - << *std::max_element(results.begin(), results.end()); + LOG(INFO) << "Maximum value used: " << *std::max_element(results.begin(), + results.end()); LOG(INFO) << " Failures: " << collector->failures(solution_index); } LOG(INFO) << " ============================================================"; } -void PrintResultsSoft(SolutionCollector* const collector, - const std::vector& variables, - IntVar* const total_cost, - const std::map& hard_variables, - const std::vector& hard_constraints, - const std::map& soft_variables, - const std::vector& soft_constraints, - const std::map& index_from_key, - const std::vector& key_from_index) { +void PrintResultsSoft(SolutionCollector *const collector, + const std::vector &variables, + IntVar *const total_cost, + const std::map &hard_variables, + const std::vector &hard_constraints, + const std::map &soft_variables, + const std::vector &soft_constraints, + const std::map &index_from_key, + const std::vector &key_from_index) { LOG(INFO) << "Printing..."; LOG(INFO) << "Number of Solutions: " << collector->solution_count(); for (int solution_index = 0; solution_index < collector->solution_count(); ++solution_index) { - Assignment* const solution = collector->solution(solution_index); + Assignment *const solution = collector->solution(solution_index); std::vector results(variables.size()); LOG(INFO) << "------------------------------------------------------------"; LOG(INFO) << "Solution"; @@ -216,12 +216,12 @@ void PrintResultsSoft(SolutionCollector* const collector, } LOG(INFO) << "Values used: " << NumberOfAssignedValues(results); - LOG(INFO) << "Maximum value used: " - << *std::max_element(results.begin(), results.end()); + LOG(INFO) << "Maximum value used: " << *std::max_element(results.begin(), + results.end()); LOG(INFO) << " Failures: " << collector->failures(solution_index); } LOG(INFO) << " ============================================================"; } -} // namespace operations_research -#endif // OR_TOOLS_EXAMPLES_FAP_UTILITIES_H_ +} // namespace operations_research +#endif // OR_TOOLS_EXAMPLES_FAP_UTILITIES_H_ diff --git a/examples/cpp/flow_api.cc b/examples/cpp/flow_api.cc index 8dcaaa0a3d..8b4f097819 100644 --- a/examples/cpp/flow_api.cc +++ b/examples/cpp/flow_api.cc @@ -27,10 +27,10 @@ void MinCostFlowOn4x4Matrix() { LOG(INFO) << "Min Cost Flow on 4x4 Matrix"; const int kNumSources = 4; const int kNumTargets = 4; - const CostValue kCost[kNumSources][kNumTargets] = {{90, 75, 75, 80}, - {35, 85, 55, 65}, - {125, 95, 90, 105}, - {45, 110, 95, 115}}; + const CostValue kCost[kNumSources][kNumTargets] = { { 90, 75, 75, 80 }, + { 35, 85, 55, 65 }, + { 125, 95, 90, 105 }, + { 45, 110, 95, 115 } }; const CostValue kExpectedCost = 275; StarGraph graph(kNumSources + kNumTargets, kNumSources * kNumTargets); MinCostFlow min_cost_flow(&graph); @@ -59,10 +59,10 @@ void MaxFeasibleFlow() { LOG(INFO) << "Max Feasible Flow"; const int kNumNodes = 6; const int kNumArcs = 9; - const NodeIndex kTail[kNumArcs] = {0, 0, 0, 0, 1, 2, 3, 3, 4}; - const NodeIndex kHead[kNumArcs] = {1, 2, 3, 4, 3, 4, 4, 5, 5}; - const FlowQuantity kCapacity[kNumArcs] = {5, 8, 5, 3, 4, 5, 6, 6, 4}; - const FlowQuantity kExpectedFlow[kNumArcs] = {1, 1, 5, 3, 1, 1, 0, 6, 4}; + const NodeIndex kTail[kNumArcs] = { 0, 0, 0, 0, 1, 2, 3, 3, 4 }; + const NodeIndex kHead[kNumArcs] = { 1, 2, 3, 4, 3, 4, 4, 5, 5 }; + const FlowQuantity kCapacity[kNumArcs] = { 5, 8, 5, 3, 4, 5, 6, 6, 4 }; + const FlowQuantity kExpectedFlow[kNumArcs] = { 1, 1, 5, 3, 1, 1, 0, 6, 4 }; const FlowQuantity kExpectedTotalFlow = 10; StarGraph graph(kNumNodes, kNumArcs); MaxFlow max_flow(&graph, 0, kNumNodes - 1); @@ -78,9 +78,9 @@ void MaxFeasibleFlow() { CHECK_EQ(kExpectedFlow[i], max_flow.Flow(i)) << " i = " << i; } } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::MinCostFlowOn4x4Matrix(); operations_research::MaxFeasibleFlow(); diff --git a/examples/cpp/frequency_assignment_problem.cc b/examples/cpp/frequency_assignment_problem.cc index 016802ae73..5c6000a406 100644 --- a/examples/cpp/frequency_assignment_problem.cc +++ b/examples/cpp/frequency_assignment_problem.cc @@ -89,42 +89,40 @@ namespace operations_research { // Decision on the relative order that the two variables of a constraint // will have. It takes as parameters the components of the constraint. class OrderingDecision : public Decision { - public: - OrderingDecision(IntVar* const variable1, IntVar* const variable2, int value, +public: + OrderingDecision(IntVar *const variable1, IntVar *const variable2, int value, std::string operation) - : variable1_(variable1), - variable2_(variable2), - value_(value), + : variable1_(variable1), variable2_(variable2), value_(value), operator_(std::move(operation)) {} ~OrderingDecision() override {} // Apply will be called first when the decision is executed. - void Apply(Solver* const s) override { + void Apply(Solver *const s) override { // variable1 < variable2 MakeDecision(s, variable1_, variable2_); } // Refute will be called after a backtrack. - void Refute(Solver* const s) override { + void Refute(Solver *const s) override { // variable1 > variable2 MakeDecision(s, variable2_, variable1_); } - private: - void MakeDecision(Solver* s, IntVar* variable1, IntVar* variable2) { +private: + void MakeDecision(Solver *s, IntVar *variable1, IntVar *variable2) { if (operator_ == ">") { - IntExpr* difference = (s->MakeDifference(variable2, variable1)); + IntExpr *difference = (s->MakeDifference(variable2, variable1)); s->AddConstraint(s->MakeGreater(difference, value_)); } else if (operator_ == "=") { - IntExpr* difference = (s->MakeDifference(variable2, variable1)); + IntExpr *difference = (s->MakeDifference(variable2, variable1)); s->AddConstraint(s->MakeEquality(difference, value_)); } else { LOG(FATAL) << "No right operator specified."; } } - IntVar* const variable1_; - IntVar* const variable2_; + IntVar *const variable1_; + IntVar *const variable2_; const int value_; const std::string operator_; @@ -134,26 +132,26 @@ class OrderingDecision : public Decision { // Decision on whether a soft constraint will be added to a model // or if it will be violated. class ConstraintDecision : public Decision { - public: - explicit ConstraintDecision(IntVar* const constraint_violation) +public: + explicit ConstraintDecision(IntVar *const constraint_violation) : constraint_violation_(constraint_violation) {} ~ConstraintDecision() override {} // Apply will be called first when the decision is executed. - void Apply(Solver* const s) override { + void Apply(Solver *const s) override { // The constraint with which the builder is dealing, will be satisfied. constraint_violation_->SetValue(0); } // Refute will be called after a backtrack. - void Refute(Solver* const s) override { + void Refute(Solver *const s) override { // The constraint with which the builder is dealing, will not be satisfied. constraint_violation_->SetValue(1); } - private: - IntVar* const constraint_violation_; +private: + IntVar *const constraint_violation_; DISALLOW_COPY_AND_ASSIGN(ConstraintDecision); }; @@ -163,23 +161,23 @@ class ConstraintDecision : public Decision { // solving becomes much more efficient since we are branching on the // disjunction implied by the absolute value expression. class OrderingBuilder : public DecisionBuilder { - public: - enum Order { LESS = -1, EQUAL = 0, GREATER = 1 }; +public: + enum Order { + LESS = -1, + EQUAL = 0, + GREATER = 1 + }; - OrderingBuilder(const std::map& data_variables, - const std::vector& data_constraints, - const std::vector& variables, - const std::vector& violated_constraints, - const std::map& index_from_key) - : data_variables_(data_variables), - data_constraints_(data_constraints), - variables_(variables), - violated_constraints_(violated_constraints), - index_from_key_(index_from_key), - size_(data_constraints.size()), - iter_(0), - checked_iter_(0) { - for (const auto& it : data_variables_) { + OrderingBuilder(const std::map &data_variables, + const std::vector &data_constraints, + const std::vector &variables, + const std::vector &violated_constraints, + const std::map &index_from_key) + : data_variables_(data_variables), data_constraints_(data_constraints), + variables_(variables), violated_constraints_(violated_constraints), + index_from_key_(index_from_key), size_(data_constraints.size()), + iter_(0), checked_iter_(0) { + for (const auto &it : data_variables_) { int first_element = (it.second.domain)[0]; minimum_value_available_.push_back(first_element); variable_state_.push_back(EQUAL); @@ -190,13 +188,13 @@ class OrderingBuilder : public DecisionBuilder { ~OrderingBuilder() override {} - Decision* Next(Solver* const s) override { + Decision *Next(Solver *const s) override { if (iter_ < size_) { FapConstraint constraint = data_constraints_[iter_]; const int index1 = gtl::FindOrDie(index_from_key_, constraint.variable1); const int index2 = gtl::FindOrDie(index_from_key_, constraint.variable2); - IntVar* variable1 = variables_[index1]; - IntVar* variable2 = variables_[index2]; + IntVar *variable1 = variables_[index1]; + IntVar *variable2 = variables_[index2]; // checked_iter is equal to 0 means that whether the constraint is to be // added or dropped hasn't been checked. @@ -204,7 +202,7 @@ class OrderingBuilder : public DecisionBuilder { // of the constraint is to be done. if (!checked_iter_ && !constraint.hard) { // New Soft Constraint: Check if it will be added or dropped. - ConstraintDecision* constraint_decision = + ConstraintDecision *constraint_decision = new ConstraintDecision(violated_constraints_[iter_]); s->SaveAndAdd(&checked_iter_, 1); @@ -215,7 +213,7 @@ class OrderingBuilder : public DecisionBuilder { if (violated_constraints_[iter_]->Bound() && violated_constraints_[iter_]->Value() == 0) { // If the constraint is added, do the ordering of its variables. - OrderingDecision* ordering_decision; + OrderingDecision *ordering_decision; Order hint = Hint(constraint); if (hint == LESS || hint == EQUAL) { ordering_decision = new OrderingDecision( @@ -239,7 +237,7 @@ class OrderingBuilder : public DecisionBuilder { } } - private: +private: Order Variable1LessVariable2(const int variable1, const int variable2, const int value) { minimum_value_available_[variable2] = @@ -268,7 +266,7 @@ class OrderingBuilder : public DecisionBuilder { // variable2. This ordering is more efficient if used with the // Solver::ASSIGN_MIN_VALUE value selection strategy. // It returns 1 if variable1 > variable2 or -1 if variable1 < variable2. - Order Hint(const FapConstraint& constraint) { + Order Hint(const FapConstraint &constraint) { const int id1 = constraint.variable1; const int id2 = constraint.variable2; const int variable1 = gtl::FindOrDie(index_from_key_, id1); @@ -306,8 +304,8 @@ class OrderingBuilder : public DecisionBuilder { // Passed as arguments from the function that creates the Decision Builder. const std::map data_variables_; const std::vector data_constraints_; - const std::vector variables_; - const std::vector violated_constraints_; + const std::vector variables_; + const std::vector violated_constraints_; const std::map index_from_key_; // Used by Next() for monitoring decisions. const int size_; @@ -330,12 +328,12 @@ bool ConstraintImpactComparator(FapConstraint constraint1, } int64 ValueEvaluator( - absl::flat_hash_map>* value_evaluator_map, + absl::flat_hash_map > *value_evaluator_map, int64 variable_index, int64 value) { CHECK(value_evaluator_map != nullptr); // Evaluate the choice. Smaller ranking denotes a better choice. int64 ranking = -1; - for (const auto& it : *value_evaluator_map) { + for (const auto &it : *value_evaluator_map) { if ((it.first != variable_index) && (it.second.first == value)) { ranking = -2; break; @@ -343,7 +341,7 @@ int64 ValueEvaluator( } // Update the history of assigned values and their rankings of each variable. - absl::flat_hash_map>::iterator it; + absl::flat_hash_map >::iterator it; int64 new_value = value; int64 new_ranking = ranking; if ((it = value_evaluator_map->find(variable_index)) != @@ -367,8 +365,8 @@ int64 ValueEvaluator( // The variables which participate in more constraints and have the // smaller domain should be in higher priority for assignment. -int64 VariableEvaluator(const std::vector& key_from_index, - const std::map& data_variables, +int64 VariableEvaluator(const std::vector &key_from_index, + const std::map &data_variables, int64 variable_index) { FapVariable variable = gtl::FindOrDie(data_variables, key_from_index[variable_index]); @@ -377,10 +375,11 @@ int64 VariableEvaluator(const std::vector& key_from_index, } // Creates the variables of the solver from the parsed data. -void CreateModelVariables(const std::map& data_variables, - Solver* solver, std::vector* model_variables, - std::map* index_from_key, - std::vector* key_from_index) { +void CreateModelVariables(const std::map &data_variables, + Solver *solver, + std::vector *model_variables, + std::map *index_from_key, + std::vector *key_from_index) { CHECK(solver != nullptr); CHECK(model_variables != nullptr); CHECK(index_from_key != nullptr); @@ -391,7 +390,7 @@ void CreateModelVariables(const std::map& data_variables, key_from_index->resize(number_of_variables); int index = 0; - for (const auto& it : data_variables) { + for (const auto &it : data_variables) { CHECK_LT(index, model_variables->size()); (*model_variables)[index] = solver->MakeIntVar(it.second.domain); gtl::InsertOrUpdate(index_from_key, it.first, index); @@ -407,20 +406,20 @@ void CreateModelVariables(const std::map& data_variables, } // Creates the constraints of the instance from the parsed data. -void CreateModelConstraints(const std::vector& data_constraints, - const std::vector& variables, - const std::map& index_from_key, - Solver* solver) { +void CreateModelConstraints(const std::vector &data_constraints, + const std::vector &variables, + const std::map &index_from_key, + Solver *solver) { CHECK(solver != nullptr); - for (const FapConstraint& ct : data_constraints) { + for (const FapConstraint &ct : data_constraints) { const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); CHECK_LT(index1, variables.size()); CHECK_LT(index2, variables.size()); - IntVar* var1 = variables[index1]; - IntVar* var2 = variables[index2]; - IntVar* absolute_difference = + IntVar *var1 = variables[index1]; + IntVar *var2 = variables[index2]; + IntVar *absolute_difference = solver->MakeAbs(solver->MakeDifference(var1, var2))->Var(); if (ct.operation == ">") { solver->AddConstraint(solver->MakeGreater(absolute_difference, ct.value)); @@ -436,67 +435,69 @@ void CreateModelConstraints(const std::vector& data_constraints, // According to the value of a command line flag, chooses the strategy which // determines the selection of the variable to be assigned next. -void ChooseVariableStrategy(Solver::IntVarStrategy* variable_strategy) { +void ChooseVariableStrategy(Solver::IntVarStrategy *variable_strategy) { CHECK(variable_strategy != nullptr); - switch (FLAGS_choose_next_variable_strategy) { - case 1: { - *variable_strategy = Solver::CHOOSE_FIRST_UNBOUND; - LOG(INFO) << "Using Solver::CHOOSE_FIRST_UNBOUND " - "for variable selection strategy."; - break; - } - case 2: { - *variable_strategy = Solver::CHOOSE_MIN_SIZE_LOWEST_MIN; - LOG(INFO) << "Using Solver::CHOOSE_MIN_SIZE_LOWEST_MIN " - "for variable selection strategy."; - break; - } - case 3: { - *variable_strategy = Solver::CHOOSE_MIN_SIZE_HIGHEST_MAX; - LOG(INFO) << "Using Solver::CHOOSE_MIN_SIZE_HIGHEST_MAX " - "for variable selection strategy."; - break; - } - case 4: { - *variable_strategy = Solver::CHOOSE_RANDOM; - LOG(INFO) << "Using Solver::CHOOSE_RANDOM " - "for variable selection strategy."; - break; - } - default: { - LOG(FATAL) << "Should not be here"; - return; - } + switch (absl::GetFlag(FLAGS_choose_next_variable_strategy)) { + case 1: { + *variable_strategy = Solver::CHOOSE_FIRST_UNBOUND; + LOG(INFO) << "Using Solver::CHOOSE_FIRST_UNBOUND " + "for variable selection strategy."; + break; + } + case 2: { + *variable_strategy = Solver::CHOOSE_MIN_SIZE_LOWEST_MIN; + LOG(INFO) << "Using Solver::CHOOSE_MIN_SIZE_LOWEST_MIN " + "for variable selection strategy."; + break; + } + case 3: { + *variable_strategy = Solver::CHOOSE_MIN_SIZE_HIGHEST_MAX; + LOG(INFO) << "Using Solver::CHOOSE_MIN_SIZE_HIGHEST_MAX " + "for variable selection strategy."; + break; + } + case 4: { + *variable_strategy = Solver::CHOOSE_RANDOM; + LOG(INFO) << "Using Solver::CHOOSE_RANDOM " + "for variable selection strategy."; + break; + } + default: { + LOG(FATAL) << "Should not be here"; + return; + } } } // According to the values of some command line flags, adds some monitors // for the search of the Solver. -void CreateAdditionalMonitors(OptimizeVar* const objective, Solver* solver, - std::vector* monitors) { +void CreateAdditionalMonitors(OptimizeVar *const objective, Solver *solver, + std::vector *monitors) { CHECK(solver != nullptr); CHECK(monitors != nullptr); // Search Log - if (FLAGS_log_search) { - SearchMonitor* const log = solver->MakeSearchLog(100000, objective); + if (absl::GetFlag(FLAGS_log_search)) { + SearchMonitor *const log = solver->MakeSearchLog(100000, objective); monitors->push_back(log); } // Time Limit - if (FLAGS_time_limit_in_ms != 0) { - LOG(INFO) << "Adding time limit of " << FLAGS_time_limit_in_ms << " ms."; - SearchLimit* const limit = solver->MakeLimit( - FLAGS_time_limit_in_ms, kint64max, kint64max, kint64max); + if (absl::GetFlag(FLAGS_time_limit_in_ms) != 0) { + LOG(INFO) << "Adding time limit of " + << absl::GetFlag(FLAGS_time_limit_in_ms) << " ms."; + SearchLimit *const limit = solver->MakeLimit( + absl::GetFlag(FLAGS_time_limit_in_ms), kint64max, kint64max, kint64max); monitors->push_back(limit); } // Search Restart - SearchMonitor* const restart = - FLAGS_restart != -1 - ? (FLAGS_luby ? solver->MakeLubyRestart(FLAGS_restart) - : solver->MakeConstantRestart(FLAGS_restart)) + SearchMonitor *const restart = + absl::GetFlag(FLAGS_restart) != -1 + ? (absl::GetFlag(FLAGS_luby) + ? solver->MakeLubyRestart(absl::GetFlag(FLAGS_restart)) + : solver->MakeConstantRestart(absl::GetFlag(FLAGS_restart))) : nullptr; if (restart) { monitors->push_back(restart); @@ -507,15 +508,15 @@ void CreateAdditionalMonitors(OptimizeVar* const objective, Solver* solver, // instances of the problem with objective either the minimization of // the largest frequency assigned or the minimization of the number // of frequencies used to the solution. -void HardFapSolver(const std::map& data_variables, - const std::vector& data_constraints, - const std::string& data_objective, - const std::vector& values) { +void HardFapSolver(const std::map &data_variables, + const std::vector &data_constraints, + const std::string &data_objective, + const std::vector &values) { Solver solver("HardFapSolver"); - std::vector monitors; + std::vector monitors; // Create Model Variables. - std::vector variables; + std::vector variables; std::map index_from_key; std::vector key_from_index; CreateModelVariables(data_variables, &solver, &variables, &index_from_key, @@ -529,15 +530,15 @@ void HardFapSolver(const std::map& data_variables, std::sort(ordered_constraints.begin(), ordered_constraints.end(), ConstraintImpactComparator); - std::vector violated_constraints; + std::vector violated_constraints; solver.MakeIntVarArray(ordered_constraints.size(), 0, 0, &violated_constraints); // Objective: // Either minimize the largest assigned frequency or // minimize the number of different frequencies assigned. - IntVar* objective_var; - OptimizeVar* objective; + IntVar *objective_var; + OptimizeVar *objective; if (data_objective == "Minimize the largest assigned value.") { LOG(INFO) << "Minimize the largest assigned value."; // The objective_var is set to hold the maximum value assigned @@ -547,11 +548,11 @@ void HardFapSolver(const std::map& data_variables, } else if (data_objective == "Minimize the number of assigned values.") { LOG(INFO) << "Minimize the number of assigned values."; - std::vector cardinality; + std::vector cardinality; solver.MakeIntVarArray(static_cast(values.size()), 0, static_cast(variables.size()), &cardinality); solver.AddConstraint(solver.MakeDistribute(variables, values, cardinality)); - std::vector value_not_assigned; + std::vector value_not_assigned; for (int val = 0; val < values.size(); ++val) { value_not_assigned.push_back( solver.MakeIsEqualCstVar(cardinality[val], 0)); @@ -568,7 +569,7 @@ void HardFapSolver(const std::map& data_variables, monitors.push_back(objective); // Ordering Builder - OrderingBuilder* ob = solver.RevAlloc( + OrderingBuilder *ob = solver.RevAlloc( new OrderingBuilder(data_variables, ordered_constraints, variables, violated_constraints, index_from_key)); @@ -577,14 +578,15 @@ void HardFapSolver(const std::map& data_variables, Solver::IntVarStrategy variable_strategy; ChooseVariableStrategy(&variable_strategy); // Choose the value selection strategy. - DecisionBuilder* db; - absl::flat_hash_map> history; - if (FLAGS_value_evaluator == "value_evaluator") { + DecisionBuilder *db; + absl::flat_hash_map > history; + if (absl::GetFlag(FLAGS_value_evaluator) == "value_evaluator") { LOG(INFO) << "Using ValueEvaluator for value selection strategy."; - Solver::IndexEvaluator2 index_evaluator2 = [&history](int64 var, - int64 value) { + Solver::IndexEvaluator2 index_evaluator2 = + [&history](int64 var, int64 value) { return ValueEvaluator(&history, var, value); - }; + } + ; LOG(INFO) << "Using ValueEvaluator for value selection strategy."; db = solver.MakePhase(variables, variable_strategy, index_evaluator2); } else { @@ -593,13 +595,13 @@ void HardFapSolver(const std::map& data_variables, Solver::ASSIGN_MIN_VALUE); } - DecisionBuilder* final_db = solver.Compose(ob, db); + DecisionBuilder *final_db = solver.Compose(ob, db); // Create Additional Monitors. CreateAdditionalMonitors(objective, &solver, &monitors); // Collector - SolutionCollector* const collector = solver.MakeLastSolutionCollector(); + SolutionCollector *const collector = solver.MakeLastSolutionCollector(); collector->Add(variables); collector->Add(objective_var); monitors.push_back(collector); @@ -611,21 +613,21 @@ void HardFapSolver(const std::map& data_variables, const int64 time2 = solver.wall_time(); // Display Time. - if (FLAGS_display_time) { + if (absl::GetFlag(FLAGS_display_time)) { PrintElapsedTime(time1, time2); } // Display Results. - if (FLAGS_display_results) { + if (absl::GetFlag(FLAGS_display_results)) { PrintResultsHard(collector, variables, objective_var, data_variables, data_constraints, index_from_key, key_from_index); } } // Splits variables of the instance to hard and soft. -void SplitVariablesHardSoft(const std::map& data_variables, - std::map* hard_variables, - std::map* soft_variables) { - for (const auto& it : data_variables) { +void SplitVariablesHardSoft(const std::map &data_variables, + std::map *hard_variables, + std::map *soft_variables) { + for (const auto &it : data_variables) { if (it.second.initial_position != -1) { if (it.second.hard) { CHECK_LT(it.second.mobility_cost, 0); @@ -639,10 +641,10 @@ void SplitVariablesHardSoft(const std::map& data_variables, } // Splits constraints of the instance to hard and soft. -void SplitConstraintHardSoft(const std::vector& data_constraints, - std::vector* hard_constraints, - std::vector* soft_constraints) { - for (const FapConstraint& ct : data_constraints) { +void SplitConstraintHardSoft(const std::vector &data_constraints, + std::vector *hard_constraints, + std::vector *soft_constraints) { + for (const FapConstraint &ct : data_constraints) { if (ct.hard) { CHECK_LT(ct.weight_cost, 0); hard_constraints->push_back(ct); @@ -655,17 +657,17 @@ void SplitConstraintHardSoft(const std::vector& data_constraints, // Penalize the modification of the initial position of soft variable of // the instance. -void PenalizeVariablesViolation( - const std::map& soft_variables, - const std::map& index_from_key, - const std::vector& variables, std::vector* cost, - Solver* solver) { - for (const auto& it : soft_variables) { +void +PenalizeVariablesViolation(const std::map &soft_variables, + const std::map &index_from_key, + const std::vector &variables, + std::vector *cost, Solver *solver) { + for (const auto &it : soft_variables) { const int index = gtl::FindOrDie(index_from_key, it.first); CHECK_LT(index, variables.size()); - IntVar* const displaced = solver->MakeIsDifferentCstVar( + IntVar *const displaced = solver->MakeIsDifferentCstVar( variables[index], it.second.initial_position); - IntVar* const weight = + IntVar *const weight = solver->MakeProd(displaced, it.second.mobility_cost)->Var(); cost->push_back(weight); } @@ -673,34 +675,31 @@ void PenalizeVariablesViolation( // Penalize the violation of soft constraints of the instance. void PenalizeConstraintsViolation( - const std::vector& constraints, - const std::vector& soft_constraints, - const std::map& index_from_key, - const std::vector& variables, std::vector* cost, - std::vector* violated_constraints, Solver* solver) { + const std::vector &constraints, + const std::vector &soft_constraints, + const std::map &index_from_key, + const std::vector &variables, std::vector *cost, + std::vector *violated_constraints, Solver *solver) { int violated_constraints_index = 0; - for (const FapConstraint& ct : constraints) { + for (const FapConstraint &ct : constraints) { CHECK_LT(violated_constraints_index, violated_constraints->size()); if (!ct.hard) { // The violated_constraints_index will stop at the first soft constraint. break; } - IntVar* const hard_violation = solver->MakeIntVar(0, 0); + IntVar *const hard_violation = solver->MakeIntVar(0, 0); (*violated_constraints)[violated_constraints_index] = hard_violation; violated_constraints_index++; } - for (const FapConstraint& ct : soft_constraints) { + for (const FapConstraint &ct : soft_constraints) { const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); CHECK_LT(index1, variables.size()); CHECK_LT(index2, variables.size()); - IntVar* const absolute_difference = - solver - ->MakeAbs( - solver->MakeDifference(variables[index1], variables[index2])) - ->Var(); - IntVar* violation = nullptr; + IntVar *const absolute_difference = solver->MakeAbs(solver->MakeDifference( + variables[index1], variables[index2]))->Var(); + IntVar *violation = nullptr; if (ct.operation == ">") { violation = solver->MakeIsLessCstVar(absolute_difference, ct.value); } else if (ct.operation == "=") { @@ -708,7 +707,7 @@ void PenalizeConstraintsViolation( } else { LOG(FATAL) << "Invalid operator detected."; } - IntVar* const weight = solver->MakeProd(violation, ct.weight_cost)->Var(); + IntVar *const weight = solver->MakeProd(violation, ct.weight_cost)->Var(); cost->push_back(weight); CHECK_LT(violated_constraints_index, violated_constraints->size()); (*violated_constraints)[violated_constraints_index] = violation; @@ -720,12 +719,12 @@ void PenalizeConstraintsViolation( // The Soft Solver is dealing with the optimization of unfeasible instances // and aims to minimize the total cost of violated constraints. Returning value // equal to 0 denotes that the instance is feasible. -int SoftFapSolver(const std::map& data_variables, - const std::vector& data_constraints, - const std::string& data_objective, - const std::vector& values) { +int SoftFapSolver(const std::map &data_variables, + const std::vector &data_constraints, + const std::string &data_objective, + const std::vector &values) { Solver solver("SoftFapSolver"); - std::vector monitors; + std::vector monitors; // Split variables to hard and soft. std::map hard_variables; @@ -743,7 +742,7 @@ int SoftFapSolver(const std::map& data_variables, &soft_constraints); // Create Model Variables. - std::vector variables; + std::vector variables; std::map index_from_key; std::vector key_from_index; CreateModelVariables(data_variables, &solver, &variables, &index_from_key, @@ -753,9 +752,9 @@ int SoftFapSolver(const std::map& data_variables, CreateModelConstraints(hard_constraints, variables, index_from_key, &solver); // Penalize variable and constraint violations. - std::vector cost; - std::vector violated_constraints(ordered_constraints.size(), - nullptr); + std::vector cost; + std::vector violated_constraints(ordered_constraints.size(), + nullptr); PenalizeVariablesViolation(soft_variables, index_from_key, variables, &cost, &solver); PenalizeConstraintsViolation(ordered_constraints, soft_constraints, @@ -764,25 +763,26 @@ int SoftFapSolver(const std::map& data_variables, // Objective // Minimize the sum of violation penalties. - IntVar* objective_var = solver.MakeSum(cost)->Var(); - OptimizeVar* objective = solver.MakeMinimize(objective_var, 1); + IntVar *objective_var = solver.MakeSum(cost)->Var(); + OptimizeVar *objective = solver.MakeMinimize(objective_var, 1); monitors.push_back(objective); // Ordering Builder - OrderingBuilder* ob = solver.RevAlloc( + OrderingBuilder *ob = solver.RevAlloc( new OrderingBuilder(data_variables, ordered_constraints, variables, violated_constraints, index_from_key)); // Decision Builder Configuration // Choose the next variable selection strategy. - DecisionBuilder* db; - if (FLAGS_variable_evaluator == "variable_evaluator") { + DecisionBuilder *db; + if (absl::GetFlag(FLAGS_variable_evaluator) == "variable_evaluator") { LOG(INFO) << "Using VariableEvaluator for variable selection strategy and " "Solver::ASSIGN_MIN_VALUE for value selection strategy."; - Solver::IndexEvaluator1 var_evaluator = [&key_from_index, - &data_variables](int64 index) { + Solver::IndexEvaluator1 var_evaluator = + [&key_from_index, &data_variables](int64 index) { return VariableEvaluator(key_from_index, data_variables, index); - }; + } + ; db = solver.MakePhase(variables, var_evaluator, Solver::ASSIGN_MIN_VALUE); } else { LOG(INFO) << "Using Solver::CHOOSE_FIRST_UNBOUND for variable selection " @@ -791,13 +791,13 @@ int SoftFapSolver(const std::map& data_variables, db = solver.MakePhase(variables, Solver::CHOOSE_FIRST_UNBOUND, Solver::ASSIGN_MIN_VALUE); } - DecisionBuilder* final_db = solver.Compose(ob, db); + DecisionBuilder *final_db = solver.Compose(ob, db); // Create Additional Monitors. CreateAdditionalMonitors(objective, &solver, &monitors); // Collector - SolutionCollector* const collector = solver.MakeLastSolutionCollector(); + SolutionCollector *const collector = solver.MakeLastSolutionCollector(); collector->Add(variables); collector->Add(objective_var); monitors.push_back(collector); @@ -811,11 +811,11 @@ int SoftFapSolver(const std::map& data_variables, int violation_sum = collector->Value(collector->solution_count() - 1, objective_var); // Display Time. - if (FLAGS_display_time) { + if (absl::GetFlag(FLAGS_display_time)) { PrintElapsedTime(time1, time2); } // Display Results. - if (FLAGS_display_results) { + if (absl::GetFlag(FLAGS_display_results)) { PrintResultsSoft(collector, variables, objective_var, hard_variables, hard_constraints, soft_variables, soft_constraints, index_from_key, key_from_index); @@ -824,9 +824,9 @@ int SoftFapSolver(const std::map& data_variables, return violation_sum; } -void SolveProblem(const std::map& variables, - const std::vector& constraints, - const std::string& objective, const std::vector& values, +void SolveProblem(const std::map &variables, + const std::vector &constraints, + const std::string &objective, const std::vector &values, bool soft) { // Print Instance! FapModelPrinter model_printer(variables, constraints, objective, values); @@ -850,35 +850,37 @@ void SolveProblem(const std::map& variables, } } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK(!FLAGS_directory.empty()) << "Requires --directory="; + CHECK(!absl::GetFlag(FLAGS_directory).empty()) + << "Requires --directory="; - LOG(INFO) << "Solving instance in directory " << FLAGS_directory; + LOG(INFO) << "Solving instance in directory " + << absl::GetFlag(FLAGS_directory); // Parse! std::map variables; std::vector constraints; std::string objective; std::vector values; absl::flat_hash_map components; - operations_research::ParseInstance(FLAGS_directory, FLAGS_find_components, - &variables, &constraints, &objective, - &values, &components); - if (!FLAGS_find_components) { + operations_research::ParseInstance( + absl::GetFlag(FLAGS_directory), absl::GetFlag(FLAGS_find_components), + &variables, &constraints, &objective, &values, &components); + if (!absl::GetFlag(FLAGS_find_components)) { operations_research::SolveProblem(variables, constraints, objective, values, - FLAGS_soft); + absl::GetFlag(FLAGS_soft)); } else { int component_id = 1; LOG(INFO) << "Number of components in the RLFAP graph " << components.size(); - for (const auto& component : components) { + for (const auto &component : components) { LOG(INFO) << "Solving Component " << component_id; operations_research::SolveProblem(component.second.variables, component.second.constraints, objective, - values, FLAGS_soft); + values, absl::GetFlag(FLAGS_soft)); component_id++; } } diff --git a/examples/cpp/golomb_sat.cc b/examples/cpp/golomb_sat.cc index b69715f694..43b6ac4fdc 100644 --- a/examples/cpp/golomb_sat.cc +++ b/examples/cpp/golomb_sat.cc @@ -39,9 +39,11 @@ DEFINE_int32( "Size of the problem. If equal to 0, will test several increasing sizes."); DEFINE_string(params, "", "Sat parameters."); -static const int kBestSolutions[] = {0, 1, 3, 6, 11, 17, 25, 34, 44, 55, 72, 85, - // just for the optimistics ones, the rest: - 106, 127, 151, 177, 199, 216, 246}; +static const int kBestSolutions[] = { + 0, 1, 3, 6, 11, 17, 25, 34, 44, 55, 72, 85, + // just for the optimistics ones, the rest: + 106, 127, 151, 177, 199, 216, 246 +}; static const int kKnownSolutions = 19; @@ -63,7 +65,10 @@ void GolombRuler(int size) { for (int i = 0; i < size; ++i) { for (int j = i + 1; j < size; ++j) { const IntVar diff = cp_model.NewIntVar(domain); - cp_model.AddEquality(LinearExpr::Sum({diff, ticks[i]}), ticks[j]); + cp_model.AddEquality(LinearExpr::Sum({ + diff, ticks[i] + }), + ticks[j]); diffs.push_back(diff); } } @@ -86,10 +91,10 @@ void GolombRuler(int size) { SatParameters parameters; parameters.set_search_branching(SatParameters::FIXED_SEARCH); // Parse the --params flag. - if (!FLAGS_params.empty()) { - CHECK(google::protobuf::TextFormat::MergeFromString(FLAGS_params, - ¶meters)) - << FLAGS_params; + if (!absl::GetFlag(FLAGS_params).empty()) { + CHECK(google::protobuf::TextFormat::MergeFromString( + absl::GetFlag(FLAGS_params), ¶meters)) + << absl::GetFlag(FLAGS_params); } model.Add(NewSatParameters(parameters)); const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model); @@ -102,7 +107,7 @@ void GolombRuler(int size) { if (size - 1 < kKnownSolutions) { CHECK_EQ(result, kBestSolutions[size - 1]); } - if (FLAGS_print) { + if (absl::GetFlag(FLAGS_print)) { for (int i = 0; i < size; ++i) { const int64 tick = SolutionIntegerValue(response, ticks[i]); printf("%d ", static_cast(tick)); @@ -112,13 +117,13 @@ void GolombRuler(int size) { } } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_size != 0) { - operations_research::sat::GolombRuler(FLAGS_size); + if (absl::GetFlag(FLAGS_size) != 0) { + operations_research::sat::GolombRuler(absl::GetFlag(FLAGS_size)); } else { for (int n = 1; n < 11; ++n) { operations_research::sat::GolombRuler(n); diff --git a/examples/cpp/integer_programming.cc b/examples/cpp/integer_programming.cc index fc7e9f79a5..15d731d770 100644 --- a/examples/cpp/integer_programming.cc +++ b/examples/cpp/integer_programming.cc @@ -18,7 +18,7 @@ #include "ortools/linear_solver/linear_solver.h" namespace operations_research { -void RunIntegerProgrammingExample(const std::string& solver_id) { +void RunIntegerProgrammingExample(const std::string &solver_id) { LOG(INFO) << "---- Integer programming example with " << solver_id << " ----"; MPSolver::OptimizationProblemType problem_type; @@ -36,22 +36,22 @@ void RunIntegerProgrammingExample(const std::string& solver_id) { const double infinity = solver.infinity(); // x and y are integer non-negative variables. - MPVariable* const x = solver.MakeIntVar(0.0, infinity, "x"); - MPVariable* const y = solver.MakeIntVar(0.0, infinity, "y"); + MPVariable *const x = solver.MakeIntVar(0.0, infinity, "x"); + MPVariable *const y = solver.MakeIntVar(0.0, infinity, "y"); // Maximize x + 10 * y. - MPObjective* const objective = solver.MutableObjective(); + MPObjective *const objective = solver.MutableObjective(); objective->SetCoefficient(x, 1); objective->SetCoefficient(y, 10); objective->SetMaximization(); // x + 7 * y <= 17.5. - MPConstraint* const c0 = solver.MakeRowConstraint(-infinity, 17.5); + MPConstraint *const c0 = solver.MakeRowConstraint(-infinity, 17.5); c0->SetCoefficient(x, 1); c0->SetCoefficient(y, 7); // x <= 3.5 - MPConstraint* const c1 = solver.MakeRowConstraint(-infinity, 3.5); + MPConstraint *const c1 = solver.MakeRowConstraint(-infinity, 3.5); c1->SetCoefficient(x, 1); c1->SetCoefficient(y, 0); @@ -83,12 +83,12 @@ void RunAllExamples() { RunIntegerProgrammingExample("GLPK"); RunIntegerProgrammingExample("CPLEX"); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - absl::SetFlag(&FLAGS_logtostderr, true); - absl::SetFlag(&FLAGS_log_prefix, false); + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); + absl::SetFlag(&absl::GetFlag(FLAGS_log_prefix), false); gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::RunAllExamples(); return 0; diff --git a/examples/cpp/jobshop_sat.cc b/examples/cpp/jobshop_sat.cc index 9401587222..5cb159cb3f 100644 --- a/examples/cpp/jobshop_sat.cc +++ b/examples/cpp/jobshop_sat.cc @@ -46,11 +46,11 @@ namespace operations_research { namespace sat { // Compute a valid horizon from a problem. -int64 ComputeHorizon(const JsspInputProblem& problem) { +int64 ComputeHorizon(const JsspInputProblem &problem) { int64 sum_of_durations = 0; int64 max_latest_end = 0; int64 max_earliest_start = 0; - for (const Job& job : problem.jobs()) { + for (const Job &job : problem.jobs()) { if (job.has_latest_end()) { max_latest_end = std::max(max_latest_end, job.latest_end().value()); } else { @@ -60,7 +60,7 @@ int64 ComputeHorizon(const JsspInputProblem& problem) { max_earliest_start = std::max(max_earliest_start, job.earliest_start().value()); } - for (const Task& task : job.tasks()) { + for (const Task &task : job.tasks()) { int64 max_duration = 0; for (int64 d : task.duration()) { max_duration = std::max(max_duration, d); @@ -71,9 +71,10 @@ int64 ComputeHorizon(const JsspInputProblem& problem) { const int num_jobs = problem.jobs_size(); int64 sum_of_transitions = 0; - for (const Machine& machine : problem.machines()) { - if (!machine.has_transition_time_matrix()) continue; - const TransitionTimeMatrix& matrix = machine.transition_time_matrix(); + for (const Machine &machine : problem.machines()) { + if (!machine.has_transition_time_matrix()) + continue; + const TransitionTimeMatrix &matrix = machine.transition_time_matrix(); for (int i = 0; i < num_jobs; ++i) { int64 max_transition = 0; for (int j = 0; j < num_jobs; ++j) { @@ -89,8 +90,8 @@ int64 ComputeHorizon(const JsspInputProblem& problem) { } // Solve a JobShop scheduling problem using SAT. -void Solve(const JsspInputProblem& problem) { - if (FLAGS_display_model) { +void Solve(const JsspInputProblem &problem) { + if (absl::GetFlag(FLAGS_display_model)) { LOG(INFO) << problem.DebugString(); } @@ -107,11 +108,11 @@ void Solve(const JsspInputProblem& problem) { const IntVar makespan = cp_model.NewIntVar(all_horizon); - std::vector> machine_to_intervals(num_machines); - std::vector> machine_to_jobs(num_machines); - std::vector> machine_to_starts(num_machines); - std::vector> machine_to_ends(num_machines); - std::vector> machine_to_presences(num_machines); + std::vector > machine_to_intervals(num_machines); + std::vector > machine_to_jobs(num_machines); + std::vector > machine_to_starts(num_machines); + std::vector > machine_to_ends(num_machines); + std::vector > machine_to_presences(num_machines); std::vector job_starts(num_jobs); std::vector job_ends(num_jobs); std::vector task_starts; @@ -120,7 +121,7 @@ void Solve(const JsspInputProblem& problem) { std::vector objective_coeffs; for (int j = 0; j < num_jobs; ++j) { - const Job& job = problem.jobs(j); + const Job &job = problem.jobs(j); IntVar previous_end; const int64 hard_start = job.has_earliest_start() ? job.earliest_start().value() : 0L; @@ -128,7 +129,7 @@ void Solve(const JsspInputProblem& problem) { job.has_latest_end() ? job.latest_end().value() : horizon; for (int t = 0; t < job.tasks_size(); ++t) { - const Task& task = job.tasks(t); + const Task &task = job.tasks(t); const int num_alternatives = task.machine_size(); CHECK_EQ(num_alternatives, task.duration_size()); @@ -177,19 +178,19 @@ void Solve(const JsspInputProblem& problem) { for (int a = 0; a < num_alternatives; ++a) { const BoolVar presence = cp_model.NewBoolVar(); const IntVar local_start = - FLAGS_use_optional_variables + absl::GetFlag(FLAGS_use_optional_variables) ? cp_model.NewIntVar(Domain(hard_start, hard_end)) : start; const IntVar local_duration = cp_model.NewConstant(task.duration(a)); const IntVar local_end = - FLAGS_use_optional_variables + absl::GetFlag(FLAGS_use_optional_variables) ? cp_model.NewIntVar(Domain(hard_start, hard_end)) : end; const IntervalVar local_interval = cp_model.NewOptionalIntervalVar( local_start, local_duration, local_end, presence); // Link local and global variables. - if (FLAGS_use_optional_variables) { + if (absl::GetFlag(FLAGS_use_optional_variables)) { cp_model.AddEquality(start, local_start).OnlyEnforceIf(presence); cp_model.AddEquality(end, local_end).OnlyEnforceIf(presence); @@ -237,8 +238,9 @@ void Solve(const JsspInputProblem& problem) { cp_model.AddEquality(shifted_var, LinearExpr(previous_end).AddConstant(-due_date)); const IntVar lateness_var = cp_model.NewIntVar(all_horizon); - cp_model.AddMaxEquality(lateness_var, - {cp_model.NewConstant(0), shifted_var}); + cp_model.AddMaxEquality(lateness_var, { + cp_model.NewConstant(0), shifted_var + }); objective_vars.push_back(lateness_var); objective_coeffs.push_back(lateness_penalty); } @@ -250,11 +252,14 @@ void Solve(const JsspInputProblem& problem) { if (due_date > 0) { const IntVar shifted_var = cp_model.NewIntVar(Domain(due_date - horizon, due_date)); - cp_model.AddEquality(LinearExpr::Sum({shifted_var, previous_end}), + cp_model.AddEquality(LinearExpr::Sum({ + shifted_var, previous_end + }), due_date); const IntVar earliness_var = cp_model.NewIntVar(all_horizon); - cp_model.AddMaxEquality(earliness_var, - {cp_model.NewConstant(0), shifted_var}); + cp_model.AddMaxEquality(earliness_var, { + cp_model.NewConstant(0), shifted_var + }); objective_vars.push_back(earliness_var); objective_coeffs.push_back(earliness_penalty); } @@ -266,7 +271,7 @@ void Solve(const JsspInputProblem& problem) { cp_model.AddNoOverlap(machine_to_intervals[m]); if (problem.machines(m).has_transition_time_matrix()) { - const TransitionTimeMatrix& transitions = + const TransitionTimeMatrix &transitions = problem.machines(m).transition_time_matrix(); const int num_intervals = machine_to_intervals[m].size(); @@ -292,9 +297,8 @@ void Solve(const JsspInputProblem& problem) { const IntVar end = machine_to_ends[m][i]; circuit.AddArc(i + 1, j + 1, lit); // Push the new start with an extra transition. - cp_model - .AddLessOrEqual(LinearExpr(end).AddConstant(transition), start) - .OnlyEnforceIf(lit); + cp_model.AddLessOrEqual(LinearExpr(end).AddConstant(transition), + start).OnlyEnforceIf(lit); } } } @@ -302,7 +306,7 @@ void Solve(const JsspInputProblem& problem) { } // Add job precedences. - for (const JobPrecedence& precedence : problem.precedences()) { + for (const JobPrecedence &precedence : problem.precedences()) { const IntVar start = job_starts[precedence.second_job_index()]; const IntVar end = job_ends[precedence.first_job_index()]; cp_model.AddLessOrEqual(LinearExpr(end).AddConstant(precedence.min_delay()), @@ -329,14 +333,14 @@ void Solve(const JsspInputProblem& problem) { LOG(INFO) << "#jobs:" << num_jobs; LOG(INFO) << "horizon:" << horizon; - if (FLAGS_display_sat_model) { + if (absl::GetFlag(FLAGS_display_sat_model)) { LOG(INFO) << cp_model.Proto().DebugString(); } LOG(INFO) << CpModelStats(cp_model.Proto()); Model model; - model.Add(NewSatParameters(FLAGS_params)); + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model); LOG(INFO) << CpSolverResponseStats(response); @@ -376,18 +380,18 @@ void Solve(const JsspInputProblem& problem) { CHECK_LE(response.objective_value(), final_cost + tolerance); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -int main(int argc, char** argv) { - absl::SetFlag(&FLAGS_logtostderr, true); +int main(int argc, char **argv) { + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_input.empty()) { + if (absl::GetFlag(FLAGS_input).empty()) { LOG(FATAL) << "Please supply a data file with --input="; } operations_research::data::jssp::JsspParser parser; - CHECK(parser.ParseFile(FLAGS_input)); + CHECK(parser.ParseFile(absl::GetFlag(FLAGS_input))); operations_research::sat::Solve(parser.problem()); return EXIT_SUCCESS; } diff --git a/examples/cpp/linear_assignment_api.cc b/examples/cpp/linear_assignment_api.cc index 4a7664e467..920d4153ab 100644 --- a/examples/cpp/linear_assignment_api.cc +++ b/examples/cpp/linear_assignment_api.cc @@ -25,10 +25,10 @@ void AssignmentOn4x4Matrix() { LOG(INFO) << "Assignment on 4x4 Matrix"; const int kNumSources = 4; const int kNumTargets = 4; - const CostValue kCost[kNumSources][kNumTargets] = {{90, 76, 75, 80}, - {35, 85, 55, 65}, - {125, 95, 90, 105}, - {45, 110, 95, 115}}; + const CostValue kCost[kNumSources][kNumTargets] = { { 90, 76, 75, 80 }, + { 35, 85, 55, 65 }, + { 125, 95, 90, 105 }, + { 45, 110, 95, 115 } }; const CostValue kExpectedCost = kCost[0][3] + kCost[1][2] + kCost[2][1] + kCost[3][0]; ForwardStarGraph graph(kNumSources + kNumTargets, kNumSources * kNumTargets); @@ -46,8 +46,12 @@ void AssignmentOn4x4Matrix() { void AnotherAssignment() { LOG(INFO) << "Another assignment on 4x4 matrix"; - std::vector> matrice( - {{8, 7, 9, 9}, {5, 2, 7, 8}, {6, 1, 4, 9}, {2, 3, 2, 6}}); + std::vector > matrice({ + { 8, 7, 9, 9 } + , { 5, 2, 7, 8 } + , { 6, 1, 4, 9 } + , { 2, 3, 2, 6 } + }); const int kSize = matrice.size(); ForwardStarGraph graph(2 * kSize, kSize * kSize); LinearSumAssignment assignement(graph, kSize); @@ -63,9 +67,9 @@ void AnotherAssignment() { LOG(INFO) << "Cost : " << assignement.GetCost(); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::AssignmentOn4x4Matrix(); operations_research::AnotherAssignment(); diff --git a/examples/cpp/linear_programming.cc b/examples/cpp/linear_programming.cc index fe7e6d2e90..53167afb6e 100644 --- a/examples/cpp/linear_programming.cc +++ b/examples/cpp/linear_programming.cc @@ -19,7 +19,7 @@ #include "ortools/linear_solver/linear_solver.pb.h" namespace operations_research { -void RunLinearProgrammingExample(const std::string& solver_id) { +void RunLinearProgrammingExample(const std::string &solver_id) { LOG(INFO) << "---- Linear programming example with " << solver_id << " ----"; MPSolver::OptimizationProblemType problem_type; if (!MPSolver::ParseSolverType(solver_id, &problem_type)) { @@ -36,31 +36,31 @@ void RunLinearProgrammingExample(const std::string& solver_id) { const double infinity = solver.infinity(); // x1, x2 and x3 are continuous non-negative variables. - MPVariable* const x1 = solver.MakeNumVar(0.0, infinity, "x1"); - MPVariable* const x2 = solver.MakeNumVar(0.0, infinity, "x2"); - MPVariable* const x3 = solver.MakeNumVar(0.0, infinity, "x3"); + MPVariable *const x1 = solver.MakeNumVar(0.0, infinity, "x1"); + MPVariable *const x2 = solver.MakeNumVar(0.0, infinity, "x2"); + MPVariable *const x3 = solver.MakeNumVar(0.0, infinity, "x3"); // Maximize 10 * x1 + 6 * x2 + 4 * x3. - MPObjective* const objective = solver.MutableObjective(); + MPObjective *const objective = solver.MutableObjective(); objective->SetCoefficient(x1, 10); objective->SetCoefficient(x2, 6); objective->SetCoefficient(x3, 4); objective->SetMaximization(); // x1 + x2 + x3 <= 100. - MPConstraint* const c0 = solver.MakeRowConstraint(-infinity, 100.0); + MPConstraint *const c0 = solver.MakeRowConstraint(-infinity, 100.0); c0->SetCoefficient(x1, 1); c0->SetCoefficient(x2, 1); c0->SetCoefficient(x3, 1); // 10 * x1 + 4 * x2 + 5 * x3 <= 600. - MPConstraint* const c1 = solver.MakeRowConstraint(-infinity, 600.0); + MPConstraint *const c1 = solver.MakeRowConstraint(-infinity, 600.0); c1->SetCoefficient(x1, 10); c1->SetCoefficient(x2, 4); c1->SetCoefficient(x3, 5); // 2 * x1 + 2 * x2 + 6 * x3 <= 300. - MPConstraint* const c2 = solver.MakeRowConstraint(-infinity, 300.0); + MPConstraint *const c2 = solver.MakeRowConstraint(-infinity, 300.0); c2->SetCoefficient(x1, 2); c2->SetCoefficient(x2, 2); c2->SetCoefficient(x3, 6); @@ -109,12 +109,12 @@ void RunAllExamples() { RunLinearProgrammingExample("GLPK_LP"); RunLinearProgrammingExample("XPRESS_LP"); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - absl::SetFlag(&FLAGS_logtostderr, true); - absl::SetFlag(&FLAGS_log_prefix, false); + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); + absl::SetFlag(&absl::GetFlag(FLAGS_log_prefix), false); gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::RunAllExamples(); return EXIT_SUCCESS; diff --git a/examples/cpp/linear_solver_protocol_buffers.cc b/examples/cpp/linear_solver_protocol_buffers.cc index c9757bb697..364a7b09e5 100644 --- a/examples/cpp/linear_solver_protocol_buffers.cc +++ b/examples/cpp/linear_solver_protocol_buffers.cc @@ -20,17 +20,17 @@ namespace operations_research { void BuildLinearProgrammingMaxExample(MPSolver::OptimizationProblemType type) { - const double kObjCoef[] = {10.0, 6.0, 4.0}; - const std::string kVarName[] = {"x1", "x2", "x3"}; + const double kObjCoef[] = { 10.0, 6.0, 4.0 }; + const std::string kVarName[] = { "x1", "x2", "x3" }; const int numVars = 3; const int kNumConstraints = 3; - const std::string kConstraintName[] = {"c1", "c2", "c3"}; - const double kConstraintCoef1[] = {1.0, 1.0, 1.0}; - const double kConstraintCoef2[] = {10.0, 4.0, 5.0}; - const double kConstraintCoef3[] = {2.0, 2.0, 6.0}; - const double* kConstraintCoef[] = {kConstraintCoef1, kConstraintCoef2, - kConstraintCoef3}; - const double kConstraintUb[] = {100.0, 600.0, 300.0}; + const std::string kConstraintName[] = { "c1", "c2", "c3" }; + const double kConstraintCoef1[] = { 1.0, 1.0, 1.0 }; + const double kConstraintCoef2[] = { 10.0, 4.0, 5.0 }; + const double kConstraintCoef3[] = { 2.0, 2.0, 6.0 }; + const double *kConstraintCoef[] = { kConstraintCoef1, kConstraintCoef2, + kConstraintCoef3 }; + const double kConstraintUb[] = { 100.0, 600.0, 300.0 }; const double infinity = MPSolver::infinity(); MPModelProto model_proto; @@ -38,20 +38,20 @@ void BuildLinearProgrammingMaxExample(MPSolver::OptimizationProblemType type) { // Create variables and objective function for (int j = 0; j < numVars; ++j) { - MPVariableProto* x = model_proto.add_variable(); - x->set_name(kVarName[j]); // Could be skipped (optional). + MPVariableProto *x = model_proto.add_variable(); + x->set_name(kVarName[j]); // Could be skipped (optional). x->set_lower_bound(0.0); - x->set_upper_bound(infinity); // Could be skipped (default value). - x->set_is_integer(false); // Could be skipped (default value). + x->set_upper_bound(infinity); // Could be skipped (default value). + x->set_is_integer(false); // Could be skipped (default value). x->set_objective_coefficient(kObjCoef[j]); } model_proto.set_maximize(true); // Create constraints for (int i = 0; i < kNumConstraints; ++i) { - MPConstraintProto* constraint_proto = model_proto.add_constraint(); - constraint_proto->set_name(kConstraintName[i]); // Could be skipped. - constraint_proto->set_lower_bound(-infinity); // Could be skipped. + MPConstraintProto *constraint_proto = model_proto.add_constraint(); + constraint_proto->set_name(kConstraintName[i]); // Could be skipped. + constraint_proto->set_lower_bound(-infinity); // Could be skipped. constraint_proto->set_upper_bound(kConstraintUb[i]); for (int j = 0; j < numVars; ++j) { // These two lines may be skipped when the coefficient is zero. @@ -66,12 +66,12 @@ void BuildLinearProgrammingMaxExample(MPSolver::OptimizationProblemType type) { if (type == MPSolver::GLOP_LINEAR_PROGRAMMING) { model_request.set_solver_type(MPModelRequest::GLOP_LINEAR_PROGRAMMING); } -#endif // USE_GLOP +#endif // USE_GLOP #if defined(USE_CLP) if (type == MPSolver::CLP_LINEAR_PROGRAMMING) { model_request.set_solver_type(MPModelRequest::CLP_LINEAR_PROGRAMMING); } -#endif // USE_CLP +#endif // USE_CLP MPSolutionResponse solution_response; MPSolver::SolveWithProto(model_request, &solution_response); @@ -90,15 +90,15 @@ void RunAllExamples() { #if defined(USE_GLOP) LOG(INFO) << "----- Running Max Example with GLOP -----"; BuildLinearProgrammingMaxExample(MPSolver::GLOP_LINEAR_PROGRAMMING); -#endif // USE_GLOP +#endif // USE_GLOP #if defined(USE_CLP) LOG(INFO) << "----- Running Max Example with Coin LP -----"; BuildLinearProgrammingMaxExample(MPSolver::CLP_LINEAR_PROGRAMMING); -#endif // USE_CLP +#endif // USE_CLP } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::RunAllExamples(); return EXIT_SUCCESS; diff --git a/examples/cpp/magic_square_sat.cc b/examples/cpp/magic_square_sat.cc index e7b7d0cac9..e7bbb71793 100644 --- a/examples/cpp/magic_square_sat.cc +++ b/examples/cpp/magic_square_sat.cc @@ -28,8 +28,8 @@ namespace sat { void MagicSquare(int size) { CpModelBuilder builder; - std::vector> square(size); - std::vector> transposed(size); + std::vector > square(size); + std::vector > transposed(size); std::vector diag1; std::vector diag2; std::vector all_variables; @@ -70,7 +70,7 @@ void MagicSquare(int size) { builder.AddEquality(LinearExpr::Sum(diag2), sum); Model model; - model.Add(NewSatParameters(FLAGS_params)); + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); const CpSolverResponse response = SolveCpModel(builder.Build(), &model); @@ -89,12 +89,12 @@ void MagicSquare(int size) { LOG(INFO) << CpSolverResponseStats(response); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research int main(int argc, char **argv) { - absl::SetFlag(&FLAGS_logtostderr, true); + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); gflags::ParseCommandLineFlags(&argc, &argv, true); - operations_research::sat::MagicSquare(FLAGS_size); + operations_research::sat::MagicSquare(absl::GetFlag(FLAGS_size)); return EXIT_SUCCESS; } diff --git a/examples/cpp/max_flow.cc b/examples/cpp/max_flow.cc index 0b119f34de..3491d18a73 100644 --- a/examples/cpp/max_flow.cc +++ b/examples/cpp/max_flow.cc @@ -22,12 +22,13 @@ void SolveMaxFlow() { // Can't use std::tuple // Initialization list is not working on std:tuple cf. N4387 // Arc are stored as {{begin_node, end_node}, capacity} - std::vector, FlowQuantity>> arcs = { - {{0, 1}, 20}, {{0, 2}, 30}, {{0, 3}, 10}, {{1, 2}, 40}, {{1, 4}, 30}, - {{2, 3}, 10}, {{2, 4}, 20}, {{3, 2}, 5}, {{3, 4}, 20}}; + std::vector, FlowQuantity> > arcs = + { { { 0, 1 }, 20 }, { { 0, 2 }, 30 }, { { 0, 3 }, 10 }, { { 1, 2 }, 40 }, + { { 1, 4 }, 30 }, { { 2, 3 }, 10 }, { { 2, 4 }, 20 }, { { 3, 2 }, 5 }, + { { 3, 4 }, 20 } }; StarGraph graph(num_nodes, arcs.size()); MaxFlow max_flow(&graph, 0, num_nodes - 1); - for (const auto& it : arcs) { + for (const auto &it : arcs) { ArcIndex arc = graph.AddArc(it.first.first, it.first.second); max_flow.SetArcCapacity(arc, it.second); } @@ -49,11 +50,11 @@ void SolveMaxFlow() { << max_flow.Flow(i) << " / " << max_flow.Capacity(i); } } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - FLAGS_logtostderr = 1; + absl::GetFlag(FLAGS_logtostderr) = 1; operations_research::SolveMaxFlow(); return EXIT_SUCCESS; } diff --git a/examples/cpp/min_cost_flow.cc b/examples/cpp/min_cost_flow.cc index 2e57a31770..294530b547 100644 --- a/examples/cpp/min_cost_flow.cc +++ b/examples/cpp/min_cost_flow.cc @@ -24,17 +24,19 @@ struct Arc { void SolveMinCostFlow() { // Define supply of each node. - const std::vector> supplies = { - {0, 20}, {1, 0}, {2, 0}, {3, -5}, {4, -15}}; + const std::vector > supplies = { + { 0, 20 }, { 1, 0 }, { 2, 0 }, { 3, -5 }, { 4, -15 } + }; // Define each arc // Can't use std::tuple // Initialization list is not working on std:tuple cf. N4387 // Arc are stored as {{begin_node, end_node}, capacity} - const std::vector arcs = { - {{0, 1}, 15, 4}, {{0, 2}, 8, 4}, {{1, 2}, 20, 2}, - {{1, 3}, 4, 2}, {{1, 4}, 10, 6}, {{2, 3}, 15, 1}, - {{2, 4}, 4, 3}, {{3, 4}, 20, 2}, {{4, 2}, 5, 3}}; + const std::vector arcs = { { { 0, 1 }, 15, 4 }, { { 0, 2 }, 8, 4 }, + { { 1, 2 }, 20, 2 }, { { 1, 3 }, 4, 2 }, + { { 1, 4 }, 10, 6 }, { { 2, 3 }, 15, 1 }, + { { 2, 4 }, 4, 3 }, { { 3, 4 }, 20, 2 }, + { { 4, 2 }, 5, 3 } }; StarGraph graph(supplies.size(), arcs.size()); MinCostFlow min_cost_flow(&graph); @@ -65,11 +67,11 @@ void SolveMinCostFlow() { << " / " << min_cost_flow.UnitCost(i); } } -} // namespace operations_research +} // namespace operations_research int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - FLAGS_logtostderr = 1; + absl::GetFlag(FLAGS_logtostderr) = 1; operations_research::SolveMinCostFlow(); return EXIT_SUCCESS; } diff --git a/examples/cpp/mps_driver.cc b/examples/cpp/mps_driver.cc index ae605163d3..eecc12a1f4 100644 --- a/examples/cpp/mps_driver.cc +++ b/examples/cpp/mps_driver.cc @@ -44,10 +44,9 @@ DEFINE_bool(mps_display_full_path, true, "Displays the full path of the input file in the result line."); DEFINE_string(input, "", "File pattern for problems to be optimized."); DEFINE_string(params_file, "", "Path to a GlopParameters file in text format."); -DEFINE_string(params, "", - "GlopParameters in text format. If --params_file was " - "also specified, the --params will be merged onto " - "them (i.e. in case of conflicts, --params wins)"); +DEFINE_string(params, "", "GlopParameters in text format. If --params_file was " + "also specified, the --params will be merged onto " + "them (i.e. in case of conflicts, --params wins)"); using google::protobuf::TextFormat; using operations_research::FullProtocolMessageAsString; @@ -62,22 +61,22 @@ using operations_research::glop::ProblemStatus; using operations_research::glop::ToDouble; // Parse glop parameters from the flags --params_file and --params. -void ReadGlopParameters(GlopParameters* parameters) { - if (!FLAGS_params_file.empty()) { +void ReadGlopParameters(GlopParameters *parameters) { + if (!absl::GetFlag(FLAGS_params_file).empty()) { std::string params; CHECK(TextFormat::ParseFromString(params, parameters)) << params; } - if (!FLAGS_params.empty()) { - CHECK(TextFormat::MergeFromString(FLAGS_params, parameters)) - << FLAGS_params; + if (!absl::GetFlag(FLAGS_params).empty()) { + CHECK(TextFormat::MergeFromString(absl::GetFlag(FLAGS_params), parameters)) + << absl::GetFlag(FLAGS_params); } - if (FLAGS_mps_verbose_result) { + if (absl::GetFlag(FLAGS_mps_verbose_result)) { printf("GlopParameters {\n%s}\n", FullProtocolMessageAsString(*parameters, 1).c_str()); } } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { gflags::ParseCommandLineFlags(&argc, &argv, true); GlopParameters parameters; @@ -86,9 +85,9 @@ int main(int argc, char* argv[]) { LinearProgram linear_program; std::vector file_list; // Replace this with your favorite match function. - file_list.push_back(FLAGS_input); + file_list.push_back(absl::GetFlag(FLAGS_input)); for (int i = 0; i < file_list.size(); ++i) { - const std::string& file_name = file_list[i]; + const std::string &file_name = file_list[i]; MPSReader mps_reader; operations_research::MPModelProto model_proto; if (absl::EndsWith(file_name, ".mps") || @@ -103,7 +102,7 @@ int main(int argc, char* argv[]) { ReadFileToProto(file_name, &model_proto); MPModelProtoToLinearProgram(model_proto, &linear_program); } - if (FLAGS_mps_dump_problem) { + if (absl::GetFlag(FLAGS_mps_dump_problem)) { printf("%s", linear_program.Dump().c_str()); } @@ -115,19 +114,19 @@ int main(int argc, char* argv[]) { std::string status_string; double objective_value; double solving_time_in_sec = 0; - if (FLAGS_mps_solve) { + if (absl::GetFlag(FLAGS_mps_solve)) { ScopedWallTime timer(&solving_time_in_sec); solve_status = solver.Solve(linear_program); status_string = GetProblemStatusString(solve_status); objective_value = ToDouble(solver.GetObjectiveValue()); } - if (FLAGS_mps_terse_result) { - if (FLAGS_mps_display_full_path) { + if (absl::GetFlag(FLAGS_mps_terse_result)) { + if (absl::GetFlag(FLAGS_mps_display_full_path)) { printf("%s,", file_name.c_str()); } printf("%s,", linear_program.name().c_str()); - if (FLAGS_mps_solve) { + if (absl::GetFlag(FLAGS_mps_solve)) { printf("%15.15e,%s,%-6.4g,", objective_value, status_string.c_str(), solving_time_in_sec); } @@ -135,12 +134,12 @@ int main(int argc, char* argv[]) { linear_program.GetNonZeroStats().c_str()); } - if (FLAGS_mps_verbose_result) { - if (FLAGS_mps_display_full_path) { + if (absl::GetFlag(FLAGS_mps_verbose_result)) { + if (absl::GetFlag(FLAGS_mps_display_full_path)) { printf("%-45s: %s\n", "File path", file_name.c_str()); } printf("%-45s: %s\n", "Problem name", linear_program.name().c_str()); - if (FLAGS_mps_solve) { + if (absl::GetFlag(FLAGS_mps_solve)) { printf("%-45s: %15.15e\n", "Objective value", objective_value); printf("%-45s: %s\n", "Problem status", status_string.c_str()); printf("%-45s: %-6.4g\n", "Solving time", solving_time_in_sec); diff --git a/examples/cpp/multi_knapsack_sat.cc b/examples/cpp/multi_knapsack_sat.cc index 9b4661f5a2..417b748f98 100644 --- a/examples/cpp/multi_knapsack_sat.cc +++ b/examples/cpp/multi_knapsack_sat.cc @@ -37,19 +37,19 @@ static const int kVolumeMin = 1156; static const int kVolumeMax = 1600; // Data for a single bin problem -static const int kItemsWeights[] = {1008, 2087, 5522, 5250, 5720, - 4998, 275, 3145, 12580, 382}; -static const int kItemsVolumes[] = {281, 307, 206, 111, 275, - 79, 23, 65, 261, 40}; +static const int kItemsWeights[] = { 1008, 2087, 5522, 5250, 5720, 4998, 275, + 3145, 12580, 382 }; +static const int kItemsVolumes[] = { 281, 307, 206, 111, 275, 79, 23, 65, 261, + 40 }; static const int kNumItems = 10; -void MultiKnapsackSat(int scaling, const std::string& params) { +void MultiKnapsackSat(int scaling, const std::string ¶ms) { CpModelBuilder builder; const int num_items = scaling * kNumItems; const int num_bins = scaling; - std::vector> items_in_bins(num_bins); + std::vector > items_in_bins(num_bins); for (int b = 0; b < num_bins; ++b) { for (int i = 0; i < num_items; ++i) { items_in_bins[b].push_back(builder.NewBoolVar()); @@ -74,13 +74,16 @@ void MultiKnapsackSat(int scaling, const std::string& params) { // Constraints per bins. std::vector bin_weights; for (int b = 0; b < num_bins; ++b) { - IntVar bin_weight = builder.NewIntVar({kWeightMin, kWeightMax}); + IntVar bin_weight = builder.NewIntVar({ + kWeightMin, kWeightMax + }); bin_weights.push_back(bin_weight); builder.AddEquality(LinearExpr::BooleanScalProd(items_in_bins[b], weights), bin_weight); builder.AddLinearConstraint( - LinearExpr::BooleanScalProd(items_in_bins[b], volumes), - {kVolumeMin, kVolumeMax}); + LinearExpr::BooleanScalProd(items_in_bins[b], volumes), { + kVolumeMin, kVolumeMax + }); } // Each item is selected at most one time. @@ -102,12 +105,13 @@ void MultiKnapsackSat(int scaling, const std::string& params) { LOG(INFO) << CpSolverResponseStats(response); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -int main(int argc, char** argv) { - absl::SetFlag(&FLAGS_logtostderr, true); +int main(int argc, char **argv) { + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); gflags::ParseCommandLineFlags(&argc, &argv, true); - operations_research::sat::MultiKnapsackSat(FLAGS_size, FLAGS_params); + operations_research::sat::MultiKnapsackSat(absl::GetFlag(FLAGS_size), + absl::GetFlag(FLAGS_params)); return EXIT_SUCCESS; } diff --git a/examples/cpp/network_routing_sat.cc b/examples/cpp/network_routing_sat.cc index 198555c2c4..b83547b7d2 100644 --- a/examples/cpp/network_routing_sat.cc +++ b/examples/cpp/network_routing_sat.cc @@ -45,9 +45,8 @@ #include "ortools/util/time_limit.h" // ----- Data Generator ----- -DEFINE_int32(clients, 0, - "Number of network clients nodes. If equal to zero, " - "then all backbones nodes are also client nodes."); +DEFINE_int32(clients, 0, "Number of network clients nodes. If equal to zero, " + "then all backbones nodes are also client nodes."); DEFINE_int32(backbones, 0, "Number of backbone nodes"); DEFINE_int32(demands, 0, "Number of network demands."); DEFINE_int32(traffic_min, 0, "Min traffic of a demand."); @@ -91,7 +90,7 @@ static const int64 kDisconnectedDistance = -1LL; // (capacity(i->j) == capacity(j->i)). // Demands are not symmetrical. class NetworkRoutingData { - public: +public: NetworkRoutingData() : name_(""), num_nodes_(-1), max_capacity_(-1), fixed_charge_cost_(-1) {} @@ -132,7 +131,7 @@ class NetworkRoutingData { void set_max_capacity(int max_capacity) { max_capacity_ = max_capacity; } void set_fixed_charge_cost(int cost) { fixed_charge_cost_ = cost; } - private: +private: std::string name_; int num_nodes_; int max_capacity_; @@ -155,7 +154,7 @@ class NetworkRoutingData { // Each arc has a capacity of 'max_capacity'. Using an arc incurs a // fixed cost of 'fixed_charge_cost'. class NetworkRoutingDataBuilder { - public: +public: NetworkRoutingDataBuilder() : random_(0) {} void BuildModelFromParameters(int num_clients, int num_backbones, @@ -192,7 +191,7 @@ class NetworkRoutingDataBuilder { max_backbone_degree, max_capacity, fixed_charge_cost, seed, data); } - private: +private: void InitData(int size, int seed) { network_.clear(); network_.resize(size); @@ -320,7 +319,7 @@ class NetworkRoutingDataBuilder { : random_.Uniform(num_clients) + num_backbones; } - std::vector> network_; + std::vector > network_; std::vector degrees_; MTRandom random_; }; @@ -329,18 +328,17 @@ class NetworkRoutingDataBuilder { // Useful data struct to hold demands. struct Demand { - public: +public: Demand(int the_source, int the_destination, int the_traffic) - : source(the_source), - destination(the_destination), - traffic(the_traffic) {} + : source(the_source), destination(the_destination), traffic(the_traffic) { + } int source; int destination; int traffic; }; class NetworkRoutingSolver { - public: +public: typedef std::unordered_set OnePath; NetworkRoutingSolver() : num_nodes_(-1) {} @@ -364,8 +362,9 @@ class NetworkRoutingSolver { tmp_vars.push_back(node_vars[i]); tmp_vars.push_back(node_vars[i + 1]); tmp_vars.push_back(arc_vars[i]); - TableConstraint table = cp_model.AddAllowedAssignments( - {node_vars[i], node_vars[i + 1], arc_vars[i]}); + TableConstraint table = cp_model.AddAllowedAssignments({ + node_vars[i], node_vars[i + 1], arc_vars[i] + }); for (const auto &tuple : arcs_data_) { table.AddTuple(tuple); } @@ -382,7 +381,7 @@ class NetworkRoutingSolver { std::atomic stopped(false); model.GetOrCreate()->RegisterExternalBooleanAsLimit(&stopped); - model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse &r) { + model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse & r) { const int path_id = all_paths_[demand_index].size(); all_paths_[demand_index].resize(path_id + 1); for (int arc_index = 0; arc_index < max_length - 1; ++arc_index) { @@ -423,7 +422,9 @@ class NetworkRoutingSolver { } void AddArcData(int64 source, int64 destination, int arc_id) { - arcs_data_.push_back({source, destination, arc_id}); + arcs_data_.push_back({ + source, destination, arc_id + }); } void InitArcInfo(const NetworkRoutingData &data) { @@ -444,7 +445,7 @@ class NetworkRoutingSolver { arc_capacity_.push_back(capacity); capacity_[i][j] = capacity; capacity_[j][i] = capacity; - if (FLAGS_print_model) { + if (absl::GetFlag(FLAGS_print_model)) { LOG(INFO) << "Arc " << i << " <-> " << j << " with capacity " << capacity; } @@ -478,10 +479,11 @@ class NetworkRoutingSolver { for (int demand_index = 0; demand_index < num_demands; ++demand_index) { paths.clear(); const Demand &demand = demands_array_[demand_index]; - CHECK(DijkstraShortestPath( - num_nodes_, demand.source, demand.destination, - [this](int x, int y) { return HasArc(x, y); }, kDisconnectedDistance, - &paths)); + CHECK(DijkstraShortestPath(num_nodes_, demand.source, demand.destination, + [this](int x, int y) { + return HasArc(x, y); + }, + kDisconnectedDistance, &paths)); all_min_path_lengths_.push_back(paths.size() - 1); } @@ -540,7 +542,7 @@ class NetworkRoutingSolver { if (capacity_[i][j] > 0) { return 1; } else { - return kDisconnectedDistance; // disconnected distance. + return kDisconnectedDistance; // disconnected distance. } } @@ -553,7 +555,7 @@ class NetworkRoutingSolver { // ----- Build Model ----- CpModelBuilder cp_model; - std::vector> path_vars(num_demands); + std::vector > path_vars(num_demands); // Node - Graph Constraint. for (int demand_index = 0; demand_index < num_demands; ++demand_index) { @@ -591,7 +593,12 @@ class NetworkRoutingSolver { const int64 capacity = arc_capacity_[arc_index]; IntVar scaled_traffic = cp_model.NewIntVar(Domain(0, sum_of_traffic * 1000)); - cp_model.AddEquality(LinearExpr::ScalProd({traffic_var}, {1000}), + cp_model.AddEquality(LinearExpr::ScalProd({ + traffic_var + }, + { + 1000 + }), scaled_traffic); IntVar normalized_traffic = cp_model.NewIntVar(Domain(0, sum_of_traffic * 1000 / capacity)); @@ -602,7 +609,7 @@ class NetworkRoutingSolver { normalized_traffic_vars[arc_index] = normalized_traffic; const BoolVar comfort = cp_model.NewBoolVar(); const int64 safe_capacity = - static_cast(capacity * FLAGS_comfort_zone); + static_cast(capacity * absl::GetFlag(FLAGS_comfort_zone)); cp_model.AddGreaterThan(traffic_var, safe_capacity) .OnlyEnforceIf(comfort); cp_model.AddLessOrEqual(traffic_var, safe_capacity) @@ -622,11 +629,11 @@ class NetworkRoutingSolver { cp_model.Minimize(objective_expr); Model model; - if (!FLAGS_params.empty()) { - model.Add(NewSatParameters(FLAGS_params)); + if (!absl::GetFlag(FLAGS_params).empty()) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); } int num_solutions = 0; - model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse &r) { + model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse & r) { LOG(INFO) << "Solution " << num_solutions; const double objective_value = r.objective_value(); const double percent = SolutionIntegerValue(r, max_usage_cost) / 10.0; @@ -648,32 +655,37 @@ class NetworkRoutingSolver { return response.objective_value(); } - private: +private: int count_arcs() const { return arcs_data_.size() / 2; } - std::vector> arcs_data_; + std::vector > arcs_data_; std::vector arc_capacity_; std::vector demands_array_; int num_nodes_; std::vector all_min_path_lengths_; - std::vector> capacity_; - std::vector> all_paths_; + std::vector > capacity_; + std::vector > all_paths_; }; -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::sat::NetworkRoutingData data; operations_research::sat::NetworkRoutingDataBuilder builder; builder.BuildModelFromParameters( - FLAGS_clients, FLAGS_backbones, FLAGS_demands, FLAGS_traffic_min, - FLAGS_traffic_max, FLAGS_min_client_degree, FLAGS_max_client_degree, - FLAGS_min_backbone_degree, FLAGS_max_backbone_degree, FLAGS_max_capacity, - FLAGS_fixed_charge_cost, FLAGS_seed, &data); + absl::GetFlag(FLAGS_clients), absl::GetFlag(FLAGS_backbones), + absl::GetFlag(FLAGS_demands), absl::GetFlag(FLAGS_traffic_min), + absl::GetFlag(FLAGS_traffic_max), absl::GetFlag(FLAGS_min_client_degree), + absl::GetFlag(FLAGS_max_client_degree), + absl::GetFlag(FLAGS_min_backbone_degree), + absl::GetFlag(FLAGS_max_backbone_degree), + absl::GetFlag(FLAGS_max_capacity), absl::GetFlag(FLAGS_fixed_charge_cost), + absl::GetFlag(FLAGS_seed), &data); operations_research::sat::NetworkRoutingSolver solver; - solver.Init(data, FLAGS_extra_hops, FLAGS_max_paths); + solver.Init(data, absl::GetFlag(FLAGS_extra_hops), + absl::GetFlag(FLAGS_max_paths)); LOG(INFO) << "Final cost = " << solver.Solve(); return EXIT_SUCCESS; } diff --git a/examples/cpp/nqueens.cc b/examples/cpp/nqueens.cc index d99a6eff17..b7cbc24b37 100644 --- a/examples/cpp/nqueens.cc +++ b/examples/cpp/nqueens.cc @@ -37,20 +37,20 @@ DEFINE_int32( DEFINE_bool(use_symmetry, false, "Use Symmetry Breaking methods"); DECLARE_bool(cp_disable_solve); -static const int kNumSolutions[] = { - 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184}; +static const int kNumSolutions[] = { 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, + 14200, 73712, 365596, 2279184 }; static const int kKnownSolutions = 15; -static const int kNumUniqueSolutions[] = { - 1, 0, 0, 1, 2, 1, 6, 12, 46, 92, - 341, 1787, 9233, 45752, 285053, 1846955, 11977939, 83263591, 621012754}; +static const int kNumUniqueSolutions[] = { 1, 0, 0, 1, 2, 1, 6, 12, 46, 92, 341, + 1787, 9233, 45752, 285053, 1846955, + 11977939, 83263591, 621012754 }; static const int kKnownUniqueSolutions = 19; namespace operations_research { class NQueenSymmetry : public SymmetryBreaker { - public: - NQueenSymmetry(Solver* const s, const std::vector& vars) +public: + NQueenSymmetry(Solver *const s, const std::vector &vars) : solver_(s), vars_(vars), size_(vars.size()) { for (int i = 0; i < size_; ++i) { indices_[vars[i]] = i; @@ -58,133 +58,133 @@ class NQueenSymmetry : public SymmetryBreaker { } ~NQueenSymmetry() override {} - protected: - int Index(IntVar* const var) const { +protected: + int Index(IntVar *const var) const { return gtl::FindWithDefault(indices_, var, -1); } - IntVar* Var(int index) const { + IntVar *Var(int index) const { DCHECK_GE(index, 0); DCHECK_LT(index, size_); return vars_[index]; } int size() const { return size_; } int symmetric(int index) const { return size_ - 1 - index; } - Solver* const solver() const { return solver_; } + Solver *const solver() const { return solver_; } - private: - Solver* const solver_; - const std::vector vars_; - std::map indices_; +private: + Solver *const solver_; + const std::vector vars_; + std::map indices_; const int size_; }; // Symmetry vertical axis. class SX : public NQueenSymmetry { - public: - SX(Solver* const s, const std::vector& vars) +public: + SX(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~SX() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { const int index = Index(var); - IntVar* const other_var = Var(symmetric(index)); + IntVar *const other_var = Var(symmetric(index)); AddIntegerVariableEqualValueClause(other_var, value); } }; // Symmetry horizontal axis. class SY : public NQueenSymmetry { - public: - SY(Solver* const s, const std::vector& vars) +public: + SY(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~SY() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { AddIntegerVariableEqualValueClause(var, symmetric(value)); } }; // Symmetry first diagonal axis. class SD1 : public NQueenSymmetry { - public: - SD1(Solver* const s, const std::vector& vars) +public: + SD1(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~SD1() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { const int index = Index(var); - IntVar* const other_var = Var(value); + IntVar *const other_var = Var(value); AddIntegerVariableEqualValueClause(other_var, index); } }; // Symmetry second diagonal axis. class SD2 : public NQueenSymmetry { - public: - SD2(Solver* const s, const std::vector& vars) +public: + SD2(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~SD2() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { const int index = Index(var); - IntVar* const other_var = Var(symmetric(value)); + IntVar *const other_var = Var(symmetric(value)); AddIntegerVariableEqualValueClause(other_var, symmetric(index)); } }; // Rotate 1/4 turn. class R90 : public NQueenSymmetry { - public: - R90(Solver* const s, const std::vector& vars) +public: + R90(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~R90() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { const int index = Index(var); - IntVar* const other_var = Var(value); + IntVar *const other_var = Var(value); AddIntegerVariableEqualValueClause(other_var, symmetric(index)); } }; // Rotate 1/2 turn. class R180 : public NQueenSymmetry { - public: - R180(Solver* const s, const std::vector& vars) +public: + R180(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~R180() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { const int index = Index(var); - IntVar* const other_var = Var(symmetric(index)); + IntVar *const other_var = Var(symmetric(index)); AddIntegerVariableEqualValueClause(other_var, symmetric(value)); } }; // Rotate 3/4 turn. class R270 : public NQueenSymmetry { - public: - R270(Solver* const s, const std::vector& vars) +public: + R270(Solver *const s, const std::vector &vars) : NQueenSymmetry(s, vars) {} ~R270() override {} - void VisitSetVariableValue(IntVar* const var, int64 value) override { + void VisitSetVariableValue(IntVar *const var, int64 value) override { const int index = Index(var); - IntVar* const other_var = Var(symmetric(value)); + IntVar *const other_var = Var(symmetric(value)); AddIntegerVariableEqualValueClause(other_var, index); } }; void CheckNumberOfSolutions(int size, int num_solutions) { - if (FLAGS_use_symmetry) { + if (absl::GetFlag(FLAGS_use_symmetry)) { if (size - 1 < kKnownUniqueSolutions) { CHECK_EQ(num_solutions, kNumUniqueSolutions[size - 1]); - } else if (!FLAGS_cp_disable_solve) { + } else if (!absl::GetFlag(FLAGS_cp_disable_solve)) { CHECK_GT(num_solutions, 0); } } else { if (size - 1 < kKnownSolutions) { CHECK_EQ(num_solutions, kNumSolutions[size - 1]); - } else if (!FLAGS_cp_disable_solve) { + } else if (!absl::GetFlag(FLAGS_cp_disable_solve)) { CHECK_GT(num_solutions, 0); } } @@ -195,14 +195,14 @@ void NQueens(int size) { Solver s("nqueens"); // model - std::vector queens; + std::vector queens; for (int i = 0; i < size; ++i) { queens.push_back( s.MakeIntVar(0, size - 1, absl::StrFormat("queen%04d", i))); } s.AddConstraint(s.MakeAllDifferent(queens)); - std::vector vars(size); + std::vector vars(size); for (int i = 0; i < size; ++i) { vars[i] = s.MakeSum(queens[i], i)->Var(); } @@ -212,50 +212,55 @@ void NQueens(int size) { } s.AddConstraint(s.MakeAllDifferent(vars)); - SolutionCollector* const solution_counter = + SolutionCollector *const solution_counter = s.MakeAllSolutionCollector(nullptr); - SolutionCollector* const collector = s.MakeAllSolutionCollector(); + SolutionCollector *const collector = s.MakeAllSolutionCollector(); collector->Add(queens); - std::vector monitors; + std::vector monitors; monitors.push_back(solution_counter); monitors.push_back(collector); - DecisionBuilder* const db = s.MakePhase(queens, Solver::CHOOSE_FIRST_UNBOUND, + DecisionBuilder *const db = s.MakePhase(queens, Solver::CHOOSE_FIRST_UNBOUND, Solver::ASSIGN_MIN_VALUE); - if (FLAGS_use_symmetry) { - std::vector breakers; - NQueenSymmetry* const sx = s.RevAlloc(new SX(&s, queens)); + if (absl::GetFlag(FLAGS_use_symmetry)) { + std::vector breakers; + NQueenSymmetry *const sx = s.RevAlloc(new SX(&s, queens)); breakers.push_back(sx); - NQueenSymmetry* const sy = s.RevAlloc(new SY(&s, queens)); + NQueenSymmetry *const sy = s.RevAlloc(new SY(&s, queens)); breakers.push_back(sy); - NQueenSymmetry* const sd1 = s.RevAlloc(new SD1(&s, queens)); + NQueenSymmetry *const sd1 = s.RevAlloc(new SD1(&s, queens)); breakers.push_back(sd1); - NQueenSymmetry* const sd2 = s.RevAlloc(new SD2(&s, queens)); + NQueenSymmetry *const sd2 = s.RevAlloc(new SD2(&s, queens)); breakers.push_back(sd2); - NQueenSymmetry* const r90 = s.RevAlloc(new R90(&s, queens)); + NQueenSymmetry *const r90 = s.RevAlloc(new R90(&s, queens)); breakers.push_back(r90); - NQueenSymmetry* const r180 = s.RevAlloc(new R180(&s, queens)); + NQueenSymmetry *const r180 = s.RevAlloc(new R180(&s, queens)); breakers.push_back(r180); - NQueenSymmetry* const r270 = s.RevAlloc(new R270(&s, queens)); + NQueenSymmetry *const r270 = s.RevAlloc(new R270(&s, queens)); breakers.push_back(r270); - SearchMonitor* const symmetry_manager = s.MakeSymmetryManager(breakers); + SearchMonitor *const symmetry_manager = s.MakeSymmetryManager(breakers); monitors.push_back(symmetry_manager); } - for (int loop = 0; loop < FLAGS_nb_loops; ++loop) { - s.Solve(db, monitors); // go! + for (int loop = 0; loop < absl::GetFlag(FLAGS_nb_loops); ++loop) { + s.Solve(db, monitors); // go! CheckNumberOfSolutions(size, solution_counter->solution_count()); } const int num_solutions = solution_counter->solution_count(); if (num_solutions > 0 && size < kKnownSolutions) { - int print_max = FLAGS_print_all ? num_solutions : FLAGS_print ? 1 : 0; + int print_max = absl::GetFlag(FLAGS_print_all) ? num_solutions + : absl::GetFlag(FLAGS_print) + ? 1 + : 0; for (int n = 0; n < print_max; ++n) { printf("--- solution #%d\n", n); for (int i = 0; i < size; ++i) { const int pos = static_cast(collector->Value(n, queens[i])); - for (int k = 0; k < pos; ++k) printf(" . "); + for (int k = 0; k < pos; ++k) + printf(" . "); printf("%2d ", i); - for (int k = pos + 1; k < size; ++k) printf(" . "); + for (int k = pos + 1; k < size; ++k) + printf(" . "); printf("\n"); } } @@ -263,12 +268,12 @@ void NQueens(int size) { printf("========= number of solutions:%d\n", num_solutions); absl::PrintF(" number of failures: %d\n", s.failures()); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_size != 0) { - operations_research::NQueens(FLAGS_size); + if (absl::GetFlag(FLAGS_size) != 0) { + operations_research::NQueens(absl::GetFlag(FLAGS_size)); } else { for (int n = 1; n < 12; ++n) { operations_research::NQueens(n); diff --git a/examples/cpp/opb_reader.h b/examples/cpp/opb_reader.h index 515a32af46..182b688a86 100644 --- a/examples/cpp/opb_reader.h +++ b/examples/cpp/opb_reader.h @@ -33,17 +33,17 @@ namespace sat { // The format is described here: // http://www.cril.univ-artois.fr/PB12/format.pdf class OpbReader { - public: +public: OpbReader() {} // Loads the given opb filename into the given problem. - bool Load(const std::string& filename, LinearBooleanProblem* problem) { + bool Load(const std::string &filename, LinearBooleanProblem *problem) { problem->Clear(); problem->set_name(ExtractProblemName(filename)); num_variables_ = 0; int num_lines = 0; - for (const std::string& line : FileLines(filename)) { + for (const std::string &line : FileLines(filename)) { ++num_lines; ProcessNewLine(problem, line); } @@ -54,17 +54,17 @@ class OpbReader { return true; } - private: +private: // Since the problem name is not stored in the cnf format, we infer it from // the file name. - static std::string ExtractProblemName(const std::string& filename) { + static std::string ExtractProblemName(const std::string &filename) { const int found = filename.find_last_of("/"); const std::string problem_name = found != std::string::npos ? filename.substr(found + 1) : filename; return problem_name; } - void ProcessNewLine(LinearBooleanProblem* problem, const std::string& line) { + void ProcessNewLine(LinearBooleanProblem *problem, const std::string &line) { const std::vector words = absl::StrSplit(line, absl::ByAnyChar(" ;"), absl::SkipEmpty()); if (words.empty() || words[0].empty() || words[0][0] == '*') { @@ -72,10 +72,11 @@ class OpbReader { } if (words[0] == "min:") { - LinearObjective* objective = problem->mutable_objective(); + LinearObjective *objective = problem->mutable_objective(); for (int i = 1; i < words.size(); ++i) { - const std::string& word = words[i]; - if (word.empty() || word[0] == ';') continue; + const std::string &word = words[i]; + if (word.empty() || word[0] == ';') + continue; if (word[0] == 'x') { int literal; CHECK(absl::SimpleAtoi(word.substr(1), &literal)); @@ -93,9 +94,9 @@ class OpbReader { } return; } - LinearBooleanConstraint* constraint = problem->add_constraints(); + LinearBooleanConstraint *constraint = problem->add_constraints(); for (int i = 0; i < words.size(); ++i) { - const std::string& word = words[i]; + const std::string &word = words[i]; CHECK(!word.empty()); if (word == ">=") { CHECK_LT(i + 1, words.size()); @@ -132,7 +133,7 @@ class OpbReader { DISALLOW_COPY_AND_ASSIGN(OpbReader); }; -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -#endif // OR_TOOLS_SAT_OPB_READER_H_ +#endif // OR_TOOLS_SAT_OPB_READER_H_ diff --git a/examples/cpp/parse_dimacs_assignment.h b/examples/cpp/parse_dimacs_assignment.h index 06b97d74b2..2c3b024347 100644 --- a/examples/cpp/parse_dimacs_assignment.h +++ b/examples/cpp/parse_dimacs_assignment.h @@ -38,13 +38,11 @@ DEFINE_bool(assignment_optimize_layout, true, namespace operations_research { -template -class LinearSumAssignment; +template class LinearSumAssignment; -template -class DimacsAssignmentParser { - public: - explicit DimacsAssignmentParser(const std::string& filename) +template class DimacsAssignmentParser { +public: + explicit DimacsAssignmentParser(const std::string &filename) : filename_(filename), graph_builder_(nullptr), assignment_(nullptr) {} // Reads an assignment problem description from the given file in @@ -60,31 +58,28 @@ class DimacsAssignmentParser { // representation back to the caller, the caller lacks a good way to // free the underlying graph (which isn't owned by the // LinearAssignment instance). - LinearSumAssignment* Parse(std::string* error_message, - GraphType** graph); + LinearSumAssignment *Parse(std::string *error_message, + GraphType **graph); - private: - void ParseProblemLine(const std::string& line); +private: + void ParseProblemLine(const std::string &line); - void ParseNodeLine(const std::string& line); + void ParseNodeLine(const std::string &line); - void ParseArcLine(const std::string& line); + void ParseArcLine(const std::string &line); - void ParseOneLine(const std::string& line); + void ParseOneLine(const std::string &line); std::string filename_; struct ErrorTrackingState { ErrorTrackingState() - : bad(false), - nodes_described(false), - reason(nullptr), - num_left_nodes(0), - num_arcs(0) {} + : bad(false), nodes_described(false), reason(nullptr), + num_left_nodes(0), num_arcs(0) {} bool bad; bool nodes_described; - const char* reason; + const char *reason; NodeIndex num_left_nodes; ArcIndex num_arcs; std::unique_ptr bad_line; @@ -92,18 +87,18 @@ class DimacsAssignmentParser { ErrorTrackingState state_; - AnnotatedGraphBuildManager* graph_builder_; + AnnotatedGraphBuildManager *graph_builder_; - LinearSumAssignment* assignment_; + LinearSumAssignment *assignment_; }; // Implementation is below here. template -void DimacsAssignmentParser::ParseProblemLine( - const std::string& line) { - static const char* kIncorrectProblemLine = +void +DimacsAssignmentParser::ParseProblemLine(const std::string &line) { + static const char *kIncorrectProblemLine = "Incorrect assignment problem line."; - static const char* kAssignmentProblemType = "asn"; + static const char *kAssignmentProblemType = "asn"; char problem_type[4]; NodeIndex num_nodes; ArcIndex num_arcs; @@ -120,11 +115,11 @@ void DimacsAssignmentParser::ParseProblemLine( state_.num_arcs = num_arcs; graph_builder_ = new AnnotatedGraphBuildManager( - num_nodes, num_arcs, FLAGS_assignment_optimize_layout); + num_nodes, num_arcs, absl::GetFlag(FLAGS_assignment_optimize_layout)); } template -void DimacsAssignmentParser::ParseNodeLine(const std::string& line) { +void DimacsAssignmentParser::ParseNodeLine(const std::string &line) { NodeIndex node_id; if (sscanf(line.c_str(), "%*c%d", &node_id) != 1) { state_.bad = true; @@ -142,7 +137,7 @@ void DimacsAssignmentParser::ParseNodeLine(const std::string& line) { } template -void DimacsAssignmentParser::ParseArcLine(const std::string& line) { +void DimacsAssignmentParser::ParseArcLine(const std::string &line) { if (graph_builder_ == nullptr) { state_.bad = true; state_.reason = @@ -165,44 +160,45 @@ void DimacsAssignmentParser::ParseArcLine(const std::string& line) { state_.bad_line.reset(new std::string(line)); } ArcIndex arc = graph_builder_->AddArc(tail - 1, head - 1); - assignment_->SetArcCost(arc, FLAGS_assignment_maximize_cost ? -cost : cost); + assignment_->SetArcCost( + arc, absl::GetFlag(FLAGS_assignment_maximize_cost) ? -cost : cost); } // Parameters out of style-guide order because this function is used // as a callback that varies the input line. template -void DimacsAssignmentParser::ParseOneLine(const std::string& line) { +void DimacsAssignmentParser::ParseOneLine(const std::string &line) { if (state_.bad) { return; } switch (line[0]) { - case 'p': { - // Problem-specification line - ParseProblemLine(line); - break; - } - case 'c': { - // Comment; do nothing. - return; - } - case 'n': { - // Node line defining a node on the left side - ParseNodeLine(line); - break; - } - case 'a': { - ParseArcLine(line); - break; - } - case '0': - case '\n': - break; - default: { - state_.bad = true; - state_.reason = "Unknown line type in the input."; - state_.bad_line.reset(new std::string(line)); - break; - } + case 'p': { + // Problem-specification line + ParseProblemLine(line); + break; + } + case 'c': { + // Comment; do nothing. + return; + } + case 'n': { + // Node line defining a node on the left side + ParseNodeLine(line); + break; + } + case 'a': { + ParseArcLine(line); + break; + } + case '0': + case '\n': + break; + default: { + state_.bad = true; + state_.reason = "Unknown line type in the input."; + state_.bad_line.reset(new std::string(line)); + break; + } } } @@ -220,12 +216,13 @@ void DimacsAssignmentParser::ParseOneLine(const std::string& line) { // free the underlying graph (which isn't owned by the // LinearAssignment instance). template -LinearSumAssignment* DimacsAssignmentParser::Parse( - std::string* error_message, GraphType** graph_handle) { +LinearSumAssignment * +DimacsAssignmentParser::Parse(std::string *error_message, + GraphType **graph_handle) { CHECK(error_message != nullptr); CHECK(graph_handle != nullptr); - for (const std::string& line : FileLines(filename_)) { + for (const std::string &line : FileLines(filename_)) { if (line.empty()) { continue; } @@ -243,7 +240,7 @@ LinearSumAssignment* DimacsAssignmentParser::Parse( } std::unique_ptr > cycle_handler( assignment_->ArcAnnotationCycleHandler()); - GraphType* graph = graph_builder_->Graph(cycle_handler.get()); + GraphType *graph = graph_builder_->Graph(cycle_handler.get()); if (graph == nullptr) { *error_message = "unable to create compact static graph"; return nullptr; @@ -257,6 +254,6 @@ LinearSumAssignment* DimacsAssignmentParser::Parse( return assignment_; } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_EXAMPLES_PARSE_DIMACS_ASSIGNMENT_H_ +#endif // OR_TOOLS_EXAMPLES_PARSE_DIMACS_ASSIGNMENT_H_ diff --git a/examples/cpp/pdptw.cc b/examples/cpp/pdptw.cc index 096a9522aa..b58d8d81c0 100644 --- a/examples/cpp/pdptw.cc +++ b/examples/cpp/pdptw.cc @@ -76,7 +76,7 @@ typedef std::vector > Coordinates; // Returns the scaled Euclidean distance between two nodes, coords holding the // coordinates of the nodes. -int64 Travel(const Coordinates* const coords, +int64 Travel(const Coordinates *const coords, RoutingIndexManager::NodeIndex from, RoutingIndexManager::NodeIndex to) { DCHECK(coords != nullptr); @@ -89,7 +89,7 @@ int64 Travel(const Coordinates* const coords, // Returns the scaled service time at a given node, service_times holding the // service times. -int64 ServiceTime(const std::vector* const service_times, +int64 ServiceTime(const std::vector *const service_times, RoutingIndexManager::NodeIndex node) { return kScalingFactor * service_times->at(node.value()); } @@ -98,9 +98,9 @@ int64 ServiceTime(const std::vector* const service_times, // holding the coordinates of the nodes and service_times holding the service // times. // The service time is the time spent to execute a delivery or a pickup. -int64 TravelPlusServiceTime(const RoutingIndexManager& manager, - const Coordinates* const coords, - const std::vector* const service_times, +int64 TravelPlusServiceTime(const RoutingIndexManager &manager, + const Coordinates *const coords, + const std::vector *const service_times, int64 from_index, int64 to_index) { const RoutingIndexManager::NodeIndex from = manager.IndexToNode(from_index); const RoutingIndexManager::NodeIndex to = manager.IndexToNode(to_index); @@ -113,14 +113,14 @@ int64 TravelPlusServiceTime(const RoutingIndexManager& manager, // - Number of used vehicles, // - Total schedule duration. // TODO(user): add total waiting time. -std::vector GetTabuVars(std::vector existing_vars, - operations_research::RoutingModel* routing) { - Solver* const solver = routing->solver(); - std::vector vars(std::move(existing_vars)); +std::vector GetTabuVars(std::vector existing_vars, + operations_research::RoutingModel *routing) { + Solver *const solver = routing->solver(); + std::vector vars(std::move(existing_vars)); vars.push_back(routing->CostVar()); - IntVar* used_vehicles = solver->MakeIntVar(0, routing->vehicles()); - std::vector is_used_vars; + IntVar *used_vehicles = solver->MakeIntVar(0, routing->vehicles()); + std::vector is_used_vars; // Number of vehicle used is_used_vars.reserve(routing->vehicles()); for (int v = 0; v < routing->vehicles(); v++) { @@ -135,14 +135,14 @@ std::vector GetTabuVars(std::vector existing_vars, } // Outputs a solution to the current model in a std::string. -std::string VerboseOutput(const RoutingModel& routing, - const RoutingIndexManager& manager, - const Assignment& assignment, - const Coordinates& coords, - const std::vector& service_times) { +std::string VerboseOutput(const RoutingModel &routing, + const RoutingIndexManager &manager, + const Assignment &assignment, + const Coordinates &coords, + const std::vector &service_times) { std::string output; - const RoutingDimension& time_dimension = routing.GetDimensionOrDie("time"); - const RoutingDimension& load_dimension = routing.GetDimensionOrDie("demand"); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie("time"); + const RoutingDimension &load_dimension = routing.GetDimensionOrDie("demand"); for (int i = 0; i < routing.vehicles(); ++i) { absl::StrAppendFormat(&output, "Vehicle %d: ", i); int64 index = routing.Start(i); @@ -152,13 +152,13 @@ std::string VerboseOutput(const RoutingModel& routing, while (!routing.IsEnd(index)) { absl::StrAppendFormat(&output, "%d ", manager.IndexToNode(index).value()); - const IntVar* vehicle = routing.VehicleVar(index); + const IntVar *vehicle = routing.VehicleVar(index); absl::StrAppendFormat(&output, "Vehicle(%d) ", assignment.Value(vehicle)); - const IntVar* arrival = time_dimension.CumulVar(index); + const IntVar *arrival = time_dimension.CumulVar(index); absl::StrAppendFormat(&output, "Time(%d..%d) ", assignment.Min(arrival), assignment.Max(arrival)); - const IntVar* load = load_dimension.CumulVar(index); + const IntVar *load = load_dimension.CumulVar(index); absl::StrAppendFormat(&output, "Load(%d..%d) ", assignment.Min(load), assignment.Max(load)); const int64 next_index = assignment.Value(routing.NextVar(index)); @@ -169,12 +169,12 @@ std::string VerboseOutput(const RoutingModel& routing, index = next_index; } output.append("Route end "); - const IntVar* vehicle = routing.VehicleVar(index); + const IntVar *vehicle = routing.VehicleVar(index); absl::StrAppendFormat(&output, "Vehicle(%d) ", assignment.Value(vehicle)); - const IntVar* arrival = time_dimension.CumulVar(index); + const IntVar *arrival = time_dimension.CumulVar(index); absl::StrAppendFormat(&output, "Time(%d..%d) ", assignment.Min(arrival), assignment.Max(arrival)); - const IntVar* load = load_dimension.CumulVar(index); + const IntVar *load = load_dimension.CumulVar(index); absl::StrAppendFormat(&output, "Load(%d..%d) ", assignment.Min(load), assignment.Max(load)); } @@ -187,27 +187,28 @@ namespace { // An inefficient but convenient method to parse a whitespace-separated list // of integers. Returns true iff the input std::string was entirely valid and // parsed. -bool SafeParseInt64Array(const std::string& str, - std::vector* parsed_int) { +bool SafeParseInt64Array(const std::string &str, + std::vector *parsed_int) { std::istringstream input(str); int64 x; parsed_int->clear(); - while (input >> x) parsed_int->push_back(x); + while (input >> x) + parsed_int->push_back(x); return input.eof(); } -} // namespace +} // namespace // Builds and solves a model from a file in the format defined by Li & Lim // (https://www.sintef.no/projectweb/top/pdptw/li-lim-benchmark/documentation/). -bool LoadAndSolve(const std::string& pdp_file, - const RoutingModelParameters& model_parameters, - const RoutingSearchParameters& search_parameters) { +bool LoadAndSolve(const std::string &pdp_file, + const RoutingModelParameters &model_parameters, + const RoutingSearchParameters &search_parameters) { // Load all the lines of the file in RAM (it shouldn't be too large anyway). std::vector lines; { std::string contents; CHECK_OK(file::GetContents(pdp_file, &contents, file::Defaults())); - const int64 kMaxInputFileSize = 1 << 30; // 1GB + const int64 kMaxInputFileSize = 1 << 30; // 1GB if (contents.size() >= kMaxInputFileSize) { LOG(WARNING) << "Input file '" << pdp_file << "' is too large (>" << kMaxInputFileSize << " bytes)."; @@ -227,8 +228,9 @@ bool LoadAndSolve(const std::string& pdp_file, LOG(WARNING) << "Malformed header: " << lines[0]; return false; } - const int num_vehicles = - FLAGS_pdp_force_vehicles > 0 ? FLAGS_pdp_force_vehicles : parsed_int[0]; + const int num_vehicles = absl::GetFlag(FLAGS_pdp_force_vehicles) > 0 + ? absl::GetFlag(FLAGS_pdp_force_vehicles) + : parsed_int[0]; const int64 capacity = parsed_int[1]; // We do not care about the 'speed' field, in third position. @@ -281,26 +283,28 @@ bool LoadAndSolve(const std::string& pdp_file, RoutingModel routing(manager, model_parameters); const int vehicle_cost = routing.RegisterTransitCallback([&coords, &manager](int64 i, int64 j) { - return Travel(const_cast(&coords), - manager.IndexToNode(i), manager.IndexToNode(j)); - }); + return Travel(const_cast(&coords), + manager.IndexToNode(i), manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); - RoutingTransitCallback2 demand_evaluator = [&](int64 from_index, - int64 to_index) { + RoutingTransitCallback2 demand_evaluator = + [&](int64 from_index, int64 to_index) { return demands[manager.IndexToNode(from_index).value()]; - }; + } + ; routing.AddDimension(routing.RegisterTransitCallback(demand_evaluator), 0, - capacity, /*fix_start_cumul_to_zero=*/true, "demand"); - RoutingTransitCallback2 time_evaluator = [&](int64 from_index, - int64 to_index) { + capacity, /*fix_start_cumul_to_zero=*/ true, "demand"); + RoutingTransitCallback2 time_evaluator = + [&](int64 from_index, int64 to_index) { return TravelPlusServiceTime(manager, &coords, &service_times, from_index, to_index); - }; + } + ; routing.AddDimension(routing.RegisterTransitCallback(time_evaluator), kScalingFactor * horizon, kScalingFactor * horizon, - /*fix_start_cumul_to_zero=*/true, "time"); - const RoutingDimension& time_dimension = routing.GetDimensionOrDie("time"); - Solver* const solver = routing.solver(); + /*fix_start_cumul_to_zero=*/ true, "time"); + const RoutingDimension &time_dimension = routing.GetDimensionOrDie("time"); + Solver *const solver = routing.solver(); for (int node = 0; node < num_nodes; ++node) { const int64 index = manager.NodeToIndex(RoutingIndexManager::NodeIndex(node)); @@ -314,7 +318,7 @@ bool LoadAndSolve(const std::string& pdp_file, routing.AddPickupAndDelivery(index, manager.NodeToIndex(deliveries[node])); } - IntVar* const cumul = time_dimension.CumulVar(index); + IntVar *const cumul = time_dimension.CumulVar(index); cumul->SetMin(kScalingFactor * open_times[node]); cumul->SetMax(kScalingFactor * close_times[node]); } @@ -325,13 +329,13 @@ bool LoadAndSolve(const std::string& pdp_file, // This will be used as one of the Tabu criteria. // This is done here and not in GetTabuVarsCallback as it requires calling // AddVariableMinimizedByFinalizer and this method must be called early. - std::vector end_cumuls; - std::vector start_cumuls; + std::vector end_cumuls; + std::vector start_cumuls; for (int i = 0; i < routing.vehicles(); ++i) { end_cumuls.push_back(time_dimension.CumulVar(routing.End(i))); start_cumuls.push_back(time_dimension.CumulVar(routing.Start(i))); } - IntVar* total_time = solver->MakeIntVar(0, 99999999, "total"); + IntVar *total_time = solver->MakeIntVar(0, 99999999, "total"); solver->AddConstraint(solver->MakeEquality( solver->MakeDifference(solver->MakeSum(end_cumuls), solver->MakeSum(start_cumuls)), @@ -340,9 +344,13 @@ bool LoadAndSolve(const std::string& pdp_file, routing.AddVariableMinimizedByFinalizer(total_time); RoutingModel::GetTabuVarsCallback tabu_var_callback = - [total_time](RoutingModel* model) { - return GetTabuVars({total_time}, model); - }; + [total_time](RoutingModel * model) { + return GetTabuVars({ + total_time + }, + model); + } + ; routing.SetTabuVarsCallback(tabu_var_callback); } @@ -357,12 +365,12 @@ bool LoadAndSolve(const std::string& pdp_file, // Solve pickup and delivery problem. SimpleCycleTimer timer; timer.Start(); - const Assignment* assignment = routing.SolveWithParameters(search_parameters); + const Assignment *assignment = routing.SolveWithParameters(search_parameters); timer.Stop(); LOG(INFO) << routing.solver()->LocalSearchProfile(); if (nullptr != assignment) { - LOG(INFO) << VerboseOutput(routing, manager, *assignment, coords, - service_times); + LOG(INFO) + << VerboseOutput(routing, manager, *assignment, coords, service_times); LOG(INFO) << "Cost: " << assignment->ObjectiveValue(); int skipped_nodes = 0; for (int node = 0; node < routing.Size(); node++) { @@ -385,22 +393,22 @@ bool LoadAndSolve(const std::string& pdp_file, return false; } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { - absl::SetFlag(&FLAGS_logtostderr, true); +int main(int argc, char **argv) { + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::RoutingModelParameters model_parameters = operations_research::DefaultRoutingModelParameters(); model_parameters.set_reduce_vehicle_cost_model( - FLAGS_reduce_vehicle_cost_model); + absl::GetFlag(FLAGS_reduce_vehicle_cost_model)); operations_research::RoutingSearchParameters search_parameters = operations_research::DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, &search_parameters)); - if (!operations_research::LoadAndSolve(FLAGS_pdp_file, model_parameters, - search_parameters)) { - LOG(INFO) << "Error solving " << FLAGS_pdp_file; + absl::GetFlag(FLAGS_routing_search_parameters), &search_parameters)); + if (!operations_research::LoadAndSolve(absl::GetFlag(FLAGS_pdp_file), + model_parameters, search_parameters)) { + LOG(INFO) << "Error solving " << absl::GetFlag(FLAGS_pdp_file); } return EXIT_SUCCESS; } diff --git a/examples/cpp/print_dimacs_assignment.h b/examples/cpp/print_dimacs_assignment.h index 43d4fb452f..047dd2d54f 100644 --- a/examples/cpp/print_dimacs_assignment.h +++ b/examples/cpp/print_dimacs_assignment.h @@ -30,8 +30,7 @@ namespace operations_research { -template -class LinearSumAssignment; +template class LinearSumAssignment; // Given a LinearSumAssigment object representing an assignment problem // description, outputs the problem in DIMACS format in the output file. @@ -39,12 +38,12 @@ class LinearSumAssignment; // http://lpsolve.sourceforge.net/5.5/DIMACS_asn.htm template void PrintDimacsAssignmentProblem( - const LinearSumAssignment& assignment, - const TailArrayManager& tail_array_manager, - const std::string& output_filename) { - File* output; + const LinearSumAssignment &assignment, + const TailArrayManager &tail_array_manager, + const std::string &output_filename) { + File *output; CHECK_OK(file::Open(output_filename, "w", &output, file::Defaults())); - const GraphType& graph(assignment.Graph()); + const GraphType &graph(assignment.Graph()); std::string output_line = absl::StrFormat("p asn %d %d\n", graph.num_nodes(), graph.num_arcs()); CHECK_OK(file::WriteString(output, output_line, file::Defaults())); @@ -67,6 +66,6 @@ void PrintDimacsAssignmentProblem( } } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_EXAMPLES_PRINT_DIMACS_ASSIGNMENT_H_ +#endif // OR_TOOLS_EXAMPLES_PRINT_DIMACS_ASSIGNMENT_H_ diff --git a/examples/cpp/random_tsp.cc b/examples/cpp/random_tsp.cc index 426c93dac4..79c4770124 100644 --- a/examples/cpp/random_tsp.cc +++ b/examples/cpp/random_tsp.cc @@ -44,11 +44,10 @@ DEFINE_int32(tsp_random_forbidden_connections, 0, "Number of random forbidden connections."); DEFINE_bool(tsp_use_deterministic_random_seed, false, "Use deterministic random seeds."); -DEFINE_string(routing_search_parameters, - "local_search_operators {" - " use_path_lns:BOOL_TRUE" - " use_inactive_lns:BOOL_TRUE" - "}", +DEFINE_string(routing_search_parameters, "local_search_operators {" + " use_path_lns:BOOL_TRUE" + " use_inactive_lns:BOOL_TRUE" + "}", "Text proto RoutingSearchParameters (possibly partial) that will " "override the DefaultRoutingSearchParameters()"); @@ -56,7 +55,7 @@ namespace operations_research { // Random seed generator. int32 GetSeed() { - if (FLAGS_tsp_use_deterministic_random_seed) { + if (absl::GetFlag(FLAGS_tsp_use_deterministic_random_seed)) { return ACMRandom::DeterministicSeed(); } else { return ACMRandom::HostnamePidTimeSeed(); @@ -69,12 +68,12 @@ int32 GetSeed() { int64 MyDistance(RoutingIndexManager::NodeIndex from, RoutingIndexManager::NodeIndex to) { // Put your distance code here. - return (from + to).value(); // for instance + return (from + to).value(); // for instance } // Random matrix. class RandomMatrix { - public: +public: explicit RandomMatrix(int size) : size_(size) {} void Initialize() { matrix_ = absl::make_unique(size_ * size_); @@ -95,7 +94,7 @@ class RandomMatrix { return matrix_[MatrixIndex(from, to)]; } - private: +private: int64 MatrixIndex(RoutingIndexManager::NodeIndex from, RoutingIndexManager::NodeIndex to) const { return (from * size_ + to).value(); @@ -105,44 +104,46 @@ class RandomMatrix { }; void Tsp() { - if (FLAGS_tsp_size > 0) { - // TSP of size FLAGS_tsp_size. + if (absl::GetFlag(FLAGS_tsp_size) > 0) { + // TSP of size absl::GetFlag(FLAGS_tsp_size). // Second argument = 1 to build a single tour (it's a TSP). - // Nodes are indexed from 0 to FLAGS_tsp_size - 1, by default the start of + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_tsp_size) - 1, by default + // the start of // the route is node 0. - RoutingIndexManager manager(FLAGS_tsp_size, 1, + RoutingIndexManager manager(absl::GetFlag(FLAGS_tsp_size), 1, RoutingIndexManager::NodeIndex(0)); RoutingModel routing(manager); RoutingSearchParameters parameters = DefaultRoutingSearchParameters(); CHECK(google::protobuf::TextFormat::MergeFromString( - FLAGS_routing_search_parameters, ¶meters)); + absl::GetFlag(FLAGS_routing_search_parameters), ¶meters)); // Setting the cost function. // Put a permanent callback to the distance accessor here. The callback // has the following signature: ResultCallback2. // The two arguments are the from and to node inidices. - RandomMatrix matrix(FLAGS_tsp_size); - if (FLAGS_tsp_use_random_matrix) { + RandomMatrix matrix(absl::GetFlag(FLAGS_tsp_size)); + if (absl::GetFlag(FLAGS_tsp_use_random_matrix)) { matrix.Initialize(); const int vehicle_cost = routing.RegisterTransitCallback( [&matrix, &manager](int64 i, int64 j) { - return matrix.Distance(manager.IndexToNode(i), - manager.IndexToNode(j)); - }); + return matrix.Distance(manager.IndexToNode(i), manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); } else { const int vehicle_cost = routing.RegisterTransitCallback([&manager](int64 i, int64 j) { - return MyDistance(manager.IndexToNode(i), manager.IndexToNode(j)); - }); + return MyDistance(manager.IndexToNode(i), manager.IndexToNode(j)); + }); routing.SetArcCostEvaluatorOfAllVehicles(vehicle_cost); } // Forbid node connections (randomly). ACMRandom randomizer(GetSeed()); int64 forbidden_connections = 0; - while (forbidden_connections < FLAGS_tsp_random_forbidden_connections) { - const int64 from = randomizer.Uniform(FLAGS_tsp_size - 1); - const int64 to = randomizer.Uniform(FLAGS_tsp_size - 1) + 1; + while (forbidden_connections < + absl::GetFlag(FLAGS_tsp_random_forbidden_connections)) { + const int64 from = randomizer.Uniform(absl::GetFlag(FLAGS_tsp_size) - 1); + const int64 to = + randomizer.Uniform(absl::GetFlag(FLAGS_tsp_size) - 1) + 1; if (routing.NextVar(from)->Contains(to)) { LOG(INFO) << "Forbidding connection " << from << " -> " << to; routing.NextVar(from)->RemoveValue(to); @@ -150,7 +151,7 @@ void Tsp() { } } // Solve, returns a solution if any (owned by RoutingModel). - const Assignment* solution = routing.SolveWithParameters(parameters); + const Assignment *solution = routing.SolveWithParameters(parameters); if (solution != nullptr) { // Solution cost. LOG(INFO) << "Cost " << solution->ObjectiveValue(); @@ -173,9 +174,9 @@ void Tsp() { LOG(INFO) << "Specify an instance size greater than 0."; } } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); operations_research::Tsp(); return EXIT_SUCCESS; diff --git a/examples/cpp/sat_cnf_reader.h b/examples/cpp/sat_cnf_reader.h index 78460acddc..81f4679cf2 100644 --- a/examples/cpp/sat_cnf_reader.h +++ b/examples/cpp/sat_cnf_reader.h @@ -40,7 +40,7 @@ namespace operations_research { namespace sat { struct LinearBooleanProblemWrapper { - explicit LinearBooleanProblemWrapper(LinearBooleanProblem* p) : problem(p) {} + explicit LinearBooleanProblemWrapper(LinearBooleanProblem *p) : problem(p) {} void SetNumVariables(int num) { problem->set_num_variables(num); } void SetOriginalNumVariables(int num) { @@ -48,7 +48,7 @@ struct LinearBooleanProblemWrapper { } void AddConstraint(absl::Span clause) { - LinearBooleanConstraint* constraint = problem->add_constraints(); + LinearBooleanConstraint *constraint = problem->add_constraints(); constraint->mutable_literals()->Reserve(clause.size()); constraint->mutable_coefficients()->Reserve(clause.size()); constraint->set_lower_bound(1); @@ -68,15 +68,15 @@ struct LinearBooleanProblemWrapper { problem->mutable_objective()->set_offset(offset); } - LinearBooleanProblem* problem; + LinearBooleanProblem *problem; }; struct CpModelProtoWrapper { - explicit CpModelProtoWrapper(CpModelProto* p) : problem(p) {} + explicit CpModelProtoWrapper(CpModelProto *p) : problem(p) {} void SetNumVariables(int num) { for (int i = 0; i < num; ++i) { - IntegerVariableProto* variable = problem->add_variables(); + IntegerVariableProto *variable = problem->add_variables(); variable->add_domain(0); variable->add_domain(1); } @@ -93,7 +93,7 @@ struct CpModelProtoWrapper { } void AddConstraint(absl::Span clause) { - auto* constraint = problem->add_constraints()->mutable_bool_or(); + auto *constraint = problem->add_constraints()->mutable_bool_or(); constraint->mutable_literals()->Reserve(clause.size()); for (const int literal : clause) { constraint->add_literals(LiteralToRef(literal)); @@ -110,7 +110,7 @@ struct CpModelProtoWrapper { problem->mutable_objective()->set_offset(offset); } - CpModelProto* problem; + CpModelProto *problem; }; // This class loads a file in cnf file format into a SatProblem. @@ -119,7 +119,7 @@ struct CpModelProtoWrapper { // // It also support the wcnf input format for partial weighted max-sat problems. class SatCnfReader { - public: +public: SatCnfReader() : interpret_cnf_as_max_sat_(false) {} // If called with true, then a cnf file will be converted to the max-sat @@ -127,22 +127,22 @@ class SatCnfReader { void InterpretCnfAsMaxSat(bool v) { interpret_cnf_as_max_sat_ = v; } // Loads the given cnf filename into the given proto. - bool Load(const std::string& filename, LinearBooleanProblem* problem) { + bool Load(const std::string &filename, LinearBooleanProblem *problem) { problem->Clear(); problem->set_name(ExtractProblemName(filename)); LinearBooleanProblemWrapper wrapper(problem); return LoadInternal(filename, &wrapper); } - bool Load(const std::string& filename, CpModelProto* problem) { + bool Load(const std::string &filename, CpModelProto *problem) { problem->Clear(); problem->set_name(ExtractProblemName(filename)); CpModelProtoWrapper wrapper(problem); return LoadInternal(filename, &wrapper); } - private: +private: template - bool LoadInternal(const std::string& filename, Problem* problem) { + bool LoadInternal(const std::string &filename, Problem *problem) { positive_literal_to_weight_.clear(); objective_offset_ = 0; is_wcnf_ = false; @@ -154,7 +154,7 @@ class SatCnfReader { num_slack_variables_ = 0; int num_lines = 0; - for (const std::string& line : FileLines(filename)) { + for (const std::string &line : FileLines(filename)) { ++num_lines; ProcessNewLine(line, problem); } @@ -185,7 +185,7 @@ class SatCnfReader { // Since the problem name is not stored in the cnf format, we infer it from // the file name. - static std::string ExtractProblemName(const std::string& filename) { + static std::string ExtractProblemName(const std::string &filename) { const int found = filename.find_last_of("/"); const std::string problem_name = found != std::string::npos ? filename.substr(found + 1) : filename; @@ -201,7 +201,7 @@ class SatCnfReader { return value; } - void ProcessHeader(const std::string& line) { + void ProcessHeader(const std::string &line) { static const char kWordDelimiters[] = " "; words_ = absl::StrSplit(line, kWordDelimiters, absl::SkipEmpty()); @@ -220,9 +220,11 @@ class SatCnfReader { } template - void ProcessNewLine(const std::string& line, Problem* problem) { - if (line.empty() || end_marker_seen_) return; - if (line[0] == 'c') return; + void ProcessNewLine(const std::string &line, Problem *problem) { + if (line.empty() || end_marker_seen_) + return; + if (line[0] == 'c') + return; if (line[0] == '%') { end_marker_seen_ = true; return; @@ -251,13 +253,14 @@ class SatCnfReader { } else { if (signed_value == 0) { end_marker_seen = true; - break; // end of clause. + break; // end of clause. } tmp_clause_.push_back(signed_value); } first = false; } - if (!end_marker_seen) return; + if (!end_marker_seen) + return; if (weight == hard_weight_) { ++num_added_clauses_; @@ -294,11 +297,13 @@ class SatCnfReader { objective_offset_ += weight; } - if (FLAGS_wcnf_use_strong_slack) { + if (absl::GetFlag(FLAGS_wcnf_use_strong_slack)) { // Add the binary implications slack_literal true => all the other // clause literals are false. for (int i = 0; i + 1 < tmp_clause_.size(); ++i) { - problem->AddConstraint({-slack_literal, -tmp_clause_[i]}); + problem->AddConstraint({ + -slack_literal, -tmp_clause_[i] + }); } } } @@ -334,7 +339,7 @@ class SatCnfReader { DISALLOW_COPY_AND_ASSIGN(SatCnfReader); }; -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -#endif // OR_TOOLS_SAT_SAT_CNF_READER_H_ +#endif // OR_TOOLS_SAT_SAT_CNF_READER_H_ diff --git a/examples/cpp/sat_runner.cc b/examples/cpp/sat_runner.cc index fbdb223093..c02c76460d 100644 --- a/examples/cpp/sat_runner.cc +++ b/examples/cpp/sat_runner.cc @@ -129,17 +129,18 @@ namespace { // Returns a trivial best bound. The best bound corresponds to the lower bound // (resp. upper bound) in case of a minimization (resp. maximization) problem. -double GetScaledTrivialBestBound(const LinearBooleanProblem& problem) { +double GetScaledTrivialBestBound(const LinearBooleanProblem &problem) { Coefficient best_bound(0); - const LinearObjective& objective = problem.objective(); + const LinearObjective &objective = problem.objective(); for (const int64 value : objective.coefficients()) { - if (value < 0) best_bound += Coefficient(value); + if (value < 0) + best_bound += Coefficient(value); } return AddOffsetAndScaleObjectiveValue(problem, best_bound); } -bool LoadBooleanProblem(const std::string& filename, - LinearBooleanProblem* problem, CpModelProto* cp_model) { +bool LoadBooleanProblem(const std::string &filename, + LinearBooleanProblem *problem, CpModelProto *cp_model) { if (absl::EndsWith(filename, ".opb") || absl::EndsWith(filename, ".opb.bz2")) { OpbReader reader; @@ -151,11 +152,12 @@ bool LoadBooleanProblem(const std::string& filename, absl::EndsWith(filename, ".wcnf") || absl::EndsWith(filename, ".wcnf.gz")) { SatCnfReader reader; - if (FLAGS_fu_malik || FLAGS_linear_scan || FLAGS_wpm1 || FLAGS_qmaxsat || - FLAGS_core_enc) { + if (absl::GetFlag(FLAGS_fu_malik) || absl::GetFlag(FLAGS_linear_scan) || + absl::GetFlag(FLAGS_wpm1) || absl::GetFlag(FLAGS_qmaxsat) || + absl::GetFlag(FLAGS_core_enc)) { reader.InterpretCnfAsMaxSat(true); } - if (FLAGS_use_cp_model) { + if (absl::GetFlag(FLAGS_use_cp_model)) { if (!reader.Load(filename, cp_model)) { LOG(FATAL) << "Cannot load file '" << filename << "'."; } @@ -164,7 +166,7 @@ bool LoadBooleanProblem(const std::string& filename, LOG(FATAL) << "Cannot load file '" << filename << "'."; } } - } else if (FLAGS_use_cp_model) { + } else if (absl::GetFlag(FLAGS_use_cp_model)) { LOG(INFO) << "Reading a CpModelProto."; *cp_model = ReadFileToProtoOrDie(filename); } else { @@ -174,12 +176,13 @@ bool LoadBooleanProblem(const std::string& filename, return true; } -std::string SolutionString(const LinearBooleanProblem& problem, - const std::vector& assignment) { +std::string SolutionString(const LinearBooleanProblem &problem, + const std::vector &assignment) { std::string output; BooleanVariable limit(problem.original_num_variables()); for (BooleanVariable index(0); index < limit; ++index) { - if (index > 0) output += " "; + if (index > 0) + output += " "; absl::StrAppend(&output, Literal(index, assignment[index.value()]).SignedValue()); } @@ -190,15 +193,15 @@ std::string SolutionString(const LinearBooleanProblem& problem, // here. int Run() { SatParameters parameters; - if (FLAGS_input.empty()) { + if (absl::GetFlag(FLAGS_input).empty()) { LOG(FATAL) << "Please supply a data file with --input="; } // Parse the --params flag. - if (!FLAGS_params.empty()) { - CHECK(google::protobuf::TextFormat::MergeFromString(FLAGS_params, - ¶meters)) - << FLAGS_params; + if (!absl::GetFlag(FLAGS_params).empty()) { + CHECK(google::protobuf::TextFormat::MergeFromString( + absl::GetFlag(FLAGS_params), ¶meters)) + << absl::GetFlag(FLAGS_params); } // Initialize the solver. @@ -208,12 +211,12 @@ int Run() { // Read the problem. LinearBooleanProblem problem; CpModelProto cp_model; - if (!LoadBooleanProblem(FLAGS_input, &problem, &cp_model)) { + if (!LoadBooleanProblem(absl::GetFlag(FLAGS_input), &problem, &cp_model)) { CpSolverResponse response; response.set_status(CpSolverStatus::MODEL_INVALID); return EXIT_SUCCESS; } - if (FLAGS_use_cp_model && cp_model.variables_size() == 0) { + if (absl::GetFlag(FLAGS_use_cp_model) && cp_model.variables_size() == 0) { LOG(INFO) << "Converting to CpModelProto ..."; cp_model = BooleanProblemToCpModelproto(problem); } @@ -221,28 +224,31 @@ int Run() { // TODO(user): clean this hack. Ideally LinearBooleanProblem should be // completely replaced by the more general CpModelProto. if (!cp_model.variables().empty()) { - problem.Clear(); // We no longer need it, release memory. + problem.Clear(); // We no longer need it, release memory. Model model; model.Add(NewSatParameters(parameters)); const CpSolverResponse response = SolveCpModel(cp_model, &model); - if (!FLAGS_output.empty()) { - if (absl::EndsWith(FLAGS_output, ".txt")) { - CHECK_OK(file::SetTextProto(FLAGS_output, response, file::Defaults())); + if (!absl::GetFlag(FLAGS_output).empty()) { + if (absl::EndsWith(absl::GetFlag(FLAGS_output), ".txt")) { + CHECK_OK(file::SetTextProto(absl::GetFlag(FLAGS_output), response, + file::Defaults())); } else { - CHECK_OK( - file::SetBinaryProto(FLAGS_output, response, file::Defaults())); + CHECK_OK(file::SetBinaryProto(absl::GetFlag(FLAGS_output), response, + file::Defaults())); } } // The SAT competition requires a particular exit code and since we don't // really use it for any other purpose, we comply. - if (response.status() == CpSolverStatus::FEASIBLE) return 10; - if (response.status() == CpSolverStatus::INFEASIBLE) return 20; + if (response.status() == CpSolverStatus::FEASIBLE) + return 10; + if (response.status() == CpSolverStatus::INFEASIBLE) + return 20; return EXIT_SUCCESS; } - if (FLAGS_strict_validity) { + if (absl::GetFlag(FLAGS_strict_validity)) { const absl::Status status = ValidateBooleanProblem(problem); if (!status.ok()) { LOG(ERROR) << "Invalid Boolean problem: " << status.message(); @@ -260,14 +266,14 @@ int Run() { // Probing. SatPostsolver probing_postsolver(problem.num_variables()); LinearBooleanProblem original_problem; - if (FLAGS_probing) { + if (absl::GetFlag(FLAGS_probing)) { // TODO(user): This is nice for testing, but consumes memory. original_problem = problem; ProbeAndSimplifyProblem(&probing_postsolver, &problem); } // Load the problem into the solver. - if (FLAGS_reduce_memory_usage) { + if (absl::GetFlag(FLAGS_reduce_memory_usage)) { if (!LoadAndConsumeBooleanProblem(&problem, solver.get())) { LOG(INFO) << "UNSAT when loading the problem."; } @@ -276,16 +282,19 @@ int Run() { LOG(INFO) << "UNSAT when loading the problem."; } } - auto strtoint64 = [](const std::string& word) { + auto strtoint64 = [](const std::string & word) { int64 value = 0; - if (!word.empty()) CHECK(absl::SimpleAtoi(word, &value)); + if (!word.empty()) + CHECK(absl::SimpleAtoi(word, &value)); return value; - }; - if (!AddObjectiveConstraint(problem, !FLAGS_lower_bound.empty(), - Coefficient(strtoint64(FLAGS_lower_bound)), - !FLAGS_upper_bound.empty(), - Coefficient(strtoint64(FLAGS_upper_bound)), - solver.get())) { + } + ; + if (!AddObjectiveConstraint( + problem, !absl::GetFlag(FLAGS_lower_bound).empty(), + Coefficient(strtoint64(absl::GetFlag(FLAGS_lower_bound))), + !absl::GetFlag(FLAGS_upper_bound).empty(), + Coefficient(strtoint64(absl::GetFlag(FLAGS_upper_bound))), + solver.get())) { LOG(INFO) << "UNSAT when setting the objective constraint."; } @@ -293,11 +302,11 @@ int Run() { // // TODO(user): To make this compatible with presolve, we just need to run // it after the presolve step. - if (FLAGS_use_symmetry) { - CHECK(!FLAGS_reduce_memory_usage) << "incompatible"; - CHECK(!FLAGS_presolve) << "incompatible"; + if (absl::GetFlag(FLAGS_use_symmetry)) { + CHECK(!absl::GetFlag(FLAGS_reduce_memory_usage)) << "incompatible"; + CHECK(!absl::GetFlag(FLAGS_presolve)) << "incompatible"; LOG(INFO) << "Finding symmetries of the problem."; - std::vector> generators; + std::vector > generators; FindLinearBooleanProblemSymmetries(problem, &generators); std::unique_ptr propagator(new SymmetryPropagator); for (int i = 0; i < generators.size(); ++i) { @@ -310,28 +319,31 @@ int Run() { // Optimize? std::vector solution; SatSolver::Status result = SatSolver::LIMIT_REACHED; - if (FLAGS_fu_malik || FLAGS_linear_scan || FLAGS_wpm1 || FLAGS_qmaxsat || - FLAGS_core_enc) { - if (FLAGS_randomize > 0 && (FLAGS_linear_scan || FLAGS_qmaxsat)) { - CHECK(!FLAGS_reduce_memory_usage) << "incompatible"; - result = SolveWithRandomParameters(STDOUT_LOG, problem, FLAGS_randomize, - solver.get(), &solution); + if (absl::GetFlag(FLAGS_fu_malik) || absl::GetFlag(FLAGS_linear_scan) || + absl::GetFlag(FLAGS_wpm1) || absl::GetFlag(FLAGS_qmaxsat) || + absl::GetFlag(FLAGS_core_enc)) { + if (absl::GetFlag(FLAGS_randomize) > 0 && + (absl::GetFlag(FLAGS_linear_scan) || absl::GetFlag(FLAGS_qmaxsat))) { + CHECK(!absl::GetFlag(FLAGS_reduce_memory_usage)) << "incompatible"; + result = SolveWithRandomParameters( + STDOUT_LOG, problem, absl::GetFlag(FLAGS_randomize), solver.get(), + &solution); } if (result == SatSolver::LIMIT_REACHED) { - if (FLAGS_qmaxsat) { + if (absl::GetFlag(FLAGS_qmaxsat)) { solver = absl::make_unique(); solver->SetParameters(parameters); CHECK(LoadBooleanProblem(problem, solver.get())); result = SolveWithCardinalityEncoding(STDOUT_LOG, problem, solver.get(), &solution); - } else if (FLAGS_core_enc) { + } else if (absl::GetFlag(FLAGS_core_enc)) { result = SolveWithCardinalityEncodingAndCore(STDOUT_LOG, problem, solver.get(), &solution); - } else if (FLAGS_fu_malik) { + } else if (absl::GetFlag(FLAGS_fu_malik)) { result = SolveWithFuMalik(STDOUT_LOG, problem, solver.get(), &solution); - } else if (FLAGS_wpm1) { + } else if (absl::GetFlag(FLAGS_wpm1)) { result = SolveWithWPM1(STDOUT_LOG, problem, solver.get(), &solution); - } else if (FLAGS_linear_scan) { + } else if (absl::GetFlag(FLAGS_linear_scan)) { result = SolveWithLinearScan(STDOUT_LOG, problem, solver.get(), &solution); } @@ -340,7 +352,7 @@ int Run() { // Only solve the decision version. parameters.set_log_search_progress(true); solver->SetParameters(parameters); - if (FLAGS_presolve) { + if (absl::GetFlag(FLAGS_presolve)) { std::unique_ptr time_limit = TimeLimit::FromParameters(parameters); result = SolveWithPresolve(&solver, time_limit.get(), &solution, nullptr); @@ -358,14 +370,15 @@ int Run() { // Print the solution status. if (result == SatSolver::FEASIBLE) { - if (FLAGS_fu_malik || FLAGS_linear_scan || FLAGS_wpm1 || FLAGS_core_enc) { + if (absl::GetFlag(FLAGS_fu_malik) || absl::GetFlag(FLAGS_linear_scan) || + absl::GetFlag(FLAGS_wpm1) || absl::GetFlag(FLAGS_core_enc)) { printf("s OPTIMUM FOUND\n"); CHECK(!solution.empty()); const Coefficient objective = ComputeObjectiveValue(problem, solution); scaled_best_bound = AddOffsetAndScaleObjectiveValue(problem, objective); // Postsolve. - if (FLAGS_probing) { + if (absl::GetFlag(FLAGS_probing)) { solution = probing_postsolver.PostsolveSolution(solution); problem = original_problem; } @@ -375,18 +388,20 @@ int Run() { // Check and output the solution. CHECK(IsAssignmentValid(problem, solution)); - if (FLAGS_output_cnf_solution) { + if (absl::GetFlag(FLAGS_output_cnf_solution)) { printf("v %s\n", SolutionString(problem, solution).c_str()); } - if (!FLAGS_output.empty()) { - CHECK(!FLAGS_reduce_memory_usage) << "incompatible"; + if (!absl::GetFlag(FLAGS_output).empty()) { + CHECK(!absl::GetFlag(FLAGS_reduce_memory_usage)) << "incompatible"; if (result == SatSolver::FEASIBLE) { StoreAssignment(solver->Assignment(), problem.mutable_assignment()); } - if (absl::EndsWith(FLAGS_output, ".txt")) { - CHECK_OK(file::SetTextProto(FLAGS_output, problem, file::Defaults())); + if (absl::EndsWith(absl::GetFlag(FLAGS_output), ".txt")) { + CHECK_OK(file::SetTextProto(absl::GetFlag(FLAGS_output), problem, + file::Defaults())); } else { - CHECK_OK(file::SetBinaryProto(FLAGS_output, problem, file::Defaults())); + CHECK_OK(file::SetBinaryProto(absl::GetFlag(FLAGS_output), problem, + file::Defaults())); } } } @@ -419,24 +434,26 @@ int Run() { // The SAT competition requires a particular exit code and since we don't // really use it for any other purpose, we comply. - if (result == SatSolver::FEASIBLE) return 10; - if (result == SatSolver::INFEASIBLE) return 20; + if (result == SatSolver::FEASIBLE) + return 10; + if (result == SatSolver::INFEASIBLE) + return 20; return EXIT_SUCCESS; } -} // namespace -} // namespace sat -} // namespace operations_research +} // namespace +} // namespace sat +} // namespace operations_research static const char kUsage[] = "Usage: see flags.\n" "This program solves a given Boolean linear problem."; -int main(int argc, char** argv) { +int main(int argc, char **argv) { // By default, we want to show how the solver progress. Note that this needs // to be set before InitGoogle() which has the nice side-effect of allowing // the user to override it. - // absl::SetFlag(&FLAGS_vmodule, "*cp_model*=1"); + // absl::SetFlag(&absl::GetFlag(FLAGS_vmodule), "*cp_model*=1"); gflags::SetUsageMessage(kUsage); gflags::ParseCommandLineFlags(&argc, &argv, true); google::InitGoogleLogging(argv[0]); diff --git a/examples/cpp/shift_minimization_sat.cc b/examples/cpp/shift_minimization_sat.cc index 9cb1f7e437..33f5cef0cd 100644 --- a/examples/cpp/shift_minimization_sat.cc +++ b/examples/cpp/shift_minimization_sat.cc @@ -45,7 +45,7 @@ DEFINE_string(params, "", "Sat parameters in text proto format."); namespace operations_research { namespace sat { class ShiftMinimizationParser { - public: +public: struct Job { int start; int end; @@ -57,17 +57,15 @@ class ShiftMinimizationParser { }; ShiftMinimizationParser() - : load_status_(NOT_STARTED), - declared_num_jobs_(0), - declared_num_workers_(0), - num_workers_read_(0) {} + : load_status_(NOT_STARTED), declared_num_jobs_(0), + declared_num_workers_(0), num_workers_read_(0) {} - const std::vector& jobs() const { return jobs_; } - const std::vector>& possible_jobs_per_worker() const { + const std::vector &jobs() const { return jobs_; } + const std::vector > &possible_jobs_per_worker() const { return possible_jobs_per_worker_; } - const std::vector>& possible_assignments_per_job() - const { + const std::vector > & + possible_assignments_per_job() const { return possible_assignments_per_job_; } @@ -78,14 +76,14 @@ class ShiftMinimizationParser { // // Repeated n times // Qualifications = // c: job_1 .. job_c // repeated k times (a counter and job ids after). - bool LoadFile(const std::string& file_name) { + bool LoadFile(const std::string &file_name) { if (load_status_ != NOT_STARTED) { return false; } load_status_ = STARTED; - for (const std::string& line : + for (const std::string &line : FileLines(file_name, FileLineIterator::REMOVE_LINEFEED | FileLineIterator::REMOVE_INLINE_CR)) { ProcessLine(line); @@ -98,16 +96,21 @@ class ShiftMinimizationParser { declared_num_workers_ == num_workers_read_; } - private: - enum LoadStatus { NOT_STARTED, STARTED, JOBS_SEEN, WORKERS_SEEN }; +private: + enum LoadStatus { + NOT_STARTED, + STARTED, + JOBS_SEEN, + WORKERS_SEEN + }; - int strtoint32(const std::string& word) { + int strtoint32(const std::string &word) { int result; CHECK(absl::SimpleAtoi(word, &result)); return result; } - void ProcessLine(const std::string& line) { + void ProcessLine(const std::string &line) { if (line.empty() || line[0] == '#') { return; } @@ -116,78 +119,81 @@ class ShiftMinimizationParser { absl::StrSplit(line, absl::ByAnyChar(" :\t"), absl::SkipEmpty()); switch (load_status_) { - case NOT_STARTED: { - LOG(FATAL) << "Wrong status: NOT_STARTED"; - break; + case NOT_STARTED: { + LOG(FATAL) << "Wrong status: NOT_STARTED"; + break; + } + case STARTED: { + if (words.size() == 3 && words[0] == "Type") { + CHECK_EQ(1, strtoint32(words[2])); + } else if (words.size() == 3 && words[0] == "Jobs") { + declared_num_jobs_ = strtoint32(words[2]); + possible_assignments_per_job_.resize(declared_num_jobs_); + load_status_ = JOBS_SEEN; + } else { + LOG(FATAL) << "Wrong state STARTED with line " << line; } - case STARTED: { - if (words.size() == 3 && words[0] == "Type") { - CHECK_EQ(1, strtoint32(words[2])); - } else if (words.size() == 3 && words[0] == "Jobs") { - declared_num_jobs_ = strtoint32(words[2]); - possible_assignments_per_job_.resize(declared_num_jobs_); - load_status_ = JOBS_SEEN; - } else { - LOG(FATAL) << "Wrong state STARTED with line " << line; - } - break; + break; + } + case JOBS_SEEN: { + if (words.size() == 2) { + jobs_.push_back({ + strtoint32(words[0]), strtoint32(words[1]) + }); + } else if (words.size() == 3 && words[0] == "Qualifications") { + declared_num_workers_ = strtoint32(words[2]); + possible_jobs_per_worker_.resize(declared_num_workers_); + load_status_ = WORKERS_SEEN; + } else { + LOG(FATAL) << "Wrong state JOBS_SEEN with line " << line; } - case JOBS_SEEN: { - if (words.size() == 2) { - jobs_.push_back({strtoint32(words[0]), strtoint32(words[1])}); - } else if (words.size() == 3 && words[0] == "Qualifications") { - declared_num_workers_ = strtoint32(words[2]); - possible_jobs_per_worker_.resize(declared_num_workers_); - load_status_ = WORKERS_SEEN; - } else { - LOG(FATAL) << "Wrong state JOBS_SEEN with line " << line; - } - break; - } - case WORKERS_SEEN: { - CHECK_EQ(strtoint32(words[0]), words.size() - 1); - for (int i = 1; i < words.size(); ++i) { - const int job = strtoint32(words[i]); - const int pos = possible_jobs_per_worker_[num_workers_read_].size(); - possible_jobs_per_worker_[num_workers_read_].push_back(job); - possible_assignments_per_job_[job].push_back( - {num_workers_read_, pos}); - } - num_workers_read_++; - break; + break; + } + case WORKERS_SEEN: { + CHECK_EQ(strtoint32(words[0]), words.size() - 1); + for (int i = 1; i < words.size(); ++i) { + const int job = strtoint32(words[i]); + const int pos = possible_jobs_per_worker_[num_workers_read_].size(); + possible_jobs_per_worker_[num_workers_read_].push_back(job); + possible_assignments_per_job_[job].push_back({ + num_workers_read_, pos + }); } + num_workers_read_++; + break; + } } } std::vector jobs_; - std::vector> possible_jobs_per_worker_; - std::vector> possible_assignments_per_job_; + std::vector > possible_jobs_per_worker_; + std::vector > possible_assignments_per_job_; LoadStatus load_status_; int declared_num_jobs_; int declared_num_workers_; int num_workers_read_; }; -bool Overlaps(const ShiftMinimizationParser::Job& j1, - const ShiftMinimizationParser::Job& j2) { +bool Overlaps(const ShiftMinimizationParser::Job &j1, + const ShiftMinimizationParser::Job &j2) { // TODO(user): Are end date inclusive or exclusive? To check. // For now, we assume that they are exclusive. return !(j1.start > j2.end || j2.start > j1.end); } -void LoadAndSolve(const std::string& file_name) { +void LoadAndSolve(const std::string &file_name) { ShiftMinimizationParser parser; CHECK(parser.LoadFile(file_name)); CpModelBuilder cp_model; const int num_workers = parser.possible_jobs_per_worker().size(); - const std::vector& jobs = parser.jobs(); + const std::vector &jobs = parser.jobs(); const int num_jobs = jobs.size(); std::vector active_workers(num_workers); - std::vector> worker_job_vars(num_workers); - std::vector> possible_workers_per_job(num_jobs); + std::vector > worker_job_vars(num_workers); + std::vector > possible_workers_per_job(num_jobs); for (int w = 0; w < num_workers; ++w) { // Status variables for workers, are they active or not? @@ -195,7 +201,7 @@ void LoadAndSolve(const std::string& file_name) { // Job-Worker variable. worker_job_vars[w][i] is true iff worker w // performs it's ith possible job. - const std::vector& possible = parser.possible_jobs_per_worker()[w]; + const std::vector &possible = parser.possible_jobs_per_worker()[w]; for (int p : possible) { const BoolVar var = cp_model.NewBoolVar(); worker_job_vars[w].push_back(var); @@ -210,14 +216,16 @@ void LoadAndSolve(const std::string& file_name) { if (Overlaps(jobs[job1], jobs[job2])) { const BoolVar v1 = worker_job_vars[w][i]; const BoolVar v2 = worker_job_vars[w][j]; - cp_model.AddBoolOr({Not(v1), Not(v2)}); + cp_model.AddBoolOr({ + Not(v1), Not(v2) + }); } } } // Maintain active_workers variable. cp_model.AddBoolOr(worker_job_vars[w]).OnlyEnforceIf(active_workers[w]); - for (const BoolVar& var : worker_job_vars[w]) { + for (const BoolVar &var : worker_job_vars[w]) { cp_model.AddImplication(var, active_workers[w]); } } @@ -235,7 +243,7 @@ void LoadAndSolve(const std::string& file_name) { // then the number of active workers on these jobs is equal to the number of // active jobs. std::set time_points; - std::set> visited_job_lists; + std::set > visited_job_lists; for (int j = 0; j < num_jobs; ++j) { time_points.insert(parser.jobs()[j].start); @@ -250,7 +258,7 @@ void LoadAndSolve(const std::string& file_name) { // Collect all jobs that intersects with this time point. std::vector intersecting_jobs; for (int j = 0; j < num_jobs; ++j) { - const ShiftMinimizationParser::Job& job = parser.jobs()[j]; + const ShiftMinimizationParser::Job &job = parser.jobs()[j]; // Assumption: End date are inclusive. if (t >= job.start && t <= job.end) { intersecting_jobs.push_back(j); @@ -258,13 +266,14 @@ void LoadAndSolve(const std::string& file_name) { } // Check that we have not already visited this exact set of candidate jobs. - if (gtl::ContainsKey(visited_job_lists, intersecting_jobs)) continue; + if (gtl::ContainsKey(visited_job_lists, intersecting_jobs)) + continue; visited_job_lists.insert(intersecting_jobs); // Collect the relevant worker job vars. std::vector overlapping_worker_jobs; for (int j : intersecting_jobs) { - for (const auto& p : parser.possible_assignments_per_job()[j]) { + for (const auto &p : parser.possible_assignments_per_job()[j]) { const BoolVar var = worker_job_vars[p.worker_id][p.job_index]; overlapping_worker_jobs.push_back(var); } @@ -292,21 +301,21 @@ void LoadAndSolve(const std::string& file_name) { // Solve. Model model; - model.Add(NewSatParameters(FLAGS_params)); + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model); LOG(INFO) << CpSolverResponseStats(response); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -int main(int argc, char** argv) { - absl::SetFlag(&FLAGS_logtostderr, true); +int main(int argc, char **argv) { + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_input.empty()) { + if (absl::GetFlag(FLAGS_input).empty()) { LOG(FATAL) << "Please supply a data file with --input="; } - operations_research::sat::LoadAndSolve(FLAGS_input); + operations_research::sat::LoadAndSolve(absl::GetFlag(FLAGS_input)); return EXIT_SUCCESS; } diff --git a/examples/cpp/slitherlink_sat.cc b/examples/cpp/slitherlink_sat.cc index c359296fa4..a31463371d 100644 --- a/examples/cpp/slitherlink_sat.cc +++ b/examples/cpp/slitherlink_sat.cc @@ -21,35 +21,34 @@ #include "ortools/sat/cp_model.h" #include "ortools/sat/model.h" -const std::vector> tiny = {{3, 3, 1}}; +const std::vector > tiny = { { 3, 3, 1 } }; -const std::vector> small = { - {3, 2, -1, 3}, {-1, -1, -1, 2}, {3, -1, -1, -1}, {3, -1, 3, 1}}; +const std::vector > small = { + { 3, 2, -1, 3 }, { -1, -1, -1, 2 }, { 3, -1, -1, -1 }, { 3, -1, 3, 1 } +}; -const std::vector> medium = { - {-1, 0, -1, 1, -1, -1, 1, -1}, {-1, 3, -1, -1, 2, 3, -1, 2}, - {-1, -1, 0, -1, -1, -1, -1, 0}, {-1, 3, -1, -1, 0, -1, -1, -1}, - {-1, -1, -1, 3, -1, -1, 0, -1}, {1, -1, -1, -1, -1, 3, -1, -1}, - {3, -1, 1, 3, -1, -1, 3, -1}, {-1, 0, -1, -1, 3, -1, 3, -1}}; +const std::vector > medium = { + { -1, 0, -1, 1, -1, -1, 1, -1 }, { -1, 3, -1, -1, 2, 3, -1, 2 }, + { -1, -1, 0, -1, -1, -1, -1, 0 }, { -1, 3, -1, -1, 0, -1, -1, -1 }, + { -1, -1, -1, 3, -1, -1, 0, -1 }, { 1, -1, -1, -1, -1, 3, -1, -1 }, + { 3, -1, 1, 3, -1, -1, 3, -1 }, { -1, 0, -1, -1, 3, -1, 3, -1 } +}; -const std::vector> big = { - {3, -1, -1, -1, 2, -1, 1, -1, 1, 2}, - {1, -1, 0, -1, 3, -1, 2, 0, -1, -1}, - {-1, 3, -1, -1, -1, -1, -1, -1, 3, -1}, - {2, 0, -1, 3, -1, 2, 3, -1, -1, -1}, - {-1, -1, -1, 1, 1, 1, -1, -1, 3, 3}, - {2, 3, -1, -1, 2, 2, 3, -1, -1, -1}, - {-1, -1, -1, 1, 2, -1, 2, -1, 3, 3}, - {-1, 2, -1, -1, -1, -1, -1, -1, 2, -1}, - {-1, -1, 1, 1, -1, 2, -1, 1, -1, 3}, - {3, 3, -1, 1, -1, 2, -1, -1, -1, 2}}; +const std::vector > big = { + { 3, -1, -1, -1, 2, -1, 1, -1, 1, 2 }, { 1, -1, 0, -1, 3, -1, 2, 0, -1, -1 }, + { -1, 3, -1, -1, -1, -1, -1, -1, 3, -1 }, + { 2, 0, -1, 3, -1, 2, 3, -1, -1, -1 }, { -1, -1, -1, 1, 1, 1, -1, -1, 3, 3 }, + { 2, 3, -1, -1, 2, 2, 3, -1, -1, -1 }, { -1, -1, -1, 1, 2, -1, 2, -1, 3, 3 }, + { -1, 2, -1, -1, -1, -1, -1, -1, 2, -1 }, + { -1, -1, 1, 1, -1, 2, -1, 1, -1, 3 }, { 3, 3, -1, 1, -1, 2, -1, -1, -1, 2 } +}; namespace operations_research { namespace sat { -void PrintSolution(const std::vector> &data, - const std::vector> &h_arcs, - const std::vector> &v_arcs) { +void PrintSolution(const std::vector > &data, + const std::vector > &h_arcs, + const std::vector > &v_arcs) { const int num_rows = data.size(); const int num_columns = data[0].size(); @@ -83,7 +82,7 @@ void PrintSolution(const std::vector> &data, std::cout << last_line << std::endl; } -void SlitherLink(const std::vector> &data) { +void SlitherLink(const std::vector > &data) { const int num_rows = data.size(); const int num_columns = data[0].size(); @@ -91,23 +90,26 @@ void SlitherLink(const std::vector> &data) { const int num_horizontal_arcs = num_columns * (num_rows + 1); const int num_vertical_arcs = (num_rows) * (num_columns + 1); - auto undirected_horizontal_arc = [=](int x, int y) { + auto undirected_horizontal_arc = [ = ](int x, int y) { CHECK_LT(x, num_columns); CHECK_LT(y, num_rows + 1); return x + (num_columns * y); - }; + } + ; - auto undirected_vertical_arc = [=](int x, int y) { + auto undirected_vertical_arc = [ = ](int x, int y) { CHECK_LT(x, num_columns + 1); CHECK_LT(y, num_rows); return x + (num_columns + 1) * y; - }; + } + ; - auto node_index = [=](int x, int y) { + auto node_index = [ = ](int x, int y) { CHECK_LT(x, num_columns + 1); CHECK_LT(y, num_rows + 1); return x + y * (num_columns + 1); - }; + } + ; CpModelBuilder builder; @@ -154,7 +156,8 @@ void SlitherLink(const std::vector> &data) { for (int x = 0; x < num_columns; ++x) { for (int y = 0; y < num_rows; ++y) { - if (data[y][x] == -1) continue; + if (data[y][x] == -1) + continue; std::vector neighbors; const int top_arc = undirected_horizontal_arc(x, y); neighbors.push_back(horizontal_arcs[2 * top_arc]); @@ -175,31 +178,43 @@ void SlitherLink(const std::vector> &data) { // Special rule on corners: value == 3 implies 2 corner arcs used. if (data[0][0] == 3) { const int h_arc = undirected_horizontal_arc(0, 0); - builder.AddBoolOr( - {horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1]}); + builder.AddBoolOr({ + horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1] + }); const int v_arc = undirected_vertical_arc(0, 0); - builder.AddBoolOr({vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1]}); + builder.AddBoolOr({ + vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1] + }); } if (data[0][num_columns - 1] == 3) { const int h_arc = undirected_horizontal_arc(num_columns - 1, 0); - builder.AddBoolOr( - {horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1]}); + builder.AddBoolOr({ + horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1] + }); const int v_arc = undirected_vertical_arc(num_columns, 0); - builder.AddBoolOr({vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1]}); + builder.AddBoolOr({ + vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1] + }); } if (data[num_rows - 1][0] == 3) { const int h_arc = undirected_horizontal_arc(0, num_rows); - builder.AddBoolOr( - {horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1]}); + builder.AddBoolOr({ + horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1] + }); const int v_arc = undirected_vertical_arc(0, num_rows - 1); - builder.AddBoolOr({vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1]}); + builder.AddBoolOr({ + vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1] + }); } if (data[num_rows - 1][num_columns - 1] == 3) { const int h_arc = undirected_horizontal_arc(num_columns - 1, num_rows); - builder.AddBoolOr( - {horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1]}); + builder.AddBoolOr({ + horizontal_arcs[2 * h_arc], horizontal_arcs[2 * h_arc + 1] + }); const int v_arc = undirected_vertical_arc(num_columns, num_rows - 1); - builder.AddBoolOr({vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1]}); + builder.AddBoolOr({ + vertical_arcs[2 * v_arc], vertical_arcs[2 * v_arc + 1] + }); } // Topology rule: Border arcs are oriented in one direction. @@ -219,7 +234,7 @@ void SlitherLink(const std::vector> &data) { const CpSolverResponse response = Solve(builder.Build()); - std::vector> h_arcs(num_rows + 1); + std::vector > h_arcs(num_rows + 1); for (int y = 0; y < num_rows + 1; ++y) { for (int x = 0; x < num_columns; ++x) { const int arc = undirected_horizontal_arc(x, y); @@ -229,7 +244,7 @@ void SlitherLink(const std::vector> &data) { } } - std::vector> v_arcs(num_columns + 1); + std::vector > v_arcs(num_columns + 1); for (int y = 0; y < num_rows; ++y) { for (int x = 0; x < num_columns + 1; ++x) { const int arc = undirected_vertical_arc(x, y); @@ -243,8 +258,8 @@ void SlitherLink(const std::vector> &data) { LOG(INFO) << CpSolverResponseStats(response); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research int main() { std::cout << "Tiny problem" << std::endl; diff --git a/examples/cpp/solve.cc b/examples/cpp/solve.cc index 1824691aba..8ac78d2105 100644 --- a/examples/cpp/solve.cc +++ b/examples/cpp/solve.cc @@ -63,7 +63,7 @@ DEFINE_string(dump_model, "", "If non-empty, dumps MPModelProto there."); DEFINE_string(dump_request, "", "If non-empty, dumps MPModelRequest there."); DEFINE_string(dump_response, "", "If non-empty, dumps MPModelResponse there."); -DECLARE_bool(verify_solution); // Defined in ./linear_solver.cc +DECLARE_bool(verify_solution); // Defined in ./linear_solver.cc static const char kUsageStr[] = "Run MPSolver on the given input file. Many formats are supported: \n" @@ -81,26 +81,28 @@ namespace { bool Run() { // Create the solver and set its parameters. MPSolver::OptimizationProblemType type; - CHECK(MPSolver::ParseSolverType(FLAGS_solver, &type)) - << "Unsupported --solver: " << FLAGS_solver; + CHECK(MPSolver::ParseSolverType(absl::GetFlag(FLAGS_solver), &type)) + << "Unsupported --solver: " << absl::GetFlag(FLAGS_solver); // Load the problem into an MPModelProto. MPModelProto model_proto; MPModelRequest request_proto; - if (absl::EndsWith(FLAGS_input, ".mps") || - absl::EndsWith(FLAGS_input, ".mps.gz")) { - CHECK_OK(glop::MPSReader().ParseFile(FLAGS_input, &model_proto)) - << "Error while parsing the mps file '" << FLAGS_input << "'."; + if (absl::EndsWith(absl::GetFlag(FLAGS_input), ".mps") || + absl::EndsWith(absl::GetFlag(FLAGS_input), ".mps.gz")) { + CHECK_OK( + glop::MPSReader().ParseFile(absl::GetFlag(FLAGS_input), &model_proto)) + << "Error while parsing the mps file '" << absl::GetFlag(FLAGS_input) + << "'."; } else { - ReadFileToProto(FLAGS_input, &model_proto); - ReadFileToProto(FLAGS_input, &request_proto); + ReadFileToProto(absl::GetFlag(FLAGS_input), &model_proto); + ReadFileToProto(absl::GetFlag(FLAGS_input), &request_proto); // If the input proto is in binary format, both ReadFileToProto could return // true. Instead use the actual number of variables found to test the // correct format of the input. const bool is_model_proto = model_proto.variable_size() > 0; const bool is_request_proto = request_proto.model().variable_size() > 0; if (!is_model_proto && !is_request_proto) { - LOG(FATAL) << "Failed to parse '" << FLAGS_input + LOG(FATAL) << "Failed to parse '" << absl::GetFlag(FLAGS_input) << "' as an MPModelProto or an MPModelRequest."; } else { CHECK(!(is_model_proto && is_request_proto)); @@ -112,54 +114,55 @@ bool Run() { } } } - printf("%-12s: '%s'\n", "File", FLAGS_input.c_str()); + printf("%-12s: '%s'\n", "File", absl::GetFlag(FLAGS_input).c_str()); // Detect format to dump protos. operations_research::ProtoWriteFormat write_format; - if (FLAGS_dump_format == "text") { + if (absl::GetFlag(FLAGS_dump_format) == "text") { write_format = ProtoWriteFormat::kProtoText; - } else if (FLAGS_dump_format == "binary") { + } else if (absl::GetFlag(FLAGS_dump_format) == "binary") { write_format = ProtoWriteFormat::kProtoBinary; - } else if (FLAGS_dump_format == "json") { + } else if (absl::GetFlag(FLAGS_dump_format) == "json") { write_format = ProtoWriteFormat::kJson; } else { - LOG(FATAL) << "Unsupported --dump_format: " << FLAGS_dump_format; + LOG(FATAL) + << "Unsupported --dump_format: " << absl::GetFlag(FLAGS_dump_format); } // Create the solver, we use the name of the model as the solver name. MPSolver solver(model_proto.name(), type); const absl::Status set_num_threads_status = - solver.SetNumThreads(FLAGS_num_threads); + solver.SetNumThreads(absl::GetFlag(FLAGS_num_threads)); if (set_num_threads_status.ok()) { - LOG(INFO) << "Set number of threads to " << FLAGS_num_threads << "."; + LOG(INFO) << "Set number of threads to " << absl::GetFlag(FLAGS_num_threads) + << "."; } else { LOG(ERROR) << "Failed to set number of threads due to: " << set_num_threads_status.message() << ". Using 1 as default."; } solver.EnableOutput(); - if (!FLAGS_params_file.empty()) { + if (!absl::GetFlag(FLAGS_params_file).empty()) { std::string file_contents; - CHECK_OK( - file::GetContents(FLAGS_params_file, &file_contents, file::Defaults())) + CHECK_OK(file::GetContents(absl::GetFlag(FLAGS_params_file), &file_contents, + file::Defaults())) << "Could not read parameters file."; CHECK(solver.SetSolverSpecificParametersAsString(file_contents)); - } else if (!FLAGS_params.empty()) { - CHECK(solver.SetSolverSpecificParametersAsString(FLAGS_params)) - << "Wrong --params format."; + } else if (!absl::GetFlag(FLAGS_params).empty()) { + CHECK(solver.SetSolverSpecificParametersAsString( + absl::GetFlag(FLAGS_params))) << "Wrong --params format."; } absl::PrintF( "%-12s: %s\n", "Solver", - MPModelRequest::SolverType_Name( - static_cast(solver.ProblemType())) - .c_str()); + MPModelRequest::SolverType_Name(static_cast( + solver.ProblemType())).c_str()); // Load the proto into the solver. std::string error_message; // If requested, save the model to file. - if (!FLAGS_dump_model.empty()) { - CHECK(WriteProtoToFile(FLAGS_dump_model, model_proto, write_format, - FLAGS_dump_gzip)); + if (!absl::GetFlag(FLAGS_dump_model).empty()) { + CHECK(WriteProtoToFile(absl::GetFlag(FLAGS_dump_model), model_proto, + write_format, absl::GetFlag(FLAGS_dump_gzip))); } const MPSolverResponseStatus status = @@ -170,8 +173,8 @@ bool Run() { static_cast(1000.0 * request_proto.solver_time_limit_seconds())); } // Note, the underlying MPSolver treats time limit equal to 0 as no limit. - if (FLAGS_time_limit_ms >= 0) { - solver.set_time_limit(FLAGS_time_limit_ms); + if (absl::GetFlag(FLAGS_time_limit_ms) >= 0) { + solver.set_time_limit(absl::GetFlag(FLAGS_time_limit_ms)); } if (status != MPSOLVER_MODEL_IS_VALID) { LOG(ERROR) << MPSolverResponseStatus_Name(status) << ": " << error_message; @@ -189,7 +192,7 @@ bool Run() { solving_time = absl::Now() - time_before; // If requested, re-create a corresponding MPModelRequest and save it to file. - if (!FLAGS_dump_request.empty()) { + if (!absl::GetFlag(FLAGS_dump_request).empty()) { operations_research::MPModelRequest request; request.set_solver_type( static_cast(solver.ProblemType())); @@ -197,21 +200,21 @@ bool Run() { request.set_solver_specific_parameters( solver.GetSolverSpecificParametersAsString()); *request.mutable_model() = model_proto; - CHECK(WriteProtoToFile(FLAGS_dump_request, request, write_format, - FLAGS_dump_gzip)); + CHECK(WriteProtoToFile(absl::GetFlag(FLAGS_dump_request), request, + write_format, absl::GetFlag(FLAGS_dump_gzip))); } const bool has_solution = solve_status == MPSolver::OPTIMAL || solve_status == MPSolver::FEASIBLE; // If requested, get the MPModelResponse and save it to file. - if (!FLAGS_dump_response.empty() && has_solution) { + if (!absl::GetFlag(FLAGS_dump_response).empty() && has_solution) { operations_research::MPSolutionResponse response; solver.FillSolutionResponseProto(&response); - CHECK(WriteProtoToFile(FLAGS_dump_response, response, write_format, - FLAGS_dump_gzip)); + CHECK(WriteProtoToFile(absl::GetFlag(FLAGS_dump_response), response, + write_format, absl::GetFlag(FLAGS_dump_gzip))); } - if (!FLAGS_output_csv.empty() && has_solution) { + if (!absl::GetFlag(FLAGS_output_csv).empty() && has_solution) { operations_research::MPSolutionResponse result; solver.FillSolutionResponseProto(&result); std::string csv_file; @@ -219,21 +222,21 @@ bool Run() { csv_file += absl::StrFormat("%s,%e\n", model_proto.variable(i).name(), result.variable_value(i)); } - CHECK_OK(file::SetContents(FLAGS_output_csv, csv_file, file::Defaults())); + CHECK_OK(file::SetContents(absl::GetFlag(FLAGS_output_csv), csv_file, + file::Defaults())); } // If --verify_solution is true, we already verified it. If not, we add // a verification step here. - if (has_solution && !FLAGS_verify_solution) { + if (has_solution && !absl::GetFlag(FLAGS_verify_solution)) { LOG(INFO) << "Verifying the solution"; - solver.VerifySolution(/*tolerance=*/param.GetDoubleParam( + solver.VerifySolution(/*tolerance=*/ param.GetDoubleParam( MPSolverParameters::PRIMAL_TOLERANCE), - /*log_errors=*/true); + /*log_errors=*/ true); } absl::PrintF("%-12s: %s\n", "Status", MPSolverResponseStatus_Name( - static_cast(solve_status)) - .c_str()); + static_cast(solve_status)).c_str()); absl::PrintF("%-12s: %15.15e\n", "Objective", has_solution ? solver.Objective().Value() : 0.0); absl::PrintF("%-12s: %15.15e\n", "BestBound", @@ -247,13 +250,13 @@ bool Run() { return true; } -} // namespace -} // namespace operations_research +} // namespace +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags=*/true); - CHECK(!FLAGS_input.empty()) << "--input is required"; + gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags=*/ true); + CHECK(!absl::GetFlag(FLAGS_input).empty()) << "--input is required"; operations_research::Run(); return EXIT_SUCCESS; diff --git a/examples/cpp/sports_scheduling_sat.cc b/examples/cpp/sports_scheduling_sat.cc index a5e57b994b..7c09364064 100644 --- a/examples/cpp/sports_scheduling_sat.cc +++ b/examples/cpp/sports_scheduling_sat.cc @@ -61,21 +61,20 @@ void FirstModel(int num_teams) { CpModelBuilder builder; // Calendar variables. - std::vector> opponents(num_teams); - std::vector> home_aways(num_teams); - std::vector> signed_opponents(num_teams); + std::vector > opponents(num_teams); + std::vector > home_aways(num_teams); + std::vector > signed_opponents(num_teams); for (int t = 0; t < num_teams; ++t) { for (int d = 0; d < num_days; ++d) { Domain opponent_domain(0, num_teams - 1); Domain signed_opponent_domain(0, 2 * num_teams - 1); IntVar opp = builder.NewIntVar(opponent_domain) - .WithName(absl::StrCat("opponent_", t, "_", d)); + .WithName(absl::StrCat("opponent_", t, "_", d)); BoolVar home = builder.NewBoolVar().WithName(absl::StrCat("home_aways", t, "_", d)); - IntVar signed_opp = - builder.NewIntVar(signed_opponent_domain) - .WithName(absl::StrCat("signed_opponent_", t, "_", d)); + IntVar signed_opp = builder.NewIntVar(signed_opponent_domain) + .WithName(absl::StrCat("signed_opponent_", t, "_", d)); opponents[t].push_back(opp); home_aways[t].push_back(home); @@ -109,7 +108,10 @@ void FirstModel(int num_teams) { IntVar second_home = builder.NewBoolVar(); builder.AddVariableElement(day_opponents[first_team], day_home_aways, second_home); - builder.AddEquality(LinearExpr::Sum({first_home, second_home}), 1); + builder.AddEquality(LinearExpr::Sum({ + first_home, second_home + }), + 1); } builder.AddEquality(LinearExpr::Sum(day_home_aways), num_teams / 2); @@ -136,11 +138,13 @@ void FirstModel(int num_teams) { // Forbid sequence of 3 homes or 3 aways. for (int start = 0; start < num_days - 2; ++start) { - builder.AddBoolOr({home_aways[t][start], home_aways[t][start + 1], - home_aways[t][start + 2]}); - builder.AddBoolOr({Not(home_aways[t][start]), - Not(home_aways[t][start + 1]), - Not(home_aways[t][start + 2])}); + builder.AddBoolOr({ + home_aways[t][start], home_aways[t][start + 1], home_aways[t][start + 2] + }); + builder.AddBoolOr({ + Not(home_aways[t][start]), Not(home_aways[t][start + 1]), + Not(home_aways[t][start + 2]) + }); } } @@ -150,9 +154,12 @@ void FirstModel(int num_teams) { for (int d = 0; d < num_days - 1; ++d) { BoolVar break_var = builder.NewBoolVar().WithName(absl::StrCat("break_", t, "_", d)); - builder.AddBoolOr( - {Not(home_aways[t][d]), Not(home_aways[t][d + 1]), break_var}); - builder.AddBoolOr({home_aways[t][d], home_aways[t][d + 1], break_var}); + builder.AddBoolOr({ + Not(home_aways[t][d]), Not(home_aways[t][d + 1]), break_var + }); + builder.AddBoolOr({ + home_aways[t][d], home_aways[t][d + 1], break_var + }); breaks.push_back(break_var); } } @@ -160,8 +167,8 @@ void FirstModel(int num_teams) { builder.Minimize(LinearExpr::BooleanSum(breaks)); Model model; - if (!FLAGS_params.empty()) { - model.Add(NewSatParameters(FLAGS_params)); + if (!absl::GetFlag(FLAGS_params).empty()) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); } const CpSolverResponse response = SolveCpModel(builder.Build(), &model); @@ -193,7 +200,7 @@ void SecondModel(int num_teams) { CpModelBuilder builder; // Does team i receive team j at home on day d? - std::vector>> fixtures(num_days); + std::vector > > fixtures(num_days); for (int d = 0; d < num_days; ++d) { fixtures[d].resize(num_teams); for (int i = 0; i < num_teams; ++i) { @@ -209,7 +216,7 @@ void SecondModel(int num_teams) { } // Is team t at home on day d? - std::vector> at_home(num_days); + std::vector > at_home(num_days); for (int d = 0; d < num_days; ++d) { for (int t = 0; t < num_teams; ++t) { at_home[d].push_back(builder.NewBoolVar()); @@ -221,7 +228,8 @@ void SecondModel(int num_teams) { for (int team = 0; team < num_teams; ++team) { std::vector possible_opponents; for (int other = 0; other < num_teams; ++other) { - if (team == other) continue; + if (team == other) + continue; possible_opponents.push_back(fixtures[d][team][other]); possible_opponents.push_back(fixtures[d][other][team]); } @@ -232,7 +240,8 @@ void SecondModel(int num_teams) { // Each fixture happens once per season. for (int team = 0; team < num_teams; ++team) { for (int other = 0; other < num_teams; ++other) { - if (team == other) continue; + if (team == other) + continue; std::vector possible_days; for (int d = 0; d < num_days; ++d) { possible_days.push_back(fixtures[d][team][other]); @@ -244,7 +253,8 @@ void SecondModel(int num_teams) { // Meet each opponent once per season. for (int team = 0; team < num_teams; ++team) { for (int other = 0; other < num_teams; ++other) { - if (team == other) continue; + if (team == other) + continue; std::vector first_half; std::vector second_half; for (int d = 0; d < matches_per_day; ++d) { @@ -262,7 +272,8 @@ void SecondModel(int num_teams) { for (int d = 0; d < num_days; ++d) { for (int team = 0; team < num_teams; ++team) { for (int other = 0; other < num_teams; ++other) { - if (team == other) continue; + if (team == other) + continue; builder.AddImplication(fixtures[d][team][other], at_home[d][team]); builder.AddImplication(fixtures[d][team][other], Not(at_home[d][other])); @@ -273,10 +284,13 @@ void SecondModel(int num_teams) { // Forbid sequence of 3 homes or 3 aways. for (int team = 0; team < num_teams; ++team) { for (int d = 0; d < num_days - 2; ++d) { - builder.AddBoolOr( - {at_home[d][team], at_home[d + 1][team], at_home[d + 2][team]}); - builder.AddBoolOr({Not(at_home[d][team]), Not(at_home[d + 1][team]), - Not(at_home[d + 2][team])}); + builder.AddBoolOr({ + at_home[d][team], at_home[d + 1][team], at_home[d + 2][team] + }); + builder.AddBoolOr({ + Not(at_home[d][team]), Not(at_home[d + 1][team]), + Not(at_home[d + 2][team]) + }); } } @@ -285,13 +299,18 @@ void SecondModel(int num_teams) { for (int t = 0; t < num_teams; ++t) { for (int d = 0; d < num_days - 1; ++d) { BoolVar break_var = builder.NewBoolVar(); - builder.AddBoolOr( - {Not(at_home[d][t]), Not(at_home[d + 1][t]), break_var}); - builder.AddBoolOr({at_home[d][t], at_home[d + 1][t], break_var}); - builder.AddBoolOr( - {Not(at_home[d][t]), at_home[d + 1][t], Not(break_var)}); - builder.AddBoolOr( - {at_home[d][t], Not(at_home[d + 1][t]), Not(break_var)}); + builder.AddBoolOr({ + Not(at_home[d][t]), Not(at_home[d + 1][t]), break_var + }); + builder.AddBoolOr({ + at_home[d][t], at_home[d + 1][t], break_var + }); + builder.AddBoolOr({ + Not(at_home[d][t]), at_home[d + 1][t], Not(break_var) + }); + builder.AddBoolOr({ + at_home[d][t], Not(at_home[d + 1][t]), Not(break_var) + }); breaks.push_back(break_var); } } @@ -301,16 +320,16 @@ void SecondModel(int num_teams) { builder.Minimize(LinearExpr::BooleanSum(breaks)); Model model; - if (!FLAGS_params.empty()) { - model.Add(NewSatParameters(FLAGS_params)); + if (!absl::GetFlag(FLAGS_params).empty()) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); } const CpSolverResponse response = SolveCpModel(builder.Build(), &model); LOG(INFO) << CpSolverResponseStats(response); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research static const char kUsage[] = "Usage: see flags.\nThis program runs a sports scheduling problem." @@ -319,8 +338,9 @@ static const char kUsage[] = int main(int argc, char **argv) { gflags::SetUsageMessage(kUsage); gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_EQ(0, FLAGS_num_teams % 2) << "The number of teams must be even"; - CHECK_GE(FLAGS_num_teams, 2) << "At least 2 teams"; - operations_research::sat::SecondModel(FLAGS_num_teams); + CHECK_EQ(0, absl::GetFlag(FLAGS_num_teams) % 2) + << "The number of teams must be even"; + CHECK_GE(absl::GetFlag(FLAGS_num_teams), 2) << "At least 2 teams"; + operations_research::sat::SecondModel(absl::GetFlag(FLAGS_num_teams)); return EXIT_SUCCESS; } diff --git a/examples/cpp/stigler_diet.cc b/examples/cpp/stigler_diet.cc index 728189251b..88012dd60c 100644 --- a/examples/cpp/stigler_diet.cc +++ b/examples/cpp/stigler_diet.cc @@ -17,16 +17,13 @@ namespace operations_research { void RunStiglerDietExample() { // Nutrient minimums. - std::vector> nutrients = { - {"Calories (kcal)", 3.0}, - {"Protein (g)", 70.0}, - {"Calcium (g)", 0.8}, - {"Iron (mg)", 12.0}, - {"Vitamin A (kIU)", 5.0}, - {"Thiamine (Vitamin B1) (mg)", 1.8}, - {"Riboflavin (Vitamin B2) (mg)", 2.7}, - {"Niacin (mg)", 18.0}, - {"Ascorbic Acid (Vitamin C) (mg)", 75.0}}; + std::vector > nutrients = { + { "Calories (kcal)", 3.0 }, { "Protein (g)", 70.0 }, { "Calcium (g)", 0.8 }, + { "Iron (mg)", 12.0 }, { "Vitamin A (kIU)", 5.0 }, + { "Thiamine (Vitamin B1) (mg)", 1.8 }, + { "Riboflavin (Vitamin B2) (mg)", 2.7 }, { "Niacin (mg)", 18.0 }, + { "Ascorbic Acid (Vitamin C) (mg)", 75.0 } + }; struct Commodity { // Commodity name @@ -48,200 +45,146 @@ void RunStiglerDietExample() { }; std::vector data = { - {"Wheat Flour (Enriched)", - "10 lb.", - 36, - {44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0}}, - {"Macaroni", "1 lb.", 14.1, {11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0}}, - {"Wheat Cereal (Enriched)", - "28 oz.", - 24.2, - {11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0}}, - {"Corn Flakes", "8 oz.", 7.1, {11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0}}, - {"Corn Meal", - "1 lb.", - 4.6, - {36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0}}, - {"Hominy Grits", - "24 oz.", - 8.5, - {28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0}}, - {"Rice", "1 lb.", 7.5, {21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0}}, - {"Rolled Oats", "1 lb.", 7.1, {25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0}}, - {"White Bread (Enriched)", - "1 lb.", - 7.9, - {15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0}}, - {"Whole Wheat Bread", - "1 lb.", - 9.1, - {12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0}}, - {"Rye Bread", "1 lb.", 9.1, {12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0}}, - {"Pound Cake", "1 lb.", 24.8, {8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0}}, - {"Soda Crackers", "1 lb.", 15.1, {12.5, 288, 0.5, 50, 0, 0, 0, 0, 0}}, - {"Milk", "1 qt.", 11, {6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177}}, - {"Evaporated Milk (can)", - "14.5 oz.", - 6.7, - {8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60}}, - {"Butter", "1 lb.", 30.8, {10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0}}, - {"Oleomargarine", "1 lb.", 16.1, {20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0}}, - {"Eggs", "1 doz.", 32.6, {2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0}}, - {"Cheese (Cheddar)", - "1 lb.", - 24.2, - {7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0}}, - {"Cream", "1/2 pt.", 14.1, {3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17}}, - {"Peanut Butter", - "1 lb.", - 17.9, - {15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0}}, - {"Mayonnaise", "1/2 pt.", 16.7, {8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0}}, - {"Crisco", "1 lb.", 20.3, {20.1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"Lard", "1 lb.", 9.8, {41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0}}, - {"Sirloin Steak", - "1 lb.", - 39.6, - {2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0}}, - {"Round Steak", "1 lb.", 36.4, {2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0}}, - {"Rib Roast", "1 lb.", 29.2, {3.4, 213, 0.1, 33, 0, 0, 2, 0, 0}}, - {"Chuck Roast", "1 lb.", 22.6, {3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0}}, - {"Plate", "1 lb.", 14.6, {8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0}}, - {"Liver (Beef)", - "1 lb.", - 26.8, - {2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525}}, - {"Leg of Lamb", "1 lb.", 27.6, {3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0}}, - {"Lamb Chops (Rib)", - "1 lb.", - 36.6, - {3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0}}, - {"Pork Chops", "1 lb.", 30.7, {3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0}}, - {"Pork Loin Roast", - "1 lb.", - 24.2, - {4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0}}, - {"Bacon", "1 lb.", 25.6, {10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0}}, - {"Ham, smoked", "1 lb.", 27.4, {6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0}}, - {"Salt Pork", "1 lb.", 16, {18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0}}, - {"Roasting Chicken", - "1 lb.", - 30.3, - {1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46}}, - {"Veal Cutlets", "1 lb.", 42.3, {1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0}}, - {"Salmon, Pink (can)", - "16 oz.", - 13, - {5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0}}, - {"Apples", "1 lb.", 4.4, {5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544}}, - {"Bananas", "1 lb.", 6.1, {4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498}}, - {"Lemons", "1 doz.", 26, {1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952}}, - {"Oranges", "1 doz.", 30.9, {2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998}}, - {"Green Beans", "1 lb.", 7.1, {2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862}}, - {"Cabbage", "1 lb.", 3.7, {2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369}}, - {"Carrots", "1 bunch", 4.7, {2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608}}, - {"Celery", "1 stalk", 7.3, {0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313}}, - {"Lettuce", "1 head", 8.2, {0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449}}, - {"Onions", "1 lb.", 3.6, {5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184}}, - {"Potatoes", - "15 lb.", - 34, - {14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522}}, - {"Spinach", "1 lb.", 8.1, {1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755}}, - {"Sweet Potatoes", - "1 lb.", - 5.1, - {9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912}}, - {"Peaches (can)", - "No. 2 1/2", - 16.8, - {3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196}}, - {"Pears (can)", - "No. 2 1/2", - 20.4, - {3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81}}, - {"Pineapple (can)", - "No. 2 1/2", - 21.3, - {2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399}}, - {"Asparagus (can)", - "No. 2", - 27.7, - {0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272}}, - {"Green Beans (can)", - "No. 2", - 10, - {1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431}}, - {"Pork and Beans (can)", - "16 oz.", - 7.1, - {7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0}}, - {"Corn (can)", "No. 2", 10.4, {5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218}}, - {"Peas (can)", - "No. 2", - 13.8, - {2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370}}, - {"Tomatoes (can)", - "No. 2", - 8.6, - {1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253}}, - {"Tomato Soup (can)", - "10 1/2 oz.", - 7.6, - {1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862}}, - {"Peaches, Dried", - "1 lb.", - 15.7, - {8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57}}, - {"Prunes, Dried", - "1 lb.", - 9, - {12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257}}, - {"Raisins, Dried", - "15 oz.", - 9.4, - {13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136}}, - {"Peas, Dried", - "1 lb.", - 7.9, - {20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0}}, - {"Lima Beans, Dried", - "1 lb.", - 8.9, - {17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0}}, - {"Navy Beans, Dried", - "1 lb.", - 5.9, - {26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0}}, - {"Coffee", "1 lb.", 22.4, {0, 0, 0, 0, 0, 4, 5.1, 50, 0}}, - {"Tea", "1/4 lb.", 17.4, {0, 0, 0, 0, 0, 0, 2.3, 42, 0}}, - {"Cocoa", "8 oz.", 8.6, {8.7, 237, 3, 72, 0, 2, 11.9, 40, 0}}, - {"Chocolate", "8 oz.", 16.2, {8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0}}, - {"Sugar", "10 lb.", 51.7, {34.9, 0, 0, 0, 0, 0, 0, 0, 0}}, - {"Corn Syrup", "24 oz.", 13.7, {14.7, 0, 0.5, 74, 0, 0, 0, 5, 0}}, - {"Molasses", "18 oz.", 13.6, {9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0}}, - {"Strawberry Preserves", - "1 lb.", - 20.5, - {6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0}}}; + { "Wheat Flour (Enriched)", "10 lb.", 36, + { 44.7, 1411, 2, 365, 0, 55.4, 33.3, 441, 0 } }, + { "Macaroni", "1 lb.", 14.1, { 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0 } }, + { "Wheat Cereal (Enriched)", "28 oz.", 24.2, + { 11.8, 377, 14.4, 175, 0, 14.4, 8.8, 114, 0 } }, + { "Corn Flakes", "8 oz.", 7.1, + { 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0 } }, + { "Corn Meal", "1 lb.", 4.6, + { 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0 } }, + { "Hominy Grits", "24 oz.", 8.5, + { 28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0 } }, + { "Rice", "1 lb.", 7.5, { 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0 } }, + { "Rolled Oats", "1 lb.", 7.1, + { 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0 } }, + { "White Bread (Enriched)", "1 lb.", 7.9, + { 15.0, 488, 2.5, 115, 0, 13.8, 8.5, 126, 0 } }, + { "Whole Wheat Bread", "1 lb.", 9.1, + { 12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0 } }, + { "Rye Bread", "1 lb.", 9.1, { 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0 } }, + { "Pound Cake", "1 lb.", 24.8, { 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0 } }, + { "Soda Crackers", "1 lb.", 15.1, { 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0 } }, + { "Milk", "1 qt.", 11, { 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177 } }, + { "Evaporated Milk (can)", "14.5 oz.", 6.7, + { 8.4, 422, 15.1, 9, 26, 3, 23.5, 11, 60 } }, + { "Butter", "1 lb.", 30.8, { 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0 } }, + { "Oleomargarine", "1 lb.", 16.1, + { 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0 } }, + { "Eggs", "1 doz.", 32.6, { 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0 } }, + { "Cheese (Cheddar)", "1 lb.", 24.2, + { 7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0 } }, + { "Cream", "1/2 pt.", 14.1, { 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17 } }, + { "Peanut Butter", "1 lb.", 17.9, + { 15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0 } }, + { "Mayonnaise", "1/2 pt.", 16.7, { 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0 } }, + { "Crisco", "1 lb.", 20.3, { 20.1, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Lard", "1 lb.", 9.8, { 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0 } }, + { "Sirloin Steak", "1 lb.", 39.6, + { 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0 } }, + { "Round Steak", "1 lb.", 36.4, + { 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0 } }, + { "Rib Roast", "1 lb.", 29.2, { 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0 } }, + { "Chuck Roast", "1 lb.", 22.6, { 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0 } }, + { "Plate", "1 lb.", 14.6, { 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0 } }, + { "Liver (Beef)", "1 lb.", 26.8, + { 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525 } }, + { "Leg of Lamb", "1 lb.", 27.6, { 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0 } }, + { "Lamb Chops (Rib)", "1 lb.", 36.6, + { 3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0 } }, + { "Pork Chops", "1 lb.", 30.7, { 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0 } }, + { "Pork Loin Roast", "1 lb.", 24.2, + { 4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0 } }, + { "Bacon", "1 lb.", 25.6, { 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0 } }, + { "Ham, smoked", "1 lb.", 27.4, { 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0 } }, + { "Salt Pork", "1 lb.", 16, { 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0 } }, + { "Roasting Chicken", "1 lb.", 30.3, + { 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46 } }, + { "Veal Cutlets", "1 lb.", 42.3, + { 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0 } }, + { "Salmon, Pink (can)", "16 oz.", 13, + { 5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0 } }, + { "Apples", "1 lb.", 4.4, { 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544 } }, + { "Bananas", "1 lb.", 6.1, { 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498 } }, + { "Lemons", "1 doz.", 26, { 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952 } }, + { "Oranges", "1 doz.", 30.9, + { 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998 } }, + { "Green Beans", "1 lb.", 7.1, + { 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862 } }, + { "Cabbage", "1 lb.", 3.7, { 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369 } }, + { "Carrots", "1 bunch", 4.7, + { 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608 } }, + { "Celery", "1 stalk", 7.3, { 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313 } }, + { "Lettuce", "1 head", 8.2, + { 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449 } }, + { "Onions", "1 lb.", 3.6, { 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184 } }, + { "Potatoes", "15 lb.", 34, + { 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522 } }, + { "Spinach", "1 lb.", 8.1, + { 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755 } }, + { "Sweet Potatoes", "1 lb.", 5.1, + { 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912 } }, + { "Peaches (can)", "No. 2 1/2", 16.8, + { 3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196 } }, + { "Pears (can)", "No. 2 1/2", 20.4, + { 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81 } }, + { "Pineapple (can)", "No. 2 1/2", 21.3, + { 2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399 } }, + { "Asparagus (can)", "No. 2", 27.7, + { 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272 } }, + { "Green Beans (can)", "No. 2", 10, + { 1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431 } }, + { "Pork and Beans (can)", "16 oz.", 7.1, + { 7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0 } }, + { "Corn (can)", "No. 2", 10.4, + { 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218 } }, + { "Peas (can)", "No. 2", 13.8, + { 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370 } }, + { "Tomatoes (can)", "No. 2", 8.6, + { 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253 } }, + { "Tomato Soup (can)", "10 1/2 oz.", 7.6, + { 1.6, 71, 0.6, 43, 57.9, 3.5, 2.4, 67, 862 } }, + { "Peaches, Dried", "1 lb.", 15.7, + { 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57 } }, + { "Prunes, Dried", "1 lb.", 9, + { 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257 } }, + { "Raisins, Dried", "15 oz.", 9.4, + { 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136 } }, + { "Peas, Dried", "1 lb.", 7.9, + { 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0 } }, + { "Lima Beans, Dried", "1 lb.", 8.9, + { 17.4, 1055, 3.7, 459, 5.1, 26.9, 38.2, 93, 0 } }, + { "Navy Beans, Dried", "1 lb.", 5.9, + { 26.9, 1691, 11.4, 792, 0, 38.4, 24.6, 217, 0 } }, + { "Coffee", "1 lb.", 22.4, { 0, 0, 0, 0, 0, 4, 5.1, 50, 0 } }, + { "Tea", "1/4 lb.", 17.4, { 0, 0, 0, 0, 0, 0, 2.3, 42, 0 } }, + { "Cocoa", "8 oz.", 8.6, { 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0 } }, + { "Chocolate", "8 oz.", 16.2, { 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0 } }, + { "Sugar", "10 lb.", 51.7, { 34.9, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Corn Syrup", "24 oz.", 13.7, { 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0 } }, + { "Molasses", "18 oz.", 13.6, { 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0 } }, + { "Strawberry Preserves", "1 lb.", 20.5, + { 6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0 } } + }; // Instantiate the solver MPSolver solver("StiglerDietExample", MPSolver::GLOP_LINEAR_PROGRAMMING); // Declare an array to hold our nutritional data. - std::vector food; + std::vector food; // Objective: minimize the sum of (price-normalized) foods. - MPObjective* const objective = solver.MutableObjective(); + MPObjective *const objective = solver.MutableObjective(); const double infinity = solver.infinity(); - for (const Commodity& commodity : data) { + for (const Commodity &commodity : data) { food.push_back(solver.MakeNumVar(0.0, infinity, commodity.name)); objective->SetCoefficient(food.back(), 1); } objective->SetMinimization(); // Create the constraints, one per nutrient. - std::vector constraints; + std::vector constraints; for (std::size_t i = 0; i < nutrients.size(); ++i) { constraints.push_back( solver.MakeRowConstraint(nutrients[i].second, infinity)); @@ -290,11 +233,11 @@ void RunStiglerDietExample() { LOG(INFO) << "Problem solved in " << solver.wall_time() << " milliseconds"; LOG(INFO) << "Problem solved in " << solver.iterations() << " iterations"; } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); - FLAGS_logtostderr = 1; + absl::GetFlag(FLAGS_logtostderr) = 1; operations_research::RunStiglerDietExample(); return EXIT_SUCCESS; } diff --git a/examples/cpp/strawberry_fields_with_column_generation.cc b/examples/cpp/strawberry_fields_with_column_generation.cc index 67b9a10229..aaa1cadc47 100644 --- a/examples/cpp/strawberry_fields_with_column_generation.cc +++ b/examples/cpp/strawberry_fields_with_column_generation.cc @@ -52,7 +52,7 @@ // No attempt is made to force integrality. #include -#include // strlen +#include // strlen #include #include #include @@ -77,170 +77,162 @@ struct Instance { int max_boxes; int width; int height; - const char* grid; + const char *grid; }; -Instance kInstances[] = {{4, 22, 6, - "..@@@@@..............." - "..@@@@@@........@@@..." - ".....@@@@@......@@@..." - ".......@@@@@@@@@@@@..." - ".........@@@@@........" - ".........@@@@@........"}, - {3, 13, 10, - "............." - "............." - "............." - "...@@@@......" - "...@@@@......" - "...@@@@......" - ".......@@@..." - ".......@@@..." - ".......@@@..." - "............."}, - {4, 13, 9, - "............." - "..@.@.@......" - "...@.@.@....." - "..@.@.@......" - "..@.@.@......" - "...@.@.@....." - "....@.@......" - "..........@@@" - "..........@@@"}, - {4, 13, 9, - ".........@..." - ".........@..." - "@@@@@@@@@@..." - "..@......@..." - "..@......@..." - "..@......@..." - "..@@@@@@@@@@@" - "..@.........." - "..@.........."}, - {7, 25, 14, - "........................." - "..@@@@@@@@@@@@@@@@@@@@..." - "..@@@@@@@@@@@@@@@@@@@@..." - "..@@.................@..." - "..@@.................@..." - "..@@.......@@@.......@.@." - "..@@.......@@@.......@..." - "..@@...@@@@@@@@@@@@@@@..." - "..@@...@@@@@@@@@@@@@@@..." - "..@@.......@@@.......@..." - "..@@.......@@@.......@..." - "..@@.................@..." - "..@@.................@..." - "........................."}, - {6, 25, 16, - "........................." - "......@@@@@@@@@@@@@......" - "........................." - ".....@..........@........" - ".....@..........@........" - ".....@......@............" - ".....@......@.@@@@@@@...." - ".....@......@............" - ".....@......@.@@@@@@@...." - ".....@......@............" - "....@@@@....@............" - "....@@@@....@............" - "..@@@@@@....@............" - "..@@@.......@............" - "..@@@...................." - "..@@@@@@@@@@@@@@@@@@@@@@@"}, - {5, 40, 18, - "........................................" - "........................................" - "...@@@@@@..............................." - "...@@@@@@..............................." - "...@@@@@@..............................." - "...@@@@@@.........@@@@@@@@@@............" - "...@@@@@@.........@@@@@@@@@@............" - "..................@@@@@@@@@@............" - "..................@@@@@@@@@@............" - ".............@@@@@@@@@@@@@@@............" - ".............@@@@@@@@@@@@@@@............" - "........@@@@@@@@@@@@...................." - "........@@@@@@@@@@@@...................." - "........@@@@@@.........................." - "........@@@@@@.........................." - "........................................" - "........................................" - "........................................"}, - {8, 40, 18, - "........................................" - "..@@.@.@.@.............................." - "..@@.@.@.@...............@.............." - "..@@.@.@.@............@................." - "..@@.@.@.@.............................." - "..@@.@.@.@.................@............" - "..@@.@..................@..............." - "..@@.@.................................." - "..@@.@.................................." - "..@@.@................@@@@.............." - "..@@.@..............@@@@@@@@............" - "..@@.@.................................." - "..@@.@..............@@@@@@@@............" - "..@@.@.................................." - "..@@.@................@@@@.............." - "..@@.@.................................." - "..@@.@.................................." - "........................................"}, - {10, 40, 19, - "@@@@@..................................." - "@@@@@..................................." - "@@@@@..................................." - "@@@@@..................................." - "@@@@@..................................." - "@@@@@...........@@@@@@@@@@@............." - "@@@@@...........@@@@@@@@@@@............." - "....................@@@@................" - "....................@@@@................" - "....................@@@@................" - "....................@@@@................" - "....................@@@@................" - "...............@@@@@@@@@@@@@@..........." - "...............@@@@@@@@@@@@@@..........." - ".......@@@@@@@@@@@@@@@@@@@@@@..........." - ".......@@@@@@@@@........................" - "........................................" - "........................................" - "........................................"}, - {10, 40, 25, - "...................@...................." - "...............@@@@@@@@@................" - "............@@@.........@@@............." - "...........@...............@............" - "..........@.................@..........." - ".........@...................@.........." - ".........@...................@.........." - ".........@.....@@......@@....@.........." - "........@.....@@@@....@@@@....@........." - "........@.....................@........." - "........@.....................@........." - "........@..........@@.........@........." - ".......@@..........@@.........@@........" - "........@.....................@........." - "........@.....................@........." - "........@......@@@@@@@@@......@........." - "........@......@@@@@@@@@......@........." - ".........@...................@.........." - ".........@...................@.........." - ".........@...................@.........." - "..........@.................@..........." - "...........@...............@............" - "............@@@.........@@@............." - "...............@@@@@@@@@................" - "...................@...................."}}; +Instance kInstances[] = { + { 4, 22, 6, "..@@@@@..............." + "..@@@@@@........@@@..." + ".....@@@@@......@@@..." + ".......@@@@@@@@@@@@..." + ".........@@@@@........" + ".........@@@@@........" }, + { 3, 13, 10, "............." + "............." + "............." + "...@@@@......" + "...@@@@......" + "...@@@@......" + ".......@@@..." + ".......@@@..." + ".......@@@..." + "............." }, + { 4, 13, 9, "............." + "..@.@.@......" + "...@.@.@....." + "..@.@.@......" + "..@.@.@......" + "...@.@.@....." + "....@.@......" + "..........@@@" + "..........@@@" }, + { 4, 13, 9, ".........@..." + ".........@..." + "@@@@@@@@@@..." + "..@......@..." + "..@......@..." + "..@......@..." + "..@@@@@@@@@@@" + "..@.........." + "..@.........." }, + { 7, 25, 14, "........................." + "..@@@@@@@@@@@@@@@@@@@@..." + "..@@@@@@@@@@@@@@@@@@@@..." + "..@@.................@..." + "..@@.................@..." + "..@@.......@@@.......@.@." + "..@@.......@@@.......@..." + "..@@...@@@@@@@@@@@@@@@..." + "..@@...@@@@@@@@@@@@@@@..." + "..@@.......@@@.......@..." + "..@@.......@@@.......@..." + "..@@.................@..." + "..@@.................@..." + "........................." }, + { 6, 25, 16, "........................." + "......@@@@@@@@@@@@@......" + "........................." + ".....@..........@........" + ".....@..........@........" + ".....@......@............" + ".....@......@.@@@@@@@...." + ".....@......@............" + ".....@......@.@@@@@@@...." + ".....@......@............" + "....@@@@....@............" + "....@@@@....@............" + "..@@@@@@....@............" + "..@@@.......@............" + "..@@@...................." + "..@@@@@@@@@@@@@@@@@@@@@@@" }, + { 5, 40, 18, "........................................" + "........................................" + "...@@@@@@..............................." + "...@@@@@@..............................." + "...@@@@@@..............................." + "...@@@@@@.........@@@@@@@@@@............" + "...@@@@@@.........@@@@@@@@@@............" + "..................@@@@@@@@@@............" + "..................@@@@@@@@@@............" + ".............@@@@@@@@@@@@@@@............" + ".............@@@@@@@@@@@@@@@............" + "........@@@@@@@@@@@@...................." + "........@@@@@@@@@@@@...................." + "........@@@@@@.........................." + "........@@@@@@.........................." + "........................................" + "........................................" + "........................................" }, + { 8, 40, 18, "........................................" + "..@@.@.@.@.............................." + "..@@.@.@.@...............@.............." + "..@@.@.@.@............@................." + "..@@.@.@.@.............................." + "..@@.@.@.@.................@............" + "..@@.@..................@..............." + "..@@.@.................................." + "..@@.@.................................." + "..@@.@................@@@@.............." + "..@@.@..............@@@@@@@@............" + "..@@.@.................................." + "..@@.@..............@@@@@@@@............" + "..@@.@.................................." + "..@@.@................@@@@.............." + "..@@.@.................................." + "..@@.@.................................." + "........................................" }, + { 10, 40, 19, "@@@@@..................................." + "@@@@@..................................." + "@@@@@..................................." + "@@@@@..................................." + "@@@@@..................................." + "@@@@@...........@@@@@@@@@@@............." + "@@@@@...........@@@@@@@@@@@............." + "....................@@@@................" + "....................@@@@................" + "....................@@@@................" + "....................@@@@................" + "....................@@@@................" + "...............@@@@@@@@@@@@@@..........." + "...............@@@@@@@@@@@@@@..........." + ".......@@@@@@@@@@@@@@@@@@@@@@..........." + ".......@@@@@@@@@........................" + "........................................" + "........................................" + "........................................" }, + { 10, 40, 25, "...................@...................." + "...............@@@@@@@@@................" + "............@@@.........@@@............." + "...........@...............@............" + "..........@.................@..........." + ".........@...................@.........." + ".........@...................@.........." + ".........@.....@@......@@....@.........." + "........@.....@@@@....@@@@....@........." + "........@.....................@........." + "........@.....................@........." + "........@..........@@.........@........." + ".......@@..........@@.........@@........" + "........@.....................@........." + "........@.....................@........." + "........@......@@@@@@@@@......@........." + "........@......@@@@@@@@@......@........." + ".........@...................@.........." + ".........@...................@.........." + ".........@...................@.........." + "..........@.................@..........." + "...........@...............@............" + "............@@@.........@@@............." + "...............@@@@@@@@@................" + "...................@...................." } +}; const int kInstanceCount = 10; // ---------- Box --------- class Box { - public: +public: static const int kAreaCost = 1; static const int kFixedCost = 10; @@ -257,11 +249,14 @@ class Box { int y_max() const { return y_max_; } // Lexicographic order - int Compare(const Box& box) const { + int Compare(const Box &box) const { int c; - if ((c = (x_min() - box.x_min())) != 0) return c; - if ((c = (x_max() - box.x_max())) != 0) return c; - if ((c = (y_min() - box.y_min())) != 0) return c; + if ((c = (x_min() - box.x_min())) != 0) + return c; + if ((c = (x_max() - box.x_max())) != 0) + return c; + if ((c = (y_min() - box.y_min())) != 0) + return c; return y_max() - box.y_max(); } @@ -279,7 +274,7 @@ class Box { y_max(), Cost()); } - private: +private: int x_min_; int x_max_; int y_min_; @@ -287,7 +282,7 @@ class Box { }; struct BoxLessThan { - bool operator()(const Box& b1, const Box& b2) const { + bool operator()(const Box &b1, const Box &b2) const { return b1.Compare(b2) < 0; } }; @@ -295,16 +290,13 @@ struct BoxLessThan { // ---------- Covering Problem --------- class CoveringProblem { - public: +public: // Grid is a row-major string of length width*height with '@' for an // occupied cell (strawberry) and '.' for an empty cell. Solver is // not owned. - CoveringProblem(MPSolver* const solver, const Instance& instance) - : solver_(solver), - max_boxes_(instance.max_boxes), - width_(instance.width), - height_(instance.height), - grid_(instance.grid) {} + CoveringProblem(MPSolver *const solver, const Instance &instance) + : solver_(solver), max_boxes_(instance.max_boxes), width_(instance.width), + height_(instance.height), grid_(instance.grid) {} // Constructs initial variables and constraints. Initial column // (box) covers entire grid, ensuring feasibility. @@ -316,13 +308,14 @@ class CoveringProblem { } for (int i = 0; i < size; ++i) { char c = grid_[i]; - if ((c != '@') && (c != '.')) return false; + if ((c != '@') && (c != '.')) + return false; } - AddCellConstraints(); // sum for every cell is <=1 or =1 - AddMaxBoxesConstraint(); // sum of box variables is <= max_boxes() - if (!FLAGS_colgen_complete) { - AddBox(Box(0, width() - 1, 0, height() - 1)); // grid-covering box + AddCellConstraints(); // sum for every cell is <=1 or =1 + AddMaxBoxesConstraint(); // sum of box variables is <= max_boxes() + if (!absl::GetFlag(FLAGS_colgen_complete)) { + AddBox(Box(0, width() - 1, 0, height() - 1)); // grid-covering box } else { // Naive alternative to column generation - generate all boxes; // works fine for smaller problems, too slow for big. @@ -366,7 +359,7 @@ class CoveringProblem { // each, so pre-calculate sums of cell duals for all rectangles with // upper-left at 0, 0, and use these to calculate the sum in // constant time using the standard inclusion-exclusion trick. - double GetOptimalBox(Box* const target) { + double GetOptimalBox(Box *const target) { // Cost change threshold for new Box const double kCostChangeThreshold = -.01; @@ -383,7 +376,7 @@ class CoveringProblem { for (int x_min = 0; x_min < width(); ++x_min) { for (int x_max = x_min; x_max < width(); ++x_max) { Box box(x_min, x_max, y_min, y_max); - const double cell_coverage_dual = // inclusion-exclusion + const double cell_coverage_dual = // inclusion-exclusion +zero_access(upper_left_sums, x_max, y_max) - zero_access(upper_left_sums, x_max, y_min - 1) - zero_access(upper_left_sums, x_min - 1, y_max) + @@ -426,9 +419,9 @@ class CoveringProblem { // Add continuous [0,1] box variable with box.Cost() as objective // coefficient. Add to cell constraint of all enclosed cells. - MPVariable* AddBox(const Box& box) { + MPVariable *AddBox(const Box &box) { CHECK(boxes_.find(box) == boxes_.end()); - MPVariable* const var = solver_->MakeNumVar(0., 1., box.DebugString()); + MPVariable *const var = solver_->MakeNumVar(0., 1., box.DebugString()); solver_->MutableObjective()->SetCoefficient(var, box.Cost()); max_boxes_constraint_->SetCoefficient(var, 1.0); for (int y = box.y_min(); y <= box.y_max(); ++y) { @@ -462,7 +455,7 @@ class CoveringProblem { std::unique_ptr display(new char[(width_ + 1) * height_ + 1]); for (int y = 0; y < height_; ++y) { memcpy(display.get() + y * (width_ + 1), grid_ + width_ * y, - width_); // Copy the original line. + width_); // Copy the original line. display[y * (width_ + 1) + width_] = '\n'; } display[height_ * (width_ + 1)] = '\0'; @@ -475,7 +468,7 @@ class CoveringProblem { active_box_index++; absl::StrAppendFormat(&output, "%c: box %s with value %f\n", box_character, i->first.DebugString(), value); - const Box& box = i->first; + const Box &box = i->first; for (int x = box.x_min(); x <= box.x_max(); ++x) { for (int y = box.y_min(); y <= box.y_max(); ++y) { display[x + y * (width_ + 1)] = box_character; @@ -487,10 +480,10 @@ class CoveringProblem { return output; } - protected: +protected: int index(int x, int y) const { return width_ * y + x; } - MPConstraint* cell(int x, int y) { return cells_[index(x, y)]; } - const MPConstraint* cell(int x, int y) const { return cells_[index(x, y)]; } + MPConstraint *cell(int x, int y) { return cells_[index(x, y)]; } + const MPConstraint *cell(int x, int y) const { return cells_[index(x, y)]; } // Adds constraints that every cell is covered at most once, exactly // once if occupied. @@ -510,7 +503,7 @@ class CoveringProblem { } // Gets 2d array element, returning 0 if out-of-bounds. - double zero_access(const std::vector& array, int x, int y) const { + double zero_access(const std::vector &array, int x, int y) const { if (x < 0 || y < 0) { return 0; } @@ -519,7 +512,7 @@ class CoveringProblem { // Precomputes the sum of reduced costs for every upper-left // rectangle. - void ComputeUpperLeftSums(std::vector* upper_left_sums) const { + void ComputeUpperLeftSums(std::vector *upper_left_sums) const { for (int y = 0; y < height(); ++y) { for (int x = 0; x < width(); ++x) { upper_left_sums->operator[](index(x, y)) = @@ -530,22 +523,22 @@ class CoveringProblem { } } - typedef std::map BoxTable; - MPSolver* const solver_; // not owned + typedef std::map BoxTable; + MPSolver *const solver_; // not owned const int max_boxes_; const int width_; const int height_; - const char* const grid_; - std::vector cells_; + const char *const grid_; + std::vector cells_; BoxTable boxes_; - MPConstraint* max_boxes_constraint_; + MPConstraint *max_boxes_constraint_; }; // ---------- Main Solve Method ---------- // Solves iteratively using delayed column generation, up to maximum // number of steps. -void SolveInstance(const Instance& instance, +void SolveInstance(const Instance &instance, MPSolver::OptimizationProblemType solver_type) { // Prepares the solver. MPSolver solver("ColumnGeneration", solver_type); @@ -558,14 +551,14 @@ void SolveInstance(const Instance& instance, LOG(INFO) << "Initial problem:\n" << problem.PrintGrid(); int step_number = 0; - while (step_number < FLAGS_colgen_max_iterations) { - if (FLAGS_colgen_verbose) { + while (step_number < absl::GetFlag(FLAGS_colgen_max_iterations)) { + if (absl::GetFlag(FLAGS_colgen_verbose)) { LOG(INFO) << "Step number " << step_number; } // Solve with existing columns. CHECK_EQ(MPSolver::OPTIMAL, solver.Solve()); - if (FLAGS_colgen_verbose) { + if (absl::GetFlag(FLAGS_colgen_verbose)) { LOG(INFO) << problem.PrintCovering(); } @@ -577,7 +570,7 @@ void SolveInstance(const Instance& instance, } // Add new column to problem. - if (FLAGS_colgen_verbose) { + if (absl::GetFlag(FLAGS_colgen_verbose)) { LOG(INFO) << "Adding " << box.DebugString() << ", reduced_cost =" << reduced_cost; } @@ -586,7 +579,7 @@ void SolveInstance(const Instance& instance, ++step_number; } - if (step_number >= FLAGS_colgen_max_iterations) { + if (step_number >= absl::GetFlag(FLAGS_colgen_max_iterations)) { // Solve one last time with all generated columns. CHECK_EQ(MPSolver::OPTIMAL, solver.Solve()); } @@ -594,9 +587,9 @@ void SolveInstance(const Instance& instance, LOG(INFO) << step_number << " columns added"; LOG(INFO) << "Final coverage: " << problem.PrintCovering(); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { std::string usage = "column_generation\n"; usage += " --colgen_verbose print verbosely\n"; usage += " --colgen_max_iterations max columns to generate\n"; @@ -607,48 +600,50 @@ int main(int argc, char** argv) { operations_research::MPSolver::OptimizationProblemType solver_type; bool found = false; #if defined(USE_CLP) - if (FLAGS_colgen_solver == "clp") { + if (absl::GetFlag(FLAGS_colgen_solver) == "clp") { solver_type = operations_research::MPSolver::CLP_LINEAR_PROGRAMMING; found = true; } -#endif // USE_CLP +#endif // USE_CLP #if defined(USE_GLOP) - if (FLAGS_colgen_solver == "glop") { + if (absl::GetFlag(FLAGS_colgen_solver) == "glop") { solver_type = operations_research::MPSolver::GLOP_LINEAR_PROGRAMMING; found = true; } -#endif // USE_GLOP +#endif // USE_GLOP #if defined(USE_XPRESS) - if (FLAGS_colgen_solver == "xpress") { + if (absl::GetFlag(FLAGS_colgen_solver) == "xpress") { solver_type = operations_research::MPSolver::XPRESS_LINEAR_PROGRAMMING; // solver_type = operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING; found = true; } #endif #if defined(USE_CPLEX) - if (FLAGS_colgen_solver == "cplex") { + if (absl::GetFlag(FLAGS_colgen_solver) == "cplex") { solver_type = operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING; found = true; } #endif if (!found) { - LOG(ERROR) << "Unknown solver " << FLAGS_colgen_solver; + LOG(ERROR) << "Unknown solver " << absl::GetFlag(FLAGS_colgen_solver); return 1; } - LOG(INFO) << "Chosen solver: " << FLAGS_colgen_solver << std::endl; + LOG(INFO) << "Chosen solver: " << absl::GetFlag(FLAGS_colgen_solver) + << std::endl; - if (FLAGS_colgen_instance == -1) { + if (absl::GetFlag(FLAGS_colgen_instance) == -1) { for (int i = 0; i < operations_research::kInstanceCount; ++i) { - const operations_research::Instance& instance = + const operations_research::Instance &instance = operations_research::kInstances[i]; operations_research::SolveInstance(instance, solver_type); } } else { - CHECK_GE(FLAGS_colgen_instance, 0); - CHECK_LT(FLAGS_colgen_instance, operations_research::kInstanceCount); - const operations_research::Instance& instance = - operations_research::kInstances[FLAGS_colgen_instance]; + CHECK_GE(absl::GetFlag(FLAGS_colgen_instance), 0); + CHECK_LT(absl::GetFlag(FLAGS_colgen_instance), + operations_research::kInstanceCount); + const operations_research::Instance &instance = + operations_research::kInstances[absl::GetFlag(FLAGS_colgen_instance)]; operations_research::SolveInstance(instance, solver_type); } return EXIT_SUCCESS; diff --git a/examples/cpp/uncapacitated_facility_location.cc b/examples/cpp/uncapacitated_facility_location.cc index 81ff1ea44a..abcc37c0b3 100644 --- a/examples/cpp/uncapacitated_facility_location.cc +++ b/examples/cpp/uncapacitated_facility_location.cc @@ -39,17 +39,22 @@ DEFINE_double(fix_cost, 5000, "Cost of opening a facility."); namespace operations_research { typedef struct { - double x{0}; - double y{0}; + double x { 0 } + ; + double y { 0 } + ; } Location; typedef struct { - int f{-1}; - int c{-1}; - MPVariable* x{nullptr}; + int f { -1 } + ; + int c { -1 } + ; + MPVariable *x { nullptr } + ; } Edge; -static double Distance(const Location& src, const Location& dst) { +static double Distance(const Location &src, const Location &dst) { return sqrt((src.x - dst.x) * (src.x - dst.x) + (src.y - dst.y) * (src.y - dst.y)); } @@ -91,15 +96,16 @@ static void UncapacitatedFacilityLocation( // Distance(f,c) <= kMaxDistance MPSolver solver("UncapacitatedFacilityLocation", optimization_problem_type); const double infinity = solver.infinity(); - MPObjective* objective = solver.MutableObjective(); + MPObjective *objective = solver.MutableObjective(); objective->SetMinimization(); // Add binary facilities variables - std::vector xf{}; + std::vector xf {} + ; for (int f = 0; f < facilities; ++f) { snprintf(name_buffer, kStrLen, "x[%d](%g,%g)", f, facility[f].x, facility[f].y); - MPVariable* x = solver.MakeBoolVar(name_buffer); + MPVariable *x = solver.MakeBoolVar(name_buffer); xf.push_back(x); objective->SetCoefficient(x, fix_cost); } @@ -109,13 +115,14 @@ static void UncapacitatedFacilityLocation( for (int c = 0; c < clients; ++c) { snprintf(name_buffer, kStrLen, "R-Client[%d](%g,%g)", c, client[c].x, client[c].y); - MPConstraint* client_constraint = - solver.MakeRowConstraint(/* lb */ 1, - /* ub */ infinity, name_buffer); + MPConstraint *client_constraint = + solver.MakeRowConstraint(/* lb */ 1, /* ub */ infinity, name_buffer); for (int f = 0; f < facilities; ++f) { double distance = Distance(facility[f], client[c]); - if (distance > kMaxDistance) continue; - Edge edge{}; + if (distance > kMaxDistance) + continue; + Edge edge {} + ; snprintf(name_buffer, kStrLen, "x[%d,%d]", f, c); edge.x = solver.MakeNumVar(/* lb */ 0, /*ub */ 1, name_buffer); edge.f = f; @@ -126,18 +133,18 @@ static void UncapacitatedFacilityLocation( client_constraint->SetCoefficient(edge.x, 1); // add constraint (2) snprintf(name_buffer, kStrLen, "R-Edge[%d,%d]", f, c); - MPConstraint* edge_constraint = - solver.MakeRowConstraint(/* lb */ 0, - /* ub */ infinity, name_buffer); + MPConstraint *edge_constraint = + solver.MakeRowConstraint(/* lb */ 0, /* ub */ infinity, name_buffer); edge_constraint->SetCoefficient(edge.x, -1); edge_constraint->SetCoefficient(xf[f], 1); } - } // End adding all edge variables + } // End adding all edge variables LOG(INFO) << "Number of variables = " << solver.NumVariables(); LOG(INFO) << "Number of constraints = " << solver.NumConstraints(); // display on screen LP if small enough if (clients <= 10 && facilities <= 10) { - std::string lp_string{}; + std::string lp_string {} + ; solver.ExportModelAsLpFormat(/* obfuscate */ false, &lp_string); std::cout << "LP-Model:\n" << lp_string << std::endl; } @@ -151,15 +158,17 @@ static void UncapacitatedFacilityLocation( LOG(FATAL) << "The problem does not have an optimal solution!"; } else { LOG(INFO) << "Optimal objective value = " << objective->Value(); - if (FLAGS_verbose) { - std::vector> solution(facilities); - for (auto& edge : edges) { - if (edge.x->solution_value() < 0.5) continue; + if (absl::GetFlag(FLAGS_verbose)) { + std::vector > solution(facilities); + for (auto &edge : edges) { + if (edge.x->solution_value() < 0.5) + continue; solution[edge.f].push_back(edge.c); } std::cout << "\tSolution:\n"; for (int f = 0; f < facilities; ++f) { - if (solution[f].size() < 1) continue; + if (solution[f].size() < 1) + continue; assert(xf[f]->solution_value() > 0.5); snprintf(name_buffer, kStrLen, "\t Facility[%d](%g,%g):", f, facility[f].x, facility[f].y); @@ -208,30 +217,34 @@ void RunAllExamples(int32 facilities, int32 clients, double fix_cost) { LOG(INFO) << "---- Integer programming example with Gurobi ----"; UncapacitatedFacilityLocation(facilities, clients, fix_cost, MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING); -#endif // USE_GUROBI +#endif // USE_GUROBI #if defined(USE_CPLEX) LOG(INFO) << "---- Integer programming example with CPLEX ----"; UncapacitatedFacilityLocation(facilities, clients, fix_cost, MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING); -#endif // USE_CPLEX +#endif // USE_CPLEX LOG(INFO) << "---- Integer programming example with CP-SAT ----"; UncapacitatedFacilityLocation(facilities, clients, fix_cost, MPSolver::SAT_INTEGER_PROGRAMMING); } -} // namespace operations_research +} // namespace operations_research -int main(int argc, char** argv) { +int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); gflags::SetUsageMessage( std::string("This program solve a (randomly generated)\n") + std::string("Uncapacitated Facility Location Problem. Sample Usage:\n")); gflags::ParseCommandLineFlags(&argc, &argv, true); - CHECK_LT(0, FLAGS_facilities) << "Specify an instance size greater than 0."; - CHECK_LT(0, FLAGS_clients) << "Specify a non-null client size."; - CHECK_LT(0, FLAGS_fix_cost) << "Specify a non-null client size."; - FLAGS_logtostderr = 1; - operations_research::RunAllExamples(FLAGS_facilities, FLAGS_clients, - FLAGS_fix_cost); + CHECK_LT(0, absl::GetFlag(FLAGS_facilities)) + << "Specify an instance size greater than 0."; + CHECK_LT(0, absl::GetFlag(FLAGS_clients)) + << "Specify a non-null client size."; + CHECK_LT(0, absl::GetFlag(FLAGS_fix_cost)) + << "Specify a non-null client size."; + absl::GetFlag(FLAGS_logtostderr) = 1; + operations_research::RunAllExamples(absl::GetFlag(FLAGS_facilities), + absl::GetFlag(FLAGS_clients), + absl::GetFlag(FLAGS_fix_cost)); return EXIT_SUCCESS; } diff --git a/examples/cpp/variable_intervals_sat.cc b/examples/cpp/variable_intervals_sat.cc index c58af91376..e78153b17b 100644 --- a/examples/cpp/variable_intervals_sat.cc +++ b/examples/cpp/variable_intervals_sat.cc @@ -24,10 +24,15 @@ void Solve() { const IntVar end_p2 = cp_model.NewIntVar(Domain(500, 1000)); const IntervalVar p2 = cp_model.NewIntervalVar(start_p2, duration_p2, end_p2); - cp_model.AddEquality(LinearExpr::Sum({duration_p1, duration_p2}), 360); + cp_model.AddEquality(LinearExpr::Sum({ + duration_p1, duration_p2 + }), + 360); cp_model.AddLessOrEqual(end_p1, start_p2); - cp_model.AddNoOverlap({ins, p1, p2}); + cp_model.AddNoOverlap({ + ins, p1, p2 + }); Model model; @@ -42,7 +47,7 @@ void Solve() { const int kSolutionLimit = 100; int num_solutions = 0; - model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse& r) { + model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse & r) { LOG(INFO) << "Solution " << num_solutions; LOG(INFO) << " start_p1 = " << SolutionIntegerValue(r, start_p1); LOG(INFO) << " duration_p1 = " << SolutionIntegerValue(r, duration_p1); @@ -60,8 +65,8 @@ void Solve() { LOG(INFO) << "Number of solutions found: " << num_solutions; } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research int main() { operations_research::sat::Solve(); diff --git a/examples/cpp/weighted_tardiness_sat.cc b/examples/cpp/weighted_tardiness_sat.cc index 88e45996a5..5a13971e00 100644 --- a/examples/cpp/weighted_tardiness_sat.cc +++ b/examples/cpp/weighted_tardiness_sat.cc @@ -39,9 +39,9 @@ namespace operations_research { namespace sat { // Solve a single machine problem with weighted tardiness cost. -void Solve(const std::vector& durations, - const std::vector& due_dates, - const std::vector& weights) { +void Solve(const std::vector &durations, + const std::vector &due_dates, + const std::vector &weights) { const int num_tasks = durations.size(); CHECK_EQ(due_dates.size(), num_tasks); CHECK_EQ(weights.size(), num_tasks); @@ -63,7 +63,8 @@ void Solve(const std::vector& durations, int next_task = -1; int64 next_cost; for (int j = 0; j < num_tasks; ++j) { - if (is_taken[j]) continue; + if (is_taken[j]) + continue; const int64 cost = weights[j] * std::max(0, end - due_dates[j]); if (next_task == -1 || cost < next_cost) { next_task = j; @@ -117,7 +118,8 @@ void Solve(const std::vector& durations, cp_model.AddNoOverlap(task_intervals); // TODO(user): We can't set an objective upper bound with the current cp_model - // interface, so we can't use heuristic or FLAGS_upper_bound here. The best is + // interface, so we can't use heuristic or absl::GetFlag(FLAGS_upper_bound) + // here. The best is // probably to provide a "solution hint" instead. // // Set a known upper bound (or use the flag). This has a bigger impact than @@ -141,7 +143,8 @@ void Solve(const std::vector& durations, int num_added_precedences = 0; for (int i = 0; i < num_tasks; ++i) { for (int j = 0; j < num_tasks; ++j) { - if (i == j) continue; + if (i == j) + continue; if (due_dates[i] <= due_dates[j] && durations[i] <= durations[j] && weights[i] >= weights[j]) { // If two jobs have exactly the same specs, we don't add both @@ -164,8 +167,8 @@ void Solve(const std::vector& durations, // Note that we only fully instantiate the start/end and only look at the // lower bound for the objective and the tardiness variables. Model model; - model.Add(NewSatParameters(FLAGS_params)); - model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse& r) { + model.Add(NewSatParameters(absl::GetFlag(FLAGS_params))); + model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse & r) { // Note that we compute the "real" cost here and do not use the tardiness // variables. This is because in the core based approach, the tardiness // variable might be fixed before the end date, and we just have a >= @@ -215,41 +218,45 @@ void Solve(const std::vector& durations, void ParseAndSolve() { std::vector numbers; std::vector entries; - for (const std::string& line : FileLines(FLAGS_input)) { + for (const std::string &line : FileLines(absl::GetFlag(FLAGS_input))) { entries = absl::StrSplit(line, ' ', absl::SkipEmpty()); - for (const std::string& entry : entries) { + for (const std::string &entry : entries) { numbers.push_back(0); CHECK(absl::SimpleAtoi(entry, &numbers.back())); } } - const int instance_size = FLAGS_size * 3; - LOG(INFO) << numbers.size() << " numbers in '" << FLAGS_input << "'."; + const int instance_size = absl::GetFlag(FLAGS_size) * 3; + LOG(INFO) << numbers.size() << " numbers in '" << absl::GetFlag(FLAGS_input) + << "'."; LOG(INFO) << "This correspond to " << numbers.size() / instance_size - << " instances of size " << FLAGS_size; - LOG(INFO) << "Loading instance #" << FLAGS_n; - CHECK_GE(FLAGS_n, 0); - CHECK_LE(FLAGS_n * instance_size, numbers.size()); + << " instances of size " << absl::GetFlag(FLAGS_size); + LOG(INFO) << "Loading instance #" << absl::GetFlag(FLAGS_n); + CHECK_GE(absl::GetFlag(FLAGS_n), 0); + CHECK_LE(absl::GetFlag(FLAGS_n) * instance_size, numbers.size()); // The order in a wt file is: duration, tardiness weights and then due_dates. - int index = (FLAGS_n - 1) * instance_size; + int index = (absl::GetFlag(FLAGS_n) - 1) * instance_size; std::vector durations; - for (int j = 0; j < FLAGS_size; ++j) durations.push_back(numbers[index++]); + for (int j = 0; j < absl::GetFlag(FLAGS_size); ++j) + durations.push_back(numbers[index++]); std::vector weights; - for (int j = 0; j < FLAGS_size; ++j) weights.push_back(numbers[index++]); + for (int j = 0; j < absl::GetFlag(FLAGS_size); ++j) + weights.push_back(numbers[index++]); std::vector due_dates; - for (int j = 0; j < FLAGS_size; ++j) due_dates.push_back(numbers[index++]); + for (int j = 0; j < absl::GetFlag(FLAGS_size); ++j) + due_dates.push_back(numbers[index++]); Solve(durations, due_dates, weights); } -} // namespace sat -} // namespace operations_research +} // namespace sat +} // namespace operations_research -int main(int argc, char** argv) { - absl::SetFlag(&FLAGS_logtostderr, true); +int main(int argc, char **argv) { + absl::SetFlag(&absl::GetFlag(FLAGS_logtostderr), true); gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_input.empty()) { + if (absl::GetFlag(FLAGS_input).empty()) { LOG(FATAL) << "Please supply a data file with --input="; } operations_research::sat::ParseAndSolve(); diff --git a/examples/tests/lp_test.cc b/examples/tests/lp_test.cc index a59995a6fe..f69dc6679d 100644 --- a/examples/tests/lp_test.cc +++ b/examples/tests/lp_test.cc @@ -184,7 +184,7 @@ void RunAllExamples() { int main(int argc, char** argv) { google::InitGoogleLogging(argv[0]); - FLAGS_logtostderr = 1; + absl::GetFlag(FLAGS_logtostderr) = 1; operations_research::RunAllExamples(); return 0; } diff --git a/examples/tests/remote/tsp.cc b/examples/tests/remote/tsp.cc index e1748cb40f..41f9b6cdbc 100644 --- a/examples/tests/remote/tsp.cc +++ b/examples/tests/remote/tsp.cc @@ -49,7 +49,7 @@ DECLARE_bool(routing_no_lns); // Random seed generator. int32 GetSeed() { - if (FLAGS_tsp_use_deterministic_random_seed) { + if (absl::GetFlag(FLAGS_tsp_use_deterministic_random_seed)) { return ACMRandom::DeterministicSeed(); } else { return ACMRandom::HostnamePidTimeSeed(); @@ -100,23 +100,23 @@ class RandomMatrix { int main(int argc, char** argv) { google::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_tsp_size > 0) { - // TSP of size FLAGS_tsp_size. + if (absl::GetFlag(FLAGS_tsp_size) > 0) { + // TSP of size absl::GetFlag(FLAGS_tsp_size). // Second argument = 1 to build a single tour (it's a TSP). - // Nodes are indexed from 0 to FLAGS_tsp_size - 1, by default the start of + // Nodes are indexed from 0 to absl::GetFlag(FLAGS_tsp_size) - 1, by default the start of // the route is node 0. - RoutingModel routing(FLAGS_tsp_size, 1); + RoutingModel routing(absl::GetFlag(FLAGS_tsp_size), 1); // Setting first solution heuristic (cheapest addition). - FLAGS_routing_first_solution = "PathCheapestArc"; + absl::GetFlag(FLAGS_routing_first_solution) = "PathCheapestArc"; // Disabling Large Neighborhood Search, comment out to activate it. - FLAGS_routing_no_lns = true; + absl::GetFlag(FLAGS_routing_no_lns) = true; // Setting the cost function. // Put a permanent callback to the distance accessor here. The callback // has the following signature: ResultCallback2. // The two arguments are the from and to node inidices. - RandomMatrix matrix(FLAGS_tsp_size); - if (FLAGS_tsp_use_random_matrix) { + RandomMatrix matrix(absl::GetFlag(FLAGS_tsp_size)); + if (absl::GetFlag(FLAGS_tsp_use_random_matrix)) { matrix.Initialize(); routing.SetArcCostEvaluatorOfAllVehicles( NewPermanentCallback(&matrix, &RandomMatrix::Distance)); @@ -127,9 +127,9 @@ int main(int argc, char** argv) { // Forbid node connections (randomly). ACMRandom randomizer(GetSeed()); int64 forbidden_connections = 0; - while (forbidden_connections < FLAGS_tsp_random_forbidden_connections) { - const int64 from = randomizer.Uniform(FLAGS_tsp_size - 1); - const int64 to = randomizer.Uniform(FLAGS_tsp_size - 1) + 1; + while (forbidden_connections < absl::GetFlag(FLAGS_tsp_random_forbidden_connections)) { + const int64 from = randomizer.Uniform(absl::GetFlag(FLAGS_tsp_size) - 1); + const int64 to = randomizer.Uniform(absl::GetFlag(FLAGS_tsp_size) - 1) + 1; if (routing.NextVar(from)->Contains(to)) { LOG(INFO) << "Forbidding connection " << from << " -> " << to; routing.NextVar(from)->RemoveValue(to); diff --git a/ortools/algorithms/dense_doubly_linked_list.h b/ortools/algorithms/dense_doubly_linked_list.h index c318e1507a..67debd4a4e 100644 --- a/ortools/algorithms/dense_doubly_linked_list.h +++ b/ortools/algorithms/dense_doubly_linked_list.h @@ -27,12 +27,11 @@ namespace operations_research { // // It is very fast and compact: it uses exactly 8*n bytes of memory. class DenseDoublyLinkedList { - public: +public: // You can construct a DenseDoublyLinkedList with any range-iterable class // that also has a size() method. The order of the elements is given by the // user and will never change (modulo the removal of elements). - template - explicit DenseDoublyLinkedList(const T& sorted_elements); + template explicit DenseDoublyLinkedList(const T &sorted_elements); int Size() const { return next_.size(); } @@ -44,7 +43,7 @@ class DenseDoublyLinkedList { // You must not call Remove() twice with the same element. void Remove(int i); - private: +private: std::vector next_; std::vector prev_; }; @@ -68,13 +67,16 @@ inline int DenseDoublyLinkedList::Prev(int i) const { inline void DenseDoublyLinkedList::Remove(int i) { const int prev = Prev(i); const int next = Next(i); - if (prev >= 0) next_[prev] = next; - if (next >= 0) prev_[next] = prev; - if (DEBUG_MODE) next_[i] = prev_[i] = -2; // To catch bugs. + if (prev >= 0) + next_[prev] = next; + if (next >= 0) + prev_[next] = prev; + if (DEBUG_MODE) + next_[i] = prev_[i] = -2; // To catch bugs. } template -DenseDoublyLinkedList::DenseDoublyLinkedList(const T& elements) +DenseDoublyLinkedList::DenseDoublyLinkedList(const T &elements) : next_(elements.size(), -2), prev_(elements.size(), -2) { int last = -1; for (const int e : elements) { @@ -82,16 +84,20 @@ DenseDoublyLinkedList::DenseDoublyLinkedList(const T& elements) DCHECK_LE(e, Size()); DCHECK_EQ(-2, prev_[e]) << "Duplicate element: " << e; prev_[e] = last; - if (last >= 0) next_[last] = e; + if (last >= 0) + next_[last] = e; last = e; } - if (!elements.empty()) next_[elements.back()] = -1; + if (!elements.empty()) + next_[elements.back()] = -1; if (DEBUG_MODE) { - for (int p : prev_) DCHECK_NE(-2, p); - for (int n : next_) DCHECK_NE(-2, n); + for (int p : prev_) + DCHECK_NE(-2, p); + for (int n : next_) + DCHECK_NE(-2, n); } } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_DENSE_DOUBLY_LINKED_LIST_H_ +#endif // OR_TOOLS_ALGORITHMS_DENSE_DOUBLY_LINKED_LIST_H_ diff --git a/ortools/algorithms/dynamic_partition.cc b/ortools/algorithms/dynamic_partition.cc index 2886ca8b54..36817579fd 100644 --- a/ortools/algorithms/dynamic_partition.cc +++ b/ortools/algorithms/dynamic_partition.cc @@ -23,10 +23,10 @@ namespace operations_research { namespace { uint64 FprintOfInt32(int i) { - return util_hash::MurmurHash64(reinterpret_cast(&i), + return util_hash::MurmurHash64(reinterpret_cast(&i), sizeof(int)); } -} // namespace +} // namespace DynamicPartition::DynamicPartition(int num_elements) { DCHECK_GE(num_elements, 0); @@ -38,15 +38,16 @@ DynamicPartition::DynamicPartition(int num_elements) { } part_of_.assign(num_elements, 0); uint64 fprint = 0; - for (int i = 0; i < num_elements; ++i) fprint ^= FprintOfInt32(i); - part_.push_back(Part(/*start_index=*/0, /*end_index=*/num_elements, - /*parent_part=*/0, - /*fprint=*/fprint)); + for (int i = 0; i < num_elements; ++i) + fprint ^= FprintOfInt32(i); + part_.push_back(Part(/*start_index=*/ 0, /*end_index=*/ num_elements, + /*parent_part=*/ 0, /*fprint=*/ fprint)); } DynamicPartition::DynamicPartition( - const std::vector& initial_part_of_element) { - if (initial_part_of_element.empty()) return; + const std::vector &initial_part_of_element) { + if (initial_part_of_element.empty()) + return; part_of_ = initial_part_of_element; const int n = part_of_.size(); const int num_parts = 1 + *std::max_element(part_of_.begin(), part_of_.end()); @@ -54,30 +55,33 @@ DynamicPartition::DynamicPartition( part_.resize(num_parts); // Compute the part fingerprints. - for (int i = 0; i < n; ++i) part_[part_of_[i]].fprint ^= FprintOfInt32(i); + for (int i = 0; i < n; ++i) + part_[part_of_[i]].fprint ^= FprintOfInt32(i); // Compute the actual start indices of each part, knowing that we'll sort // them as they were given implicitly in "initial_part_of_element". // The code looks a bit weird to do it in-place, with no additional memory. for (int p = 0; p < num_parts; ++p) { - part_[p].end_index = 0; // Temporarily utilized as size_of_part. + part_[p].end_index = 0; // Temporarily utilized as size_of_part. part_[p].parent_part = p; } - for (const int p : part_of_) ++part_[p].end_index; // size_of_part + for (const int p : part_of_) + ++part_[p].end_index; // size_of_part int sum_part_sizes = 0; for (int p = 0; p < num_parts; ++p) { part_[p].start_index = sum_part_sizes; - sum_part_sizes += part_[p].end_index; // size of part. + sum_part_sizes += part_[p].end_index; // size of part. } // Now that we have the correct start indices, we set the end indices to the // start indices, and incrementally add all elements to their part, adjusting // the end indices as we go. - for (Part& part : part_) part.end_index = part.start_index; + for (Part &part : part_) + part.end_index = part.start_index; element_.assign(n, -1); index_of_.assign(n, -1); for (int element = 0; element < n; ++element) { - Part* const part = &part_[part_of_[element]]; + Part *const part = &part_[part_of_[element]]; element_[part->end_index] = element; index_of_[element] = part->end_index; ++part->end_index; @@ -93,7 +97,7 @@ DynamicPartition::DynamicPartition( } } -void DynamicPartition::Refine(const std::vector& distinguished_subset) { +void DynamicPartition::Refine(const std::vector &distinguished_subset) { // tmp_counter_of_part_[i] will contain the number of // elements in distinguished_subset that were part of part #i. tmp_counter_of_part_.resize(NumParts(), 0); @@ -132,12 +136,13 @@ void DynamicPartition::Refine(const std::vector& distinguished_subset) { const int start_index = part_[part].start_index; const int end_index = part_[part].end_index; const int split_index = end_index - tmp_counter_of_part_[part]; - tmp_counter_of_part_[part] = 0; // Clean up after us. + tmp_counter_of_part_[part] = 0; // Clean up after us. DCHECK_GE(split_index, start_index); DCHECK_LT(split_index, end_index); // Do nothing if all elements were distinguished. - if (split_index == start_index) continue; + if (split_index == start_index) + continue; // Compute the fingerprint of the new part. uint64 new_fprint = 0; @@ -163,7 +168,7 @@ void DynamicPartition::UndoRefineUntilNumPartsEqual(int original_num_parts) { DCHECK_GE(original_num_parts, 1); while (NumParts() > original_num_parts) { const int part_index = NumParts() - 1; - const Part& part = part_[part_index]; + const Part &part = part_[part_index]; const int parent_part_index = part.parent_part; DCHECK_LT(parent_part_index, part_index) << "UndoRefineUntilNumPartsEqual()" " called with " @@ -173,7 +178,7 @@ void DynamicPartition::UndoRefineUntilNumPartsEqual(int original_num_parts) { for (const int element : ElementsInPart(part_index)) { part_of_[element] = parent_part_index; } - Part* const parent_part = &part_[parent_part_index]; + Part *const parent_part = &part_[parent_part_index]; DCHECK_EQ(part.start_index, parent_part->end_index); parent_part->end_index = part.end_index; parent_part->fprint ^= part.fprint; @@ -185,7 +190,7 @@ std::string DynamicPartition::DebugString(DebugStringSorting sorting) const { if (sorting != SORT_LEXICOGRAPHICALLY && sorting != SORT_BY_PART) { return absl::StrFormat("Unsupported sorting: %d", sorting); } - std::vector> parts; + std::vector > parts; for (int i = 0; i < NumParts(); ++i) { IterablePart iterable_part = ElementsInPart(i); parts.emplace_back(iterable_part.begin(), iterable_part.end()); @@ -195,8 +200,9 @@ std::string DynamicPartition::DebugString(DebugStringSorting sorting) const { std::sort(parts.begin(), parts.end()); } std::string out; - for (const std::vector& part : parts) { - if (!out.empty()) out += " | "; + for (const std::vector &part : parts) { + if (!out.empty()) + out += " | "; out += absl::StrJoin(part, " "); } return out; @@ -206,7 +212,8 @@ void MergingPartition::Reset(int num_nodes) { DCHECK_GE(num_nodes, 0); part_size_.assign(num_nodes, 1); parent_.assign(num_nodes, -1); - for (int i = 0; i < num_nodes; ++i) parent_[i] = i; + for (int i = 0; i < num_nodes; ++i) + parent_[i] = i; tmp_part_bit_.assign(num_nodes, false); } @@ -217,7 +224,8 @@ int MergingPartition::MergePartsOf(int node1, int node2) { DCHECK_LT(node2, NumNodes()); int root1 = GetRoot(node1); int root2 = GetRoot(node2); - if (root1 == root2) return -1; + if (root1 == root2) + return -1; int s1 = part_size_[root1]; int s2 = part_size_[root2]; // Attach the smaller part to the larger one. Break ties by root index. @@ -242,7 +250,7 @@ int MergingPartition::GetRootAndCompressPath(int node) { return root; } -void MergingPartition::KeepOnlyOneNodePerPart(std::vector* nodes) { +void MergingPartition::KeepOnlyOneNodePerPart(std::vector *nodes) { int num_nodes_kept = 0; for (const int node : *nodes) { const int representative = GetRootAndCompressPath(node); @@ -255,11 +263,12 @@ void MergingPartition::KeepOnlyOneNodePerPart(std::vector* nodes) { // Clean up the tmp_part_bit_ vector. Since we've already compressed the // paths (if backtracking was enabled), no need to do it again. - for (const int node : *nodes) tmp_part_bit_[GetRoot(node)] = false; + for (const int node : *nodes) + tmp_part_bit_[GetRoot(node)] = false; } int MergingPartition::FillEquivalenceClasses( - std::vector* node_equivalence_classes) { + std::vector *node_equivalence_classes) { node_equivalence_classes->assign(NumNodes(), -1); int num_roots = 0; for (int node = 0; node < NumNodes(); ++node) { @@ -274,21 +283,22 @@ int MergingPartition::FillEquivalenceClasses( } std::string MergingPartition::DebugString() { - std::vector> sorted_parts(NumNodes()); + std::vector > sorted_parts(NumNodes()); for (int i = 0; i < NumNodes(); ++i) { sorted_parts[GetRootAndCompressPath(i)].push_back(i); } - for (std::vector& part : sorted_parts) + for (std::vector &part : sorted_parts) std::sort(part.begin(), part.end()); std::sort(sorted_parts.begin(), sorted_parts.end()); // Note: typically, a lot of elements of "sorted_parts" will be empty, // but these won't be visible in the string that we construct below. std::string out; - for (const std::vector& part : sorted_parts) { - if (!out.empty()) out += " | "; + for (const std::vector &part : sorted_parts) { + if (!out.empty()) + out += " | "; out += absl::StrJoin(part, " "); } return out; } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/dynamic_partition.h b/ortools/algorithms/dynamic_partition.h index 8b9c6d89ad..2121efd063 100644 --- a/ortools/algorithms/dynamic_partition.h +++ b/ortools/algorithms/dynamic_partition.h @@ -47,14 +47,14 @@ namespace operations_research { // // TODO(user): rename this to BacktrackableSplittingPartition. class DynamicPartition { - public: +public: // Creates a DynamicPartition on n elements, numbered 0..n-1. Start with // the trivial partition (only one subset containing all elements). explicit DynamicPartition(int num_elements); // Ditto, but specify the initial part of each elements. Part indices must // form a dense integer set starting at 0; eg. [2, 1, 0, 1, 1, 3, 0] is valid. - explicit DynamicPartition(const std::vector& initial_part_of_element); + explicit DynamicPartition(const std::vector &initial_part_of_element); // Accessors. int NumElements() const { return element_.size(); } @@ -105,7 +105,7 @@ class DynamicPartition { // keeping track of one additional bit of information for each part that // remains unchanged by a Refine() operation: was that part entirely *in* // the distinguished subset or entirely *out*? - void Refine(const std::vector& distinguished_subset); + void Refine(const std::vector &distinguished_subset); // Undo one or several Refine() operations, until the number of parts // becomes equal to "original_num_parts". @@ -133,11 +133,11 @@ class DynamicPartition { // Note that the order does get changed by Refine() operations. // This is a reference, so it'll only remain valid and constant until the // class is destroyed or until Refine() get called. - const std::vector& ElementsInHierarchicalOrder() const { + const std::vector &ElementsInHierarchicalOrder() const { return element_; } - private: +private: // A DynamicPartition instance maintains a list of all of its elements, // 'sorted' by partitions: elements of the same subset are contiguous // in that list. @@ -152,13 +152,13 @@ class DynamicPartition { struct Part { // This part holds elements[start_index .. end_index-1]. // INVARIANT: end_index > start_index. - int start_index; // Inclusive - int end_index; // Exclusive + int start_index; // Inclusive + int end_index; // Exclusive // The Part that this part was split out of. See the comment at Refine(). // INVARIANT: part[i].parent_part <= i, and the equality holds iff part[i] // has no parent. - int parent_part; // Index into the part[] array. + int parent_part; // Index into the part[] array. // The part's fingerprint is the XOR of all fingerprints of its elements. // See FprintOfInt32() in the .cc. @@ -166,12 +166,10 @@ class DynamicPartition { Part() : start_index(0), end_index(0), parent_part(0), fprint(0) {} Part(int start_index, int end_index, int parent_part, uint64 fprint) - : start_index(start_index), - end_index(end_index), - parent_part(parent_part), - fprint(fprint) {} + : start_index(start_index), end_index(end_index), + parent_part(parent_part), fprint(fprint) {} }; - std::vector part_; // The disjoint parts. + std::vector part_; // The disjoint parts. // Used temporarily and exclusively by Refine(). This prevents Refine() // from being thread-safe. @@ -189,8 +187,8 @@ struct DynamicPartition::IterablePart { int size() const { return end_ - begin_; } IterablePart() {} - IterablePart(const std::vector::const_iterator& b, - const std::vector::const_iterator& e) + IterablePart(const std::vector::const_iterator &b, + const std::vector::const_iterator &e) : begin_(b), end_(e) {} // These typedefs allow this iterator to be used within testing::ElementsAre. @@ -201,7 +199,7 @@ struct DynamicPartition::IterablePart { // Partition class that supports incremental merging, using the union-find // algorithm (see http://en.wikipedia.org/wiki/Disjoint-set_data_structure). class MergingPartition { - public: +public: // At first, all nodes are in their own singleton part. MergingPartition() { Reset(0); } explicit MergingPartition(int num_nodes) { Reset(num_nodes); } @@ -218,7 +216,7 @@ class MergingPartition { // // Details: a smaller part will always be merged onto a larger one. // Upons ties, the smaller representative becomes the overall representative. - int MergePartsOf(int node1, int node2); // The 'union' of the union-find. + int MergePartsOf(int node1, int node2); // The 'union' of the union-find. // Get the representative of "node" (a node in the same equivalence class, // which will also be returned for any other "node" in the same class). @@ -227,7 +225,7 @@ class MergingPartition { // Specialized reader API: prunes "nodes" to only keep at most one node per // part: any node which is in the same part as an earlier node will be pruned. - void KeepOnlyOneNodePerPart(std::vector* nodes); + void KeepOnlyOneNodePerPart(std::vector *nodes); // Output the whole partition as node equivalence classes: if there are K // parts and N nodes, node_equivalence_classes[i] will contain the part index @@ -235,7 +233,7 @@ class MergingPartition { // (i.e. node 0 will always be in part 0; then the next node that isn't in // part 0 will be in part 1, and so on). // Returns the number K of classes. - int FillEquivalenceClasses(std::vector* node_equivalence_classes); + int FillEquivalenceClasses(std::vector *node_equivalence_classes); // Dump all components, with nodes sorted within each part and parts // sorted lexicographically. Eg. "0 1 3 4 | 2 5 | 6 7 8". @@ -259,7 +257,7 @@ class MergingPartition { // version using path compression. int GetRoot(int node) const; - private: +private: // Along the upwards path from 'node' to its root, set the parent of all // nodes (including the root) to 'parent'. void SetParentAlongPathToRoot(int node, int parent); @@ -273,8 +271,8 @@ class MergingPartition { // *** Implementation of inline methods of the above classes. *** -inline DynamicPartition::IterablePart DynamicPartition::ElementsInPart( - int i) const { +inline DynamicPartition::IterablePart +DynamicPartition::ElementsInPart(int i) const { DCHECK_GE(i, 0); DCHECK_LT(i, NumParts()); return IterablePart(element_.begin() + part_[i].start_index, @@ -290,7 +288,7 @@ inline int DynamicPartition::PartOf(int element) const { inline int DynamicPartition::SizeOfPart(int part) const { DCHECK_GE(part, 0); DCHECK_LT(part, part_.size()); - const Part& p = part_[part]; + const Part &p = part_[part]; return p.end_index - p.start_index; } @@ -300,8 +298,8 @@ inline int DynamicPartition::ParentOfPart(int part) const { return part_[part].parent_part; } -inline DynamicPartition::IterablePart DynamicPartition::ElementsInSamePartAs( - int i) const { +inline DynamicPartition::IterablePart +DynamicPartition::ElementsInSamePartAs(int i) const { return ElementsInPart(PartOf(i)); } @@ -317,7 +315,8 @@ inline int MergingPartition::GetRoot(int node) const { int child = node; while (true) { const int parent = parent_[child]; - if (parent == child) return child; + if (parent == child) + return child; child = parent; } } @@ -331,7 +330,8 @@ inline void MergingPartition::SetParentAlongPathToRoot(int node, int parent) { while (true) { const int old_parent = parent_[child]; parent_[child] = parent; - if (old_parent == child) return; + if (old_parent == child) + return; child = old_parent; } } @@ -343,6 +343,6 @@ inline void MergingPartition::ResetNode(int node) { part_size_[node] = 1; } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_DYNAMIC_PARTITION_H_ +#endif // OR_TOOLS_ALGORITHMS_DYNAMIC_PARTITION_H_ diff --git a/ortools/algorithms/dynamic_permutation.cc b/ortools/algorithms/dynamic_permutation.cc index afcceb525a..9db20469a2 100644 --- a/ortools/algorithms/dynamic_permutation.cc +++ b/ortools/algorithms/dynamic_permutation.cc @@ -21,36 +21,39 @@ namespace operations_research { DynamicPermutation::DynamicPermutation(int n) : image_(n, -1), ancestor_(n, -1), tmp_mask_(n, false) { - for (int i = 0; i < Size(); ++i) image_[i] = ancestor_[i] = i; + for (int i = 0; i < Size(); ++i) + image_[i] = ancestor_[i] = i; } -void DynamicPermutation::AddMappings(const std::vector& src, - const std::vector& dst) { +void DynamicPermutation::AddMappings(const std::vector &src, + const std::vector &dst) { DCHECK_EQ(src.size(), dst.size()); mapping_src_size_stack_.push_back(mapping_src_stack_.size()); mapping_src_stack_.reserve(mapping_src_stack_.size() + src.size()); for (int i = 0; i < src.size(); ++i) { const int s = src[i]; const int d = dst[i]; - DCHECK_EQ(s, ImageOf(s)); // No prior image of s. - DCHECK_EQ(d, ancestor_[d]); // No prior ancestor of d. + DCHECK_EQ(s, ImageOf(s)); // No prior image of s. + DCHECK_EQ(d, ancestor_[d]); // No prior ancestor of d. ancestor_[d] = RootOf(s); image_[s] = d; - if (image_[d] == d) loose_ends_.insert(d); - loose_ends_.erase(s); // Also takes care of the corner case s == d. + if (image_[d] == d) + loose_ends_.insert(d); + loose_ends_.erase(s); // Also takes care of the corner case s == d. // Remember the sources for the undo stack. mapping_src_stack_.push_back(s); } } -void DynamicPermutation::UndoLastMappings( - std::vector* undone_mapping_src) { +void +DynamicPermutation::UndoLastMappings(std::vector *undone_mapping_src) { DCHECK(undone_mapping_src != nullptr); undone_mapping_src->clear(); - if (mapping_src_size_stack_.empty()) return; // Nothing to undo. + if (mapping_src_size_stack_.empty()) + return; // Nothing to undo. const int num_mappings_before = mapping_src_size_stack_.back(); mapping_src_size_stack_.pop_back(); const int num_mappings_now = mapping_src_stack_.size(); @@ -66,13 +69,14 @@ void DynamicPermutation::UndoLastMappings( const int s = mapping_src_stack_[i]; const int d = ImageOf(s); - if (ancestor_[s] != s) loose_ends_.insert(s); + if (ancestor_[s] != s) + loose_ends_.insert(s); loose_ends_.erase(d); ancestor_[d] = d; image_[s] = s; } - mapping_src_stack_.resize(num_mappings_before); // Shrink. + mapping_src_stack_.resize(num_mappings_before); // Shrink. } void DynamicPermutation::Reset() { @@ -86,12 +90,13 @@ void DynamicPermutation::Reset() { loose_ends_.clear(); } -std::unique_ptr DynamicPermutation::CreateSparsePermutation() - const { +std::unique_ptr +DynamicPermutation::CreateSparsePermutation() const { std::unique_ptr sparse_perm(new SparsePermutation(Size())); int num_identity_singletons = 0; for (const int x : mapping_src_stack_) { - if (tmp_mask_[x]) continue; + if (tmp_mask_[x]) + continue; // Deal with the special case of a trivial x->x cycle, which we do *not* // want to add to the sparse permutation. if (ImageOf(x) == x) { @@ -106,11 +111,13 @@ std::unique_ptr DynamicPermutation::CreateSparsePermutation() tmp_mask_[next] = true; DCHECK_NE(next, ImageOf(next)); next = ImageOf(next); - if (next == root) break; + if (next == root) + break; } sparse_perm->CloseCurrentCycle(); } - for (const int x : mapping_src_stack_) tmp_mask_[x] = false; + for (const int x : mapping_src_stack_) + tmp_mask_[x] = false; DCHECK_EQ(mapping_src_stack_.size(), sparse_perm->Support().size() + num_identity_singletons); return sparse_perm; @@ -121,4 +128,4 @@ std::string DynamicPermutation::DebugString() const { return CreateSparsePermutation()->DebugString(); } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/dynamic_permutation.h b/ortools/algorithms/dynamic_permutation.h index f5202ce398..1c218ac2e8 100644 --- a/ortools/algorithms/dynamic_permutation.h +++ b/ortools/algorithms/dynamic_permutation.h @@ -15,7 +15,7 @@ #define OR_TOOLS_ALGORITHMS_DYNAMIC_PERMUTATION_H_ #include -#include // TODO(user): remove when no longer used. +#include // TODO(user): remove when no longer used. #include #include "ortools/base/logging.h" @@ -31,11 +31,13 @@ class SparsePermutation; // RAM usage: as of 2014-04, this class needs less than: // 32.125 * (n + 2 * support_size) bytes. class DynamicPermutation { - public: +public: // Upon construction, every element i in [0..n-1] maps to itself. explicit DynamicPermutation(int n); - int Size() const { return image_.size(); } // Return the original "n". + int Size() const { + return image_.size(); + } // Return the original "n". // Declares a set of mappings for this permutation: src[i] will map to dst[i]. // Requirements that are DCHECKed: @@ -44,7 +46,7 @@ class DynamicPermutation { // - For all i, dst[i] must not already be the image of something. // // Complexity: amortized O(src.size()). - void AddMappings(const std::vector& src, const std::vector& dst); + void AddMappings(const std::vector &src, const std::vector &dst); // Undoes the last AddMappings() operation, and fills the "undone_mapping_src" // vector with the src of that last operation. This works like an undo stack. @@ -54,17 +56,17 @@ class DynamicPermutation { // simply a no-op. // // Complexity: same as the AddMappings() operation being undone. - void UndoLastMappings(std::vector* undone_mapping_src); + void UndoLastMappings(std::vector *undone_mapping_src); // Makes the permutation back to the identity (i.e. like right after // construction). // Complexity: O(support size). void Reset(); - int ImageOf(int i) const; // Complexity: one vector lookup. + int ImageOf(int i) const; // Complexity: one vector lookup. // Returns the union of all "src" ever given to AddMappings(). - const std::vector& AllMappingsSrc() const { return mapping_src_stack_; } + const std::vector &AllMappingsSrc() const { return mapping_src_stack_; } // While the permutation is partially being built, the orbit of elements will // either form unclosed paths, or closed cycles. In the former case, @@ -80,7 +82,7 @@ class DynamicPermutation { // (e.g., paths) built so far. // TODO(user): use a faster underlying container like SparseBitSet, and // tweak this API accordingly. - const std::set& LooseEnds() const { return loose_ends_; } + const std::set &LooseEnds() const { return loose_ends_; } // Creates a SparsePermutation representing the current permutation. // Requirements: the permutation must only have cycles. @@ -90,7 +92,7 @@ class DynamicPermutation { std::string DebugString() const; - private: +private: std::vector image_; // ancestor_[i] isn't exactly RootOf(i): it might itself have an ancestor, and // so on. @@ -123,11 +125,12 @@ inline int DynamicPermutation::RootOf(int i) const { DCHECK_LT(i, Size()); while (true) { const int j = ancestor_[i]; - if (j == i) return i; + if (j == i) + return i; i = j; } } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_DYNAMIC_PERMUTATION_H_ +#endif // OR_TOOLS_ALGORITHMS_DYNAMIC_PERMUTATION_H_ diff --git a/ortools/algorithms/find_graph_symmetries.cc b/ortools/algorithms/find_graph_symmetries.cc index dd9d6ddc76..c45b4707f2 100644 --- a/ortools/algorithms/find_graph_symmetries.cc +++ b/ortools/algorithms/find_graph_symmetries.cc @@ -43,16 +43,17 @@ using util::GraphIsSymmetric; namespace { // Some routines used below. -void SwapFrontAndBack(std::vector* v) { +void SwapFrontAndBack(std::vector *v) { DCHECK(!v->empty()); std::swap((*v)[0], v->back()); } -bool PartitionsAreCompatibleAfterPartIndex(const DynamicPartition& p1, - const DynamicPartition& p2, +bool PartitionsAreCompatibleAfterPartIndex(const DynamicPartition &p1, + const DynamicPartition &p2, int part_index) { const int num_parts = p1.NumParts(); - if (p2.NumParts() != num_parts) return false; + if (p2.NumParts() != num_parts) + return false; for (int p = part_index; p < num_parts; ++p) { if (p1.SizeOfPart(p) != p2.SizeOfPart(p) || p1.ParentOfPart(p) != p2.ParentOfPart(p)) { @@ -71,9 +72,9 @@ bool PartitionsAreCompatibleAfterPartIndex(const DynamicPartition& p1, // be repeated in the list), and see if that's sufficient to make the whole // graph symmetry finder support multi-arcs. template -bool ListMapsToList(const List& l1, const List& l2, - const DynamicPermutation& permutation, - std::vector* tmp_node_mask) { +bool ListMapsToList(const List &l1, const List &l2, + const DynamicPermutation &permutation, + std::vector *tmp_node_mask) { int num_elements_delta = 0; bool match = true; for (const int mapped_x : l2) { @@ -89,20 +90,20 @@ bool ListMapsToList(const List& l1, const List& l2, } (*tmp_node_mask)[mapped_x] = false; } - if (num_elements_delta != 0) match = false; + if (num_elements_delta != 0) + match = false; if (!match) { // We need to clean up tmp_node_mask. - for (const int x : l2) (*tmp_node_mask)[x] = false; + for (const int x : l2) + (*tmp_node_mask)[x] = false; } return match; } -} // namespace +} // namespace -GraphSymmetryFinder::GraphSymmetryFinder(const Graph& graph, bool is_undirected) - : graph_(graph), - tmp_dynamic_permutation_(NumNodes()), - tmp_node_mask_(NumNodes(), false), - tmp_degree_(NumNodes(), 0), +GraphSymmetryFinder::GraphSymmetryFinder(const Graph &graph, bool is_undirected) + : graph_(graph), tmp_dynamic_permutation_(NumNodes()), + tmp_node_mask_(NumNodes(), false), tmp_degree_(NumNodes(), 0), tmp_nodes_with_degree_(NumNodes() + 1) { // Set up an "unlimited" time limit by default. time_limit_ = TimeLimit::Infinite(); @@ -131,25 +132,26 @@ GraphSymmetryFinder::GraphSymmetryFinder(const Graph& graph, bool is_undirected) flattened_reverse_adj_lists_.assign(graph.num_arcs(), -1); for (const int node : graph.AllNodes()) { for (const int arc : graph.OutgoingArcs(node)) { - flattened_reverse_adj_lists_[reverse_adj_list_index_[graph.Head(arc) + - /*shift*/ 1]++] = - node; + flattened_reverse_adj_lists_[ + reverse_adj_list_index_[graph.Head(arc) + /*shift*/ 1]++] = node; } } // The last pass shifted reverse_adj_list_index, so it's now as we want it: // [0, in_degree(node0), in_degree(node0) + in_degree(node1), ...] if (DEBUG_MODE) { DCHECK_EQ(graph.num_arcs(), reverse_adj_list_index_[graph.num_nodes()]); - for (const int i : flattened_reverse_adj_lists_) DCHECK_NE(i, -1); + for (const int i : flattened_reverse_adj_lists_) + DCHECK_NE(i, -1); } } } bool GraphSymmetryFinder::IsGraphAutomorphism( - const DynamicPermutation& permutation) const { + const DynamicPermutation &permutation) const { for (const int base : permutation.AllMappingsSrc()) { const int image = permutation.ImageOf(base); - if (image == base) continue; + if (image == base) + continue; if (!ListMapsToList(graph_[base], graph_[image], permutation, &tmp_node_mask_)) { return false; @@ -160,7 +162,8 @@ bool GraphSymmetryFinder::IsGraphAutomorphism( // to displaced nodes. for (const int base : permutation.AllMappingsSrc()) { const int image = permutation.ImageOf(base); - if (image == base) continue; + if (image == base) + continue; if (!ListMapsToList(TailsOfIncomingArcsTo(base), TailsOfIncomingArcsTo(image), permutation, &tmp_node_mask_)) { @@ -175,22 +178,24 @@ namespace { // Specialized subroutine, to avoid code duplication: see its call site // and its self-explanatory code. template -inline void IncrementCounterForNonSingletons(const T& nodes, - const DynamicPartition& partition, - std::vector* node_count, - std::vector* nodes_seen) { +inline void IncrementCounterForNonSingletons(const T &nodes, + const DynamicPartition &partition, + std::vector *node_count, + std::vector *nodes_seen) { for (const int node : nodes) { - if (partition.ElementsInSamePartAs(node).size() == 1) continue; + if (partition.ElementsInSamePartAs(node).size() == 1) + continue; const int count = ++(*node_count)[node]; - if (count == 1) nodes_seen->push_back(node); + if (count == 1) + nodes_seen->push_back(node); } } -} // namespace +} // namespace void GraphSymmetryFinder::RecursivelyRefinePartitionByAdjacency( - int first_unrefined_part_index, DynamicPartition* partition) { + int first_unrefined_part_index, DynamicPartition *partition) { // Rename, for readability of the code below. - std::vector& tmp_nodes_with_nonzero_degree = tmp_stack_; + std::vector &tmp_nodes_with_nonzero_degree = tmp_stack_; // Assuming that the partition was refined based on the adjacency on // parts [0 .. first_unrefined_part_index) already, we simply need to @@ -205,10 +210,10 @@ void GraphSymmetryFinder::RecursivelyRefinePartitionByAdjacency( // advertised. std::vector adjacency_directions(1, /*outgoing*/ true); if (!reverse_adj_list_index_.empty()) { - adjacency_directions.push_back(false); // Also look at incoming arcs. + adjacency_directions.push_back(false); // Also look at incoming arcs. } for (int part_index = first_unrefined_part_index; - part_index < partition->NumParts(); // Moving target! + part_index < partition->NumParts(); // Moving target! ++part_index) { for (const bool outgoing_adjacency : adjacency_directions) { // Count the aggregated degree of all nodes, only looking at arcs that @@ -230,23 +235,23 @@ void GraphSymmetryFinder::RecursivelyRefinePartitionByAdjacency( int max_degree = 0; for (const int node : tmp_nodes_with_nonzero_degree) { const int degree = tmp_degree_[node]; - tmp_degree_[node] = 0; // To clean up after us. + tmp_degree_[node] = 0; // To clean up after us. max_degree = std::max(max_degree, degree); tmp_nodes_with_degree_[degree].push_back(node); } - tmp_nodes_with_nonzero_degree.clear(); // To clean up after us. + tmp_nodes_with_nonzero_degree.clear(); // To clean up after us. // For each degree, refine the partition by the set of nodes with that // degree. for (int degree = 1; degree <= max_degree; ++degree) { partition->Refine(tmp_nodes_with_degree_[degree]); - tmp_nodes_with_degree_[degree].clear(); // To clean up after us. + tmp_nodes_with_degree_[degree].clear(); // To clean up after us. } } } } void GraphSymmetryFinder::DistinguishNodeInPartition( - int node, DynamicPartition* partition, std::vector* new_singletons) { + int node, DynamicPartition *partition, std::vector *new_singletons) { const int original_num_parts = partition->NumParts(); partition->Refine(std::vector(1, node)); RecursivelyRefinePartitionByAdjacency(partition->PartOf(node), partition); @@ -276,8 +281,8 @@ void GraphSymmetryFinder::DistinguishNodeInPartition( namespace { void MergeNodeEquivalenceClassesAccordingToPermutation( - const SparsePermutation& perm, MergingPartition* node_equivalence_classes, - DenseDoublyLinkedList* sorted_representatives) { + const SparsePermutation &perm, MergingPartition *node_equivalence_classes, + DenseDoublyLinkedList *sorted_representatives) { for (int c = 0; c < perm.NumCycles(); ++c) { // TODO(user): use the global element->image iterator when it exists. int prev = -1; @@ -307,10 +312,10 @@ void MergeNodeEquivalenceClassesAccordingToPermutation( // representatives of the nodes of the targeted part are contiguous in that // linked list. void GetAllOtherRepresentativesInSamePartAs( - int representative_node, const DynamicPartition& partition, - const DenseDoublyLinkedList& representatives_sorted_by_index_in_partition, - MergingPartition* node_equivalence_classes, // Only for debugging. - std::vector* pruned_other_nodes) { + int representative_node, const DynamicPartition &partition, + const DenseDoublyLinkedList &representatives_sorted_by_index_in_partition, + MergingPartition *node_equivalence_classes, // Only for debugging. + std::vector *pruned_other_nodes) { pruned_other_nodes->clear(); const int part_index = partition.PartOf(representative_node); // Iterate on all contiguous representatives after the initial one... @@ -318,7 +323,8 @@ void GetAllOtherRepresentativesInSamePartAs( while (true) { DCHECK_EQ(repr, node_equivalence_classes->GetRoot(repr)); repr = representatives_sorted_by_index_in_partition.Prev(repr); - if (repr < 0 || partition.PartOf(repr) != part_index) break; + if (repr < 0 || partition.PartOf(repr) != part_index) + break; pruned_other_nodes->push_back(repr); } // ... and then on all contiguous representatives *before* it. @@ -326,7 +332,8 @@ void GetAllOtherRepresentativesInSamePartAs( while (true) { DCHECK_EQ(repr, node_equivalence_classes->GetRoot(repr)); repr = representatives_sorted_by_index_in_partition.Next(repr); - if (repr < 0 || partition.PartOf(repr) != part_index) break; + if (repr < 0 || partition.PartOf(repr) != part_index) + break; pruned_other_nodes->push_back(repr); } @@ -342,7 +349,8 @@ void GetAllOtherRepresentativesInSamePartAs( } } node_equivalence_classes->KeepOnlyOneNodePerPart(&expected_output); - for (int& x : expected_output) x = node_equivalence_classes->GetRoot(x); + for (int &x : expected_output) + x = node_equivalence_classes->GetRoot(x); std::sort(expected_output.begin(), expected_output.end()); std::vector sorted_output = *pruned_other_nodes; std::sort(sorted_output.begin(), sorted_output.end()); @@ -350,12 +358,12 @@ void GetAllOtherRepresentativesInSamePartAs( absl::StrJoin(sorted_output, " ")); } } -} // namespace +} // namespace absl::Status GraphSymmetryFinder::FindSymmetries( - double time_limit_seconds, std::vector* node_equivalence_classes_io, - std::vector>* generators, - std::vector* factorized_automorphism_group_size) { + double time_limit_seconds, std::vector *node_equivalence_classes_io, + std::vector > *generators, + std::vector *factorized_automorphism_group_size) { // Initialization. time_limit_ = absl::make_unique(time_limit_seconds); IF_STATS_ENABLED(stats_.initialization_time.StartTimer()); @@ -369,18 +377,18 @@ absl::Status GraphSymmetryFinder::FindSymmetries( // Break all inherent asymmetries in the graph. { ScopedTimeDistributionUpdater u(&stats_.initialization_refine_time); - RecursivelyRefinePartitionByAdjacency(/*first_unrefined_part_index=*/0, + RecursivelyRefinePartitionByAdjacency(/*first_unrefined_part_index=*/ 0, &base_partition); } if (time_limit_->LimitReached()) { return absl::Status(absl::StatusCode::kDeadlineExceeded, "During the initial refinement."); } - VLOG(4) << "Base partition: " - << base_partition.DebugString(DynamicPartition::SORT_BY_PART); + VLOG(4) << "Base partition: " << base_partition.DebugString( + DynamicPartition::SORT_BY_PART); MergingPartition node_equivalence_classes(NumNodes()); - std::vector> permutations_displacing_node(NumNodes()); + std::vector > permutations_displacing_node(NumNodes()); std::vector potential_root_image_nodes; IF_STATS_ENABLED(stats_.initialization_time.StopTimerAndAddElapsedTime()); @@ -426,8 +434,8 @@ absl::Status GraphSymmetryFinder::FindSymmetries( InvariantDiveState(invariant_node, base_partition.NumParts())); DistinguishNodeInPartition(invariant_node, &base_partition, nullptr); VLOG(4) << "Invariant dive: invariant node = " << invariant_node - << "; partition after: " - << base_partition.DebugString(DynamicPartition::SORT_BY_PART); + << "; partition after: " << base_partition.DebugString( + DynamicPartition::SORT_BY_PART); if (time_limit_->LimitReached()) { return absl::Status(absl::StatusCode::kDeadlineExceeded, "During the invariant dive."); @@ -442,7 +450,8 @@ absl::Status GraphSymmetryFinder::FindSymmetries( IF_STATS_ENABLED(stats_.main_search_time.StartTimer()); while (!invariant_dive_stack.empty()) { - if (time_limit_->LimitReached()) break; + if (time_limit_->LimitReached()) + break; // Backtrack the last step of 1) (the invariant dive). IF_STATS_ENABLED(stats_.invariant_unroll_time.StartTimer()); const int root_node = invariant_dive_stack.back().invariant_node; @@ -452,8 +461,8 @@ absl::Status GraphSymmetryFinder::FindSymmetries( base_partition.UndoRefineUntilNumPartsEqual(base_num_parts); image_partition.UndoRefineUntilNumPartsEqual(base_num_parts); VLOG(4) << "Backtracking invariant dive: root node = " << root_node - << "; partition: " - << base_partition.DebugString(DynamicPartition::SORT_BY_PART); + << "; partition: " << base_partition.DebugString( + DynamicPartition::SORT_BY_PART); // Now we'll try to map "root_node" to all image nodes that seem compatible // and that aren't "root_node" itself. @@ -485,7 +494,8 @@ absl::Status GraphSymmetryFinder::FindSymmetries( // Try to map "root_node" to all of its potential images. For each image, // we only care about finding a single compatible permutation, if it exists. while (!potential_root_image_nodes.empty()) { - if (time_limit_->LimitReached()) break; + if (time_limit_->LimitReached()) + break; VLOG(4) << "Potential (pruned) images of root node " << root_node << " left: [" << absl::StrJoin(potential_root_image_nodes, " ") << "]."; @@ -551,9 +561,9 @@ namespace { // Knowing that we want to map some element of part #part_index of // "base_partition" to part #part_index of "image_partition", pick the "best" // such mapping, for the global search algorithm. -inline void GetBestMapping(const DynamicPartition& base_partition, - const DynamicPartition& image_partition, - int part_index, int* base_node, int* image_node) { +inline void GetBestMapping(const DynamicPartition &base_partition, + const DynamicPartition &image_partition, + int part_index, int *base_node, int *image_node) { // As of pending CL 66620435, we've loosely tried three variants of // GetBestMapping(): // 1) Just take the first element of the base part, map it to the first @@ -566,8 +576,8 @@ inline void GetBestMapping(const DynamicPartition& base_partition, // Variant 2) gives the best results on most benchmarks, in terms of speed, // but 3) yields much smaller supports for the sat_holeXXX benchmarks, as // long as it's combined with the other tweak enabled by - // FLAGS_minimize_permutation_support_size. - if (FLAGS_minimize_permutation_support_size) { + // absl::GetFlag(FLAGS_minimize_permutation_support_size). + if (absl::GetFlag(FLAGS_minimize_permutation_support_size)) { // Variant 3). for (const int node : base_partition.ElementsInPart(part_index)) { if (image_partition.PartOf(node) == part_index) { @@ -588,18 +598,18 @@ inline void GetBestMapping(const DynamicPartition& base_partition, *image_node = *image_partition.ElementsInPart(part_index).begin(); } } -} // namespace +} // namespace // TODO(user): refactor this method and its submethods into a dedicated class // whose members will be ominously accessed by all the class methods; most // notably the search state stack. This may improve readability. std::unique_ptr GraphSymmetryFinder::FindOneSuitablePermutation( - int root_node, int root_image_node, DynamicPartition* base_partition, - DynamicPartition* image_partition, - const std::vector>& + int root_node, int root_image_node, DynamicPartition *base_partition, + DynamicPartition *image_partition, + const std::vector > & generators_found_so_far, - const std::vector>& permutations_displacing_node) { + const std::vector > &permutations_displacing_node) { // DCHECKs() and statistics. ScopedTimeDistributionUpdater search_time_updater(&stats_.search_time); DCHECK_EQ("", tmp_dynamic_permutation_.DebugString()); @@ -618,9 +628,9 @@ GraphSymmetryFinder::FindOneSuitablePermutation( // Initialize the search: we can already distinguish "root_node" in the base // partition. See the comment below. search_states_.emplace_back( - /*base_node=*/root_node, /*first_image_node=*/-1, - /*num_parts_before_trying_to_map_base_node=*/base_partition->NumParts(), - /*min_potential_mismatching_part_index=*/base_partition->NumParts()); + /*base_node=*/ root_node, /*first_image_node=*/ -1, + /*num_parts_before_trying_to_map_base_node=*/ base_partition->NumParts(), + /*min_potential_mismatching_part_index=*/ base_partition->NumParts()); // We inject the image node directly as the "remaining_pruned_image_nodes". search_states_.back().remaining_pruned_image_nodes.assign(1, root_image_node); { @@ -628,7 +638,8 @@ GraphSymmetryFinder::FindOneSuitablePermutation( DistinguishNodeInPartition(root_node, base_partition, &base_singletons); } while (!search_states_.empty()) { - if (time_limit_->LimitReached()) return nullptr; + if (time_limit_->LimitReached()) + return nullptr; // When exploring a SearchState "ss", we're supposed to have: // - A base_partition that has already been refined on ss->base_node. // (base_singleton is the list of singletons created on the base @@ -639,10 +650,10 @@ GraphSymmetryFinder::FindOneSuitablePermutation( // // Also, one should note that the base partition (before its refinement on // base_node) was deemed compatible with the image partition as it is now. - const SearchState& ss = search_states_.back(); - const int image_node = ss.first_image_node >= 0 - ? ss.first_image_node - : ss.remaining_pruned_image_nodes.back(); + const SearchState &ss = search_states_.back(); + const int image_node = + ss.first_image_node >= 0 ? ss.first_image_node + : ss.remaining_pruned_image_nodes.back(); // Statistics, DCHECKs. IF_STATS_ENABLED(stats_.search_depth.Add(search_states_.size())); @@ -773,7 +784,7 @@ GraphSymmetryFinder::FindOneSuitablePermutation( // 'current' image node of the upper SearchState (which might lead to us // backtracking it, and so on). while (!search_states_.empty()) { - SearchState* const last_ss = &search_states_.back(); + SearchState *const last_ss = &search_states_.back(); image_partition->UndoRefineUntilNumPartsEqual( last_ss->num_parts_before_trying_to_map_base_node); if (last_ss->first_image_node >= 0) { @@ -790,10 +801,10 @@ GraphSymmetryFinder::FindOneSuitablePermutation( // like incrementally maintaining the list of permutations compatible // with the partition so far. const int part = image_partition->PartOf(last_ss->first_image_node); - last_ss->remaining_pruned_image_nodes.reserve( - image_partition->SizeOfPart(part)); - last_ss->remaining_pruned_image_nodes.push_back( - last_ss->first_image_node); + last_ss->remaining_pruned_image_nodes + .reserve(image_partition->SizeOfPart(part)); + last_ss->remaining_pruned_image_nodes + .push_back(last_ss->first_image_node); for (const int e : image_partition->ElementsInPart(part)) { if (e != last_ss->first_image_node) { last_ss->remaining_pruned_image_nodes.push_back(e); @@ -812,7 +823,8 @@ GraphSymmetryFinder::FindOneSuitablePermutation( last_ss->first_image_node = -1; } last_ss->remaining_pruned_image_nodes.pop_back(); - if (!last_ss->remaining_pruned_image_nodes.empty()) break; + if (!last_ss->remaining_pruned_image_nodes.empty()) + break; VLOG(4) << "Backtracking one level up."; base_partition->UndoRefineUntilNumPartsEqual( @@ -854,9 +866,9 @@ GraphSymmetryFinder::TailsOfIncomingArcsTo(int node) const { } void GraphSymmetryFinder::PruneOrbitsUnderPermutationsCompatibleWithPartition( - const DynamicPartition& partition, - const std::vector>& permutations, - const std::vector& permutation_indices, std::vector* nodes) { + const DynamicPartition &partition, + const std::vector > &permutations, + const std::vector &permutation_indices, std::vector *nodes) { VLOG(4) << " Pruning [" << absl::StrJoin(*nodes, ", ") << "]"; // TODO(user): apply a smarter test to decide whether to do the pruning // or not: we can accurately estimate the cost of pruning (iterate through @@ -864,19 +876,20 @@ void GraphSymmetryFinder::PruneOrbitsUnderPermutationsCompatibleWithPartition( // the search below the state that we're currently in, times the expected // number of pruned nodes). Sometimes it may be better to skip the // pruning. - if (nodes->size() <= 1) return; + if (nodes->size() <= 1) + return; // Iterate on all targeted permutations. If they are compatible, apply // them to tmp_partition_ which will contain the incrementally merged // equivalence classes. - std::vector& tmp_nodes_on_support = - tmp_stack_; // Rename, for readability. + std::vector &tmp_nodes_on_support = + tmp_stack_; // Rename, for readability. DCHECK(tmp_nodes_on_support.empty()); // TODO(user): investigate further optimizations: maybe it's possible // to incrementally maintain the set of permutations that is compatible // with the current partition, instead of recomputing it here? for (const int p : permutation_indices) { - const SparsePermutation& permutation = *permutations[p]; + const SparsePermutation &permutation = *permutations[p]; // First, a quick compatibility check: the permutation's cycles must be // smaller or equal to the size of the part that they are included in. bool compatible = true; @@ -888,7 +901,8 @@ void GraphSymmetryFinder::PruneOrbitsUnderPermutationsCompatibleWithPartition( break; } } - if (!compatible) continue; + if (!compatible) + continue; // Now the full compatibility check: each cycle of the permutation must // be fully included in an image part. for (int c = 0; c < permutation.NumCycles(); ++c) { @@ -899,11 +913,12 @@ void GraphSymmetryFinder::PruneOrbitsUnderPermutationsCompatibleWithPartition( compatible = false; break; } - part = partition.PartOf(node); // Initilization of 'part'. + part = partition.PartOf(node); // Initilization of 'part'. } } } - if (!compatible) continue; + if (!compatible) + continue; // The permutation is fully compatible! // TODO(user): ignore cycles that are outside of image_part. MergeNodeEquivalenceClassesAccordingToPermutation(permutation, @@ -929,17 +944,17 @@ void GraphSymmetryFinder::PruneOrbitsUnderPermutationsCompatibleWithPartition( } bool GraphSymmetryFinder::ConfirmFullMatchOrFindNextMappingDecision( - const DynamicPartition& base_partition, - const DynamicPartition& image_partition, - const DynamicPermutation& current_permutation_candidate, - int* min_potential_mismatching_part_index_io, int* next_base_node, - int* next_image_node) const { + const DynamicPartition &base_partition, + const DynamicPartition &image_partition, + const DynamicPermutation ¤t_permutation_candidate, + int *min_potential_mismatching_part_index_io, int *next_base_node, + int *next_image_node) const { *next_base_node = -1; *next_image_node = -1; // The following clause should be true most of the times, except in some // specific use cases. - if (!FLAGS_minimize_permutation_support_size) { + if (!absl::GetFlag(FLAGS_minimize_permutation_support_size)) { // First, we try to map the loose ends of the current permutations: these // loose ends can't be mapped to themselves, so we'll have to map them to // something anyway. @@ -958,10 +973,8 @@ bool GraphSymmetryFinder::ConfirmFullMatchOrFindNextMappingDecision( if (*next_base_node != -1) { // We found loose ends, but none that mapped to its own root. Just pick // any valid image. - *next_image_node = - *image_partition - .ElementsInPart(base_partition.PartOf(*next_base_node)) - .begin(); + *next_image_node = *image_partition + .ElementsInPart(base_partition.PartOf(*next_base_node)).begin(); return false; } } @@ -1013,13 +1026,12 @@ bool GraphSymmetryFinder::ConfirmFullMatchOrFindNextMappingDecision( } std::string GraphSymmetryFinder::SearchState::DebugString() const { - return absl::StrFormat( - "SearchState{ base_node=%d, first_image_node=%d," - " remaining_pruned_image_nodes=[%s]," - " num_parts_before_trying_to_map_base_node=%d }", - base_node, first_image_node, - absl::StrJoin(remaining_pruned_image_nodes, " "), - num_parts_before_trying_to_map_base_node); + return absl::StrFormat("SearchState{ base_node=%d, first_image_node=%d," + " remaining_pruned_image_nodes=[%s]," + " num_parts_before_trying_to_map_base_node=%d }", + base_node, first_image_node, + absl::StrJoin(remaining_pruned_image_nodes, " "), + num_parts_before_trying_to_map_base_node); } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/find_graph_symmetries.h b/ortools/algorithms/find_graph_symmetries.h index 3006a4d953..878fea16c3 100644 --- a/ortools/algorithms/find_graph_symmetries.h +++ b/ortools/algorithms/find_graph_symmetries.h @@ -41,7 +41,7 @@ namespace operations_research { class SparsePermutation; class GraphSymmetryFinder { - public: +public: typedef ::util::StaticGraph<> Graph; // If the Graph passed to the GraphSymmetryFinder is undirected, i.e. @@ -55,12 +55,12 @@ class GraphSymmetryFinder { // // "graph" must not have multi-arcs. // TODO(user): support multi-arcs. - GraphSymmetryFinder(const Graph& graph, bool is_undirected); + GraphSymmetryFinder(const Graph &graph, bool is_undirected); // Whether the given permutation is an automorphism of the graph given at // construction. This costs O(sum(degree(x))) (the sum is over all nodes x // that are displaced by the permutation). - bool IsGraphAutomorphism(const DynamicPermutation& permutation) const; + bool IsGraphAutomorphism(const DynamicPermutation &permutation) const; // Find a set of generators of the automorphism subgroup of the graph that // respects the given node equivalence classes. The generators are themselves @@ -101,9 +101,9 @@ class GraphSymmetryFinder { // partially valid: its last element may be undervalued. But all prior // elements are valid factors of the automorphism group size. absl::Status FindSymmetries( - double time_limit_seconds, std::vector* node_equivalence_classes_io, - std::vector >* generators, - std::vector* factorized_automorphism_group_size); + double time_limit_seconds, std::vector *node_equivalence_classes_io, + std::vector > *generators, + std::vector *factorized_automorphism_group_size); // Fully refine the partition of nodes, using the graph as symmetry breaker. // This means applying the following steps on each part P of the partition: @@ -117,7 +117,7 @@ class GraphSymmetryFinder { // already partially refined on all parts #0...#K, then you should set // "first_unrefined_part_index" to K+1. void RecursivelyRefinePartitionByAdjacency(int first_unrefined_part_index, - DynamicPartition* partition); + DynamicPartition *partition); // **** Methods below are public FOR TESTING ONLY. **** @@ -125,11 +125,11 @@ class GraphSymmetryFinder { // fully refined, further refine it by {node}, and propagate by adjacency. // Also, optionally collect all the new singletons of the partition in // "new_singletons", sorted by their part number in the partition. - void DistinguishNodeInPartition(int node, DynamicPartition* partition, - std::vector* new_singletons_or_null); + void DistinguishNodeInPartition(int node, DynamicPartition *partition, + std::vector *new_singletons_or_null); - private: - const Graph& graph_; +private: + const Graph &graph_; inline int NumNodes() const { return graph_.num_nodes(); } @@ -145,8 +145,8 @@ class GraphSymmetryFinder { // vectors are empty, and TailsOfIncomingArcsTo() crashes. std::vector flattened_reverse_adj_lists_; std::vector reverse_adj_list_index_; - util::BeginEndWrapper::const_iterator> TailsOfIncomingArcsTo( - int node) const; + util::BeginEndWrapper::const_iterator> + TailsOfIncomingArcsTo(int node) const; // Deadline management. Populated upon FindSymmetries(). mutable std::unique_ptr time_limit_; @@ -162,11 +162,11 @@ class GraphSymmetryFinder { // is an inverted index from each node to all permutations (that we found) // that displace it. std::unique_ptr FindOneSuitablePermutation( - int root_node, int root_image_node, DynamicPartition* base_partition, - DynamicPartition* image_partition, - const std::vector >& + int root_node, int root_image_node, DynamicPartition *base_partition, + DynamicPartition *image_partition, + const std::vector > & generators_found_so_far, - const std::vector >& permutations_displacing_node); + const std::vector > &permutations_displacing_node); // Data structure used by FindOneSuitablePermutation(). See the .cc struct SearchState { @@ -187,8 +187,7 @@ class GraphSymmetryFinder { int min_potential_mismatching_part_index; SearchState(int bn, int in, int np, int mi) - : base_node(bn), - first_image_node(in), + : base_node(bn), first_image_node(in), num_parts_before_trying_to_map_base_node(np), min_potential_mismatching_part_index(mi) {} @@ -211,11 +210,11 @@ class GraphSymmetryFinder { // even if the partitions aren't actually a full match, because it uses // fingerprints to compare part. This should almost never happen. bool ConfirmFullMatchOrFindNextMappingDecision( - const DynamicPartition& base_partition, - const DynamicPartition& image_partition, - const DynamicPermutation& current_permutation_candidate, - int* min_potential_mismatching_part_index_io, int* next_base_node, - int* next_image_node) const; + const DynamicPartition &base_partition, + const DynamicPartition &image_partition, + const DynamicPermutation ¤t_permutation_candidate, + int *min_potential_mismatching_part_index_io, int *next_base_node, + int *next_image_node) const; // Subroutine of FindOneSuitablePermutation(), split out for modularity: // Keep only one node of "nodes" per orbit, where the orbits are described @@ -223,20 +222,20 @@ class GraphSymmetryFinder { // "permutation_indices" and that are compatible with "partition". // For each orbit, keep the first node that appears in "nodes". void PruneOrbitsUnderPermutationsCompatibleWithPartition( - const DynamicPartition& partition, - const std::vector >& all_permutations, - const std::vector& permutation_indices, std::vector* nodes); + const DynamicPartition &partition, + const std::vector > &all_permutations, + const std::vector &permutation_indices, std::vector *nodes); // Temporary objects used by some of the class methods, and owned by the // class to avoid (costly) re-allocation. Their resting states are described // in the side comments; with N = NumNodes(). - DynamicPermutation tmp_dynamic_permutation_; // Identity(N) - mutable std::vector tmp_node_mask_; // [0..N-1] = false - std::vector tmp_degree_; // [0..N-1] = 0. - std::vector tmp_stack_; // Empty. - std::vector > tmp_nodes_with_degree_; // [0..N-1] = []. - MergingPartition tmp_partition_; // Reset(N). - std::vector tmp_compatible_permutations_; // Empty. + DynamicPermutation tmp_dynamic_permutation_; // Identity(N) + mutable std::vector tmp_node_mask_; // [0..N-1] = false + std::vector tmp_degree_; // [0..N-1] = 0. + std::vector tmp_stack_; // Empty. + std::vector > tmp_nodes_with_degree_; // [0..N-1] = []. + MergingPartition tmp_partition_; // Reset(N). + std::vector tmp_compatible_permutations_; // Empty. // Internal statistics, used for performance tuning and debugging. struct Stats : public StatsGroup { @@ -262,16 +261,19 @@ class GraphSymmetryFinder { "p ┣╸Mapping election / full match detection", this), map_election_std_mapping_time("q ┃ ┣╸Mapping elected", this), map_election_std_full_match_time("r ┃ ┗╸Full Match", this), - automorphism_test_time("s ┣╸[Upon full match] Automorphism check", - this), + automorphism_test_time( + "s ┣╸[Upon full match] Automorphism check", this), automorphism_test_fail_time("t ┃ ┣╸Fail", this), automorphism_test_success_time("u ┃ ┗╸Success", this), - search_finalize_time("v ┣╸[Upon auto success] Finalization", this), + search_finalize_time("v ┣╸[Upon auto success] Finalization", + this), dynamic_permutation_undo_time( - "w ┣╸[Upon auto fail, full] Dynamic permutation undo", this), + "w ┣╸[Upon auto fail, full] Dynamic permutation undo", + this), map_reelection_time( "x ┣╸[Upon auto fail, partial] Mapping re-election", this), - non_singleton_search_time("y ┃ ┗╸Non-singleton search", this), + non_singleton_search_time("y ┃ ┗╸Non-singleton search", + this), backtracking_time("z ┗╸Backtracking", this), pruning_time("{ ┗╸Pruning", this), search_depth("~ Search Stats: search_depth", this) {} @@ -309,6 +311,6 @@ class GraphSymmetryFinder { mutable Stats stats_; }; -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_FIND_GRAPH_SYMMETRIES_H_ +#endif // OR_TOOLS_ALGORITHMS_FIND_GRAPH_SYMMETRIES_H_ diff --git a/ortools/algorithms/hungarian.cc b/ortools/algorithms/hungarian.cc index 8f537d7ea5..e911e67e9c 100644 --- a/ortools/algorithms/hungarian.cc +++ b/ortools/algorithms/hungarian.cc @@ -29,7 +29,7 @@ class HungarianOptimizer { static constexpr int kHungarianOptimizerRowNotFound = -1; static constexpr int kHungarianOptimizerColNotFound = -2; - public: +public: // Setup the initial conditions for the algorithm. // Parameters: costs is a matrix of the cost of assigning each agent to @@ -38,25 +38,29 @@ class HungarianOptimizer { // be square (i.e. we can have different numbers of agents and tasks), but it // must be regular (i.e. there must be the same number of entries in each row // of the matrix). - explicit HungarianOptimizer(const std::vector>& costs); + explicit HungarianOptimizer(const std::vector > &costs); // Find an assignment which maximizes the total cost. // Returns the assignment in the two vectors passed as argument. // preimage[i] is assigned to image[i]. - void Maximize(std::vector* preimage, std::vector* image); + void Maximize(std::vector *preimage, std::vector *image); // Like Maximize(), but minimizing the cost instead. - void Minimize(std::vector* preimage, std::vector* image); + void Minimize(std::vector *preimage, std::vector *image); - private: - typedef void (HungarianOptimizer::*Step)(); +private: + typedef void(HungarianOptimizer::*Step)(); - typedef enum { NONE, PRIME, STAR } Mark; + typedef enum { + NONE, + PRIME, + STAR + } Mark; // Convert the final cost matrix into a set of assignments of preimage->image. // Returns the assignment in the two vectors passed as argument, the same as // Minimize and Maximize - void FindAssignments(std::vector* preimage, std::vector* image); + void FindAssignments(std::vector *preimage, std::vector *image); // Is the cell (row, col) starred? bool IsStarred(int row, int col) const { return marks_[row][col] == STAR; } @@ -123,7 +127,7 @@ class HungarianOptimizer { // Find an uncovered zero and store its coordinates in (zeroRow_, zeroCol_) // and return true, or return false if no such cell exists. - bool FindZero(int* zero_row, int* zero_col) const; + bool FindZero(int *zero_row, int *zero_col) const; // Print the matrix to stdout (for debugging.) void PrintMatrix(); @@ -177,7 +181,7 @@ class HungarianOptimizer { int matrix_size_; // The expanded cost matrix. - std::vector> costs_; + std::vector > costs_; // The greatest cost in the initial cost matrix. double max_cost_; @@ -187,14 +191,14 @@ class HungarianOptimizer { std::vector cols_covered_; // The marks_ (star/prime/none) on each element of the cost matrix. - std::vector> marks_; + std::vector > marks_; // The number of stars in each column - used to speed up coverStarredZeroes. std::vector stars_in_col_; // Representation of a path_ through the matrix - used in step 5. - std::vector preimage_; // i.e. the agents - std::vector image_; // i.e. the tasks + std::vector preimage_; // i.e. the agents + std::vector image_; // i.e. the tasks // The width_ and height_ of the initial (non-expanded) cost matrix. int width_; @@ -205,18 +209,9 @@ class HungarianOptimizer { }; HungarianOptimizer::HungarianOptimizer( - const std::vector>& costs) - : matrix_size_(0), - costs_(), - max_cost_(0), - rows_covered_(), - cols_covered_(), - marks_(), - stars_in_col_(), - preimage_(), - image_(), - width_(0), - height_(0), + const std::vector > &costs) + : matrix_size_(0), costs_(), max_cost_(0), rows_covered_(), cols_covered_(), + marks_(), stars_in_col_(), preimage_(), image_(), width_(0), height_(0), state_(nullptr) { width_ = costs.size(); @@ -270,8 +265,8 @@ HungarianOptimizer::HungarianOptimizer( // Find an assignment which maximizes the total cost. // Return an array of pairs of integers. Each pair (i, j) corresponds to // assigning agent i to task j. -void HungarianOptimizer::Maximize(std::vector* preimage, - std::vector* image) { +void HungarianOptimizer::Maximize(std::vector *preimage, + std::vector *image) { // Find a maximal assignment by subtracting each of the // original costs from max_cost_ and then minimizing. for (int row = 0; row < width_; ++row) { @@ -285,8 +280,8 @@ void HungarianOptimizer::Maximize(std::vector* preimage, // Find an assignment which minimizes the total cost. // Return an array of pairs of integers. Each pair (i, j) corresponds to // assigning agent i to task j. -void HungarianOptimizer::Minimize(std::vector* preimage, - std::vector* image) { +void HungarianOptimizer::Minimize(std::vector *preimage, + std::vector *image) { DoMunkres(); FindAssignments(preimage, image); } @@ -294,8 +289,8 @@ void HungarianOptimizer::Minimize(std::vector* preimage, // Convert the final cost matrix into a set of assignments of agents -> tasks. // Return an array of pairs of integers, the same as the return values of // Minimize() and Maximize() -void HungarianOptimizer::FindAssignments(std::vector* preimage, - std::vector* image) { +void HungarianOptimizer::FindAssignments(std::vector *preimage, + std::vector *image) { preimage->clear(); image->clear(); for (int row = 0; row < width_; ++row) { @@ -396,7 +391,7 @@ double HungarianOptimizer::FindSmallestUncovered() const { // Find an uncovered zero and store its co-ordinates in (zeroRow, zeroCol) // and return true, or return false if no such cell exists. -bool HungarianOptimizer::FindZero(int* zero_row, int* zero_col) const { +bool HungarianOptimizer::FindZero(int *zero_row, int *zero_col) const { for (int row = 0; row < matrix_size_; ++row) { if (RowCovered(row)) { continue; @@ -642,9 +637,9 @@ void HungarianOptimizer::AugmentPath() { state_ = &HungarianOptimizer::PrimeZeroes; } -bool InputContainsNan(const std::vector>& input) { - for (const auto& subvector : input) { - for (const auto& num : subvector) { +bool InputContainsNan(const std::vector > &input) { + for (const auto &subvector : input) { + for (const auto &num : subvector) { if (std::isnan(num)) { LOG(ERROR) << "The provided input contains " << num << "."; return true; @@ -654,10 +649,10 @@ bool InputContainsNan(const std::vector>& input) { return false; } -void MinimizeLinearAssignment( - const std::vector>& cost, - absl::flat_hash_map* direct_assignment, - absl::flat_hash_map* reverse_assignment) { +void +MinimizeLinearAssignment(const std::vector > &cost, + absl::flat_hash_map *direct_assignment, + absl::flat_hash_map *reverse_assignment) { if (InputContainsNan(cost)) { LOG(ERROR) << "Returning before invoking the Hungarian optimizer."; return; @@ -672,10 +667,10 @@ void MinimizeLinearAssignment( } } -void MaximizeLinearAssignment( - const std::vector>& cost, - absl::flat_hash_map* direct_assignment, - absl::flat_hash_map* reverse_assignment) { +void +MaximizeLinearAssignment(const std::vector > &cost, + absl::flat_hash_map *direct_assignment, + absl::flat_hash_map *reverse_assignment) { if (InputContainsNan(cost)) { LOG(ERROR) << "Returning before invoking the Hungarian optimizer."; return; @@ -690,4 +685,4 @@ void MaximizeLinearAssignment( } } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/hungarian.h b/ortools/algorithms/hungarian.h index 8a382bf9f4..42846b226b 100644 --- a/ortools/algorithms/hungarian.h +++ b/ortools/algorithms/hungarian.h @@ -45,17 +45,17 @@ namespace operations_research { // See IMPORTANT NOTE at the top of the file. -void MinimizeLinearAssignment( - const std::vector >& cost, - absl::flat_hash_map* direct_assignment, - absl::flat_hash_map* reverse_assignment); +void + MinimizeLinearAssignment(const std::vector > &cost, + absl::flat_hash_map *direct_assignment, + absl::flat_hash_map *reverse_assignment); // See IMPORTANT NOTE at the top of the file. -void MaximizeLinearAssignment( - const std::vector >& cost, - absl::flat_hash_map* direct_assignment, - absl::flat_hash_map* reverse_assignment); +void + MaximizeLinearAssignment(const std::vector > &cost, + absl::flat_hash_map *direct_assignment, + absl::flat_hash_map *reverse_assignment); -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_HUNGARIAN_H_ +#endif // OR_TOOLS_ALGORITHMS_HUNGARIAN_H_ diff --git a/ortools/algorithms/hungarian_test.cc b/ortools/algorithms/hungarian_test.cc index 840f8adee9..1b7ec461e8 100644 --- a/ortools/algorithms/hungarian_test.cc +++ b/ortools/algorithms/hungarian_test.cc @@ -15,8 +15,8 @@ namespace operations_research { // result as well as whether the result is the expected one. void GenericCheck(const int expected_assignment_size, - const absl::flat_hash_map& direct_assignment, - const absl::flat_hash_map& reverse_assignment, + const absl::flat_hash_map &direct_assignment, + const absl::flat_hash_map &reverse_assignment, const int expected_agents[], const int expected_tasks[]) { EXPECT_EQ(expected_assignment_size, direct_assignment.size()); EXPECT_EQ(expected_assignment_size, reverse_assignment.size()); @@ -26,14 +26,14 @@ void GenericCheck(const int expected_assignment_size, EXPECT_EQ(gtl::FindOrDie(reverse_assignment, expected_tasks[i]), expected_agents[i]); } - for (const auto& direct_iter : direct_assignment) { + for (const auto &direct_iter : direct_assignment) { EXPECT_EQ(gtl::FindOrDie(reverse_assignment, direct_iter.second), direct_iter.first) << direct_iter.first << " -> " << direct_iter.second; } } -void TestMinimization(const std::vector >& cost, +void TestMinimization(const std::vector > &cost, const int expected_assignment_size, const int expected_agents[], const int expected_tasks[]) { absl::flat_hash_map direct_assignment; @@ -44,7 +44,7 @@ void TestMinimization(const std::vector >& cost, expected_agents, expected_tasks); } -void TestMaximization(const std::vector >& cost, +void TestMaximization(const std::vector > &cost, const int expected_assignment_size, const int expected_agents[], const int expected_tasks[]) { absl::flat_hash_map direct_assignment; @@ -59,30 +59,30 @@ void TestMaximization(const std::vector >& cost, TEST(LinearAssignmentTest, NullMatrix) { std::vector > cost; - const int* expected_agents = NULL; - const int* expected_tasks = NULL; + const int *expected_agents = NULL; + const int *expected_tasks = NULL; TestMinimization(cost, 0, expected_agents, expected_tasks); TestMaximization(cost, 0, expected_agents, expected_tasks); } -#define MATRIX_TEST \ - { \ - std::vector > cost(kMatrixHeight); \ - for (int row = 0; row < kMatrixHeight; ++row) { \ - cost[row].resize(kMatrixWidth); \ - for (int col = 0; col < kMatrixWidth; ++col) { \ - cost[row][col] = kCost[row][col]; \ - } \ - } \ - EXPECT_EQ(arraysize(expected_agents_for_min), \ - arraysize(expected_tasks_for_min)); \ - EXPECT_EQ(arraysize(expected_agents_for_max), \ - arraysize(expected_tasks_for_max)); \ - const int assignment_size = arraysize(expected_agents_for_max); \ - TestMinimization(cost, assignment_size, expected_agents_for_min, \ - expected_tasks_for_min); \ - TestMaximization(cost, assignment_size, expected_agents_for_max, \ - expected_tasks_for_max); \ +#define MATRIX_TEST \ + { \ + std::vector > cost(kMatrixHeight); \ + for (int row = 0; row < kMatrixHeight; ++row) { \ + cost[row].resize(kMatrixWidth); \ + for (int col = 0; col < kMatrixWidth; ++col) { \ + cost[row][col] = kCost[row][col]; \ + } \ + } \ + EXPECT_EQ(arraysize(expected_agents_for_min), \ + arraysize(expected_tasks_for_min)); \ + EXPECT_EQ(arraysize(expected_agents_for_max), \ + arraysize(expected_tasks_for_max)); \ + const int assignment_size = arraysize(expected_agents_for_max); \ + TestMinimization(cost, assignment_size, expected_agents_for_min, \ + expected_tasks_for_min); \ + TestMaximization(cost, assignment_size, expected_agents_for_max, \ + expected_tasks_for_max); \ } // Test on a 1x1 matrix @@ -90,11 +90,11 @@ TEST(LinearAssignmentTest, NullMatrix) { TEST(LinearAssignmentTest, SizeOneMatrix) { const int kMatrixHeight = 1; const int kMatrixWidth = 1; - const double kCost[kMatrixHeight][kMatrixWidth] = {{4}}; - const int expected_agents_for_min[] = {0}; - const int expected_tasks_for_min[] = {0}; - const int expected_agents_for_max[] = {0}; - const int expected_tasks_for_max[] = {0}; + const double kCost[kMatrixHeight][kMatrixWidth] = { { 4 } }; + const int expected_agents_for_min[] = { 0 }; + const int expected_tasks_for_min[] = { 0 }; + const int expected_agents_for_max[] = { 0 }; + const int expected_tasks_for_max[] = { 0 }; MATRIX_TEST; } @@ -103,14 +103,14 @@ TEST(LinearAssignmentTest, SizeOneMatrix) { TEST(LinearAssignmentTest, Small4x4Matrix) { const int kMatrixHeight = 4; const int kMatrixWidth = 4; - const double kCost[kMatrixHeight][kMatrixWidth] = {{90, 75, 75, 80}, - {35, 85, 55, 65}, - {125, 95, 90, 105}, - {45, 110, 95, 115}}; - const int expected_agents_for_min[] = {0, 1, 2, 3}; - const int expected_tasks_for_min[] = {3, 2, 1, 0}; - const int expected_agents_for_max[] = {0, 1, 2, 3}; - const int expected_tasks_for_max[] = {2, 1, 0, 3}; + const double kCost[kMatrixHeight][kMatrixWidth] = { { 90, 75, 75, 80 }, + { 35, 85, 55, 65 }, + { 125, 95, 90, 105 }, + { 45, 110, 95, 115 } }; + const int expected_agents_for_min[] = { 0, 1, 2, 3 }; + const int expected_tasks_for_min[] = { 3, 2, 1, 0 }; + const int expected_agents_for_max[] = { 0, 1, 2, 3 }; + const int expected_tasks_for_max[] = { 2, 1, 0, 3 }; MATRIX_TEST; } @@ -118,12 +118,13 @@ TEST(LinearAssignmentTest, Small4x4Matrix) { TEST(LinearAssignmentTest, Small3x4Matrix) { const int kMatrixHeight = 3; const int kMatrixWidth = 4; - const double kCost[kMatrixHeight][kMatrixWidth] = { - {90, 75, 75, 80}, {35, 85, 55, 65}, {125, 95, 90, 105}}; - const int expected_agents_for_min[] = {0, 1, 2}; - const int expected_tasks_for_min[] = {1, 0, 2}; - const int expected_agents_for_max[] = {0, 1, 2}; - const int expected_tasks_for_max[] = {3, 1, 0}; + const double kCost[kMatrixHeight][kMatrixWidth] = { { 90, 75, 75, 80 }, + { 35, 85, 55, 65 }, + { 125, 95, 90, 105 } }; + const int expected_agents_for_min[] = { 0, 1, 2 }; + const int expected_tasks_for_min[] = { 1, 0, 2 }; + const int expected_agents_for_max[] = { 0, 1, 2 }; + const int expected_tasks_for_max[] = { 3, 1, 0 }; MATRIX_TEST; } @@ -132,14 +133,15 @@ TEST(LinearAssignmentTest, Small4x3Matrix) { const int kMatrixHeight = 4; const int kMatrixWidth = 3; const double kCost[kMatrixHeight][kMatrixWidth] = { - {90, 75, 75}, {35, 85, 55}, {125, 95, 90}, {45, 110, 95}}; - const int expected_agents_for_min[] = {0, 1, 3}; - const int expected_tasks_for_min[] = {1, 2, 0}; - const int expected_agents_for_max[] = {0, 2, 3}; - const int expected_tasks_for_max[] = {2, 0, 1}; + { 90, 75, 75 }, { 35, 85, 55 }, { 125, 95, 90 }, { 45, 110, 95 } + }; + const int expected_agents_for_min[] = { 0, 1, 3 }; + const int expected_tasks_for_min[] = { 1, 2, 0 }; + const int expected_agents_for_max[] = { 0, 2, 3 }; + const int expected_tasks_for_max[] = { 2, 0, 1 }; MATRIX_TEST; } #undef MATRIX_TEST -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/knapsack_solver.cc b/ortools/algorithms/knapsack_solver.cc index 923cf1920a..adbedf3b65 100644 --- a/ortools/algorithms/knapsack_solver.cc +++ b/ortools/algorithms/knapsack_solver.cc @@ -37,8 +37,8 @@ const int kMaxNumberOf64Items = 64; struct CompareKnapsackItemsInDecreasingEfficiencyOrder { explicit CompareKnapsackItemsInDecreasingEfficiencyOrder(int64 _profit_max) : profit_max(_profit_max) {} - bool operator()(const KnapsackItemPtr& item1, - const KnapsackItemPtr& item2) const { + bool operator()(const KnapsackItemPtr &item1, + const KnapsackItemPtr &item2) const { return item1->GetEfficiency(profit_max) > item2->GetEfficiency(profit_max); } const int64 profit_max; @@ -50,8 +50,8 @@ struct CompareKnapsackItemsInDecreasingEfficiencyOrder { // prefer the one with the highest current profit, ie. usually the one closer // to a leaf. In practice, the main advantage is to have smaller path. struct CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder { - bool operator()(const KnapsackSearchNode* node_1, - const KnapsackSearchNode* node_2) const { + bool operator()(const KnapsackSearchNode *node_1, + const KnapsackSearchNode *node_2) const { const int64 profit_upper_bound_1 = node_1->profit_upper_bound(); const int64 profit_upper_bound_2 = node_2->profit_upper_bound(); if (profit_upper_bound_1 == profit_upper_bound_2) { @@ -62,9 +62,8 @@ struct CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder { }; typedef std::priority_queue< - KnapsackSearchNode*, std::vector, - CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder> - SearchQueue; + KnapsackSearchNode *, std::vector, + CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder> SearchQueue; // Returns true when value_1 * value_2 may overflow int64. inline bool WillProductOverflow(int64 value_1, int64 value_2) { @@ -79,7 +78,9 @@ inline bool WillProductOverflow(int64 value_1, int64 value_2) { // Returns an upper bound of (numerator_1 * numerator_2) / denominator int64 UpperBoundOfRatio(int64 numerator_1, int64 numerator_2, int64 denominator) { - DCHECK_GT(denominator, int64{0}); + DCHECK_GT(denominator, int64 { + 0 + }); if (!WillProductOverflow(numerator_1, numerator_2)) { const int64 numerator = numerator_1 * numerator_2; // Round to zero. @@ -95,26 +96,23 @@ int64 UpperBoundOfRatio(int64 numerator_1, int64 numerator_2, } } -} // namespace +} // namespace // ----- KnapsackSearchNode ----- -KnapsackSearchNode::KnapsackSearchNode(const KnapsackSearchNode* const parent, - const KnapsackAssignment& assignment) - : depth_((parent == nullptr) ? 0 : parent->depth() + 1), - parent_(parent), - assignment_(assignment), - current_profit_(0), - profit_upper_bound_(kint64max), - next_item_id_(kNoSelection) {} +KnapsackSearchNode::KnapsackSearchNode(const KnapsackSearchNode *const parent, + const KnapsackAssignment &assignment) + : depth_((parent == nullptr) ? 0 : parent->depth() + 1), parent_(parent), + assignment_(assignment), current_profit_(0), + profit_upper_bound_(kint64max), next_item_id_(kNoSelection) {} // ----- KnapsackSearchPath ----- -KnapsackSearchPath::KnapsackSearchPath(const KnapsackSearchNode& from, - const KnapsackSearchNode& to) +KnapsackSearchPath::KnapsackSearchPath(const KnapsackSearchNode &from, + const KnapsackSearchNode &to) : from_(from), via_(nullptr), to_(to) {} void KnapsackSearchPath::Init() { - const KnapsackSearchNode* node_from = MoveUpToDepth(from_, to_.depth()); - const KnapsackSearchNode* node_to = MoveUpToDepth(to_, from_.depth()); + const KnapsackSearchNode *node_from = MoveUpToDepth(from_, to_.depth()); + const KnapsackSearchNode *node_to = MoveUpToDepth(to_, from_.depth()); CHECK_EQ(node_from->depth(), node_to->depth()); // Find common parent. @@ -125,9 +123,10 @@ void KnapsackSearchPath::Init() { via_ = node_from; } -const KnapsackSearchNode* KnapsackSearchPath::MoveUpToDepth( - const KnapsackSearchNode& node, int depth) const { - const KnapsackSearchNode* current_node = &node; +const KnapsackSearchNode * +KnapsackSearchPath::MoveUpToDepth(const KnapsackSearchNode &node, + int depth) const { + const KnapsackSearchNode *current_node = &node; while (current_node->depth() > depth) { current_node = current_node->parent(); } @@ -144,7 +143,7 @@ void KnapsackState::Init(int number_of_items) { // Returns false when the state is invalid. bool KnapsackState::UpdateState(bool revert, - const KnapsackAssignment& assignment) { + const KnapsackAssignment &assignment) { if (revert) { is_bound_[assignment.item_id] = false; } else { @@ -159,17 +158,14 @@ bool KnapsackState::UpdateState(bool revert, } // ----- KnapsackPropagator ----- -KnapsackPropagator::KnapsackPropagator(const KnapsackState& state) - : items_(), - current_profit_(0), - profit_lower_bound_(0), - profit_upper_bound_(kint64max), - state_(state) {} +KnapsackPropagator::KnapsackPropagator(const KnapsackState &state) + : items_(), current_profit_(0), profit_lower_bound_(0), + profit_upper_bound_(kint64max), state_(state) {} KnapsackPropagator::~KnapsackPropagator() { gtl::STLDeleteElements(&items_); } -void KnapsackPropagator::Init(const std::vector& profits, - const std::vector& weights) { +void KnapsackPropagator::Init(const std::vector &profits, + const std::vector &weights) { const int number_of_items = profits.size(); items_.assign(number_of_items, static_cast(nullptr)); for (int i = 0; i < number_of_items; ++i) { @@ -182,7 +178,7 @@ void KnapsackPropagator::Init(const std::vector& profits, } bool KnapsackPropagator::Update(bool revert, - const KnapsackAssignment& assignment) { + const KnapsackAssignment &assignment) { if (assignment.is_in) { if (revert) { current_profit_ -= items_[assignment.item_id]->profit; @@ -194,9 +190,9 @@ bool KnapsackPropagator::Update(bool revert, } void KnapsackPropagator::CopyCurrentStateToSolution( - bool has_one_propagator, std::vector* solution) const { + bool has_one_propagator, std::vector *solution) const { CHECK(solution != nullptr); - for (const KnapsackItem* const item : items_) { + for (const KnapsackItem *const item : items_) { const int item_id = item->id; (*solution)[item_id] = state_.is_bound(item_id) && state_.is_in(item_id); } @@ -207,13 +203,9 @@ void KnapsackPropagator::CopyCurrentStateToSolution( // ----- KnapsackCapacityPropagator ----- KnapsackCapacityPropagator::KnapsackCapacityPropagator( - const KnapsackState& state, int64 capacity) - : KnapsackPropagator(state), - capacity_(capacity), - consumed_capacity_(0), - break_item_id_(kNoSelection), - sorted_items_(), - profit_max_(0) {} + const KnapsackState &state, int64 capacity) + : KnapsackPropagator(state), capacity_(capacity), consumed_capacity_(0), + break_item_id_(kNoSelection), sorted_items_(), profit_max_(0) {} KnapsackCapacityPropagator::~KnapsackCapacityPropagator() {} @@ -227,7 +219,7 @@ void KnapsackCapacityPropagator::ComputeProfitBounds() { int break_sorted_item_id = kNoSelection; const int number_of_sorted_items = sorted_items_.size(); for (int sorted_id = 0; sorted_id < number_of_sorted_items; ++sorted_id) { - const KnapsackItem* const item = sorted_items_[sorted_id]; + const KnapsackItem *const item = sorted_items_[sorted_id]; if (!state().is_bound(item->id)) { break_item_id_ = item->id; @@ -255,7 +247,7 @@ void KnapsackCapacityPropagator::InitPropagator() { break_item_id_ = kNoSelection; sorted_items_ = items(); profit_max_ = 0; - for (const KnapsackItem* const item : sorted_items_) { + for (const KnapsackItem *const item : sorted_items_) { profit_max_ = std::max(profit_max_, item->profit); } ++profit_max_; @@ -265,7 +257,7 @@ void KnapsackCapacityPropagator::InitPropagator() { // Returns false when the propagator fails. bool KnapsackCapacityPropagator::UpdatePropagator( - bool revert, const KnapsackAssignment& assignment) { + bool revert, const KnapsackAssignment &assignment) { if (assignment.is_in) { if (revert) { consumed_capacity_ -= items()[assignment.item_id]->weight; @@ -280,10 +272,10 @@ bool KnapsackCapacityPropagator::UpdatePropagator( } void KnapsackCapacityPropagator::CopyCurrentStateToSolutionPropagator( - std::vector* solution) const { + std::vector *solution) const { CHECK(solution != nullptr); int64 remaining_capacity = capacity_ - consumed_capacity_; - for (const KnapsackItem* const item : sorted_items_) { + for (const KnapsackItem *const item : sorted_items_) { if (!state().is_bound(item->id)) { if (remaining_capacity >= item->weight) { remaining_capacity -= item->weight; @@ -333,20 +325,17 @@ int64 KnapsackCapacityPropagator::GetAdditionalProfit(int64 remaining_capacity, } // ----- KnapsackGenericSolver ----- -KnapsackGenericSolver::KnapsackGenericSolver(const std::string& solver_name) - : BaseKnapsackSolver(solver_name), - propagators_(), - master_propagator_id_(kMasterPropagatorId), - search_nodes_(), - state_(), - best_solution_profit_(0), - best_solution_() {} +KnapsackGenericSolver::KnapsackGenericSolver(const std::string &solver_name) + : BaseKnapsackSolver(solver_name), propagators_(), + master_propagator_id_(kMasterPropagatorId), search_nodes_(), state_(), + best_solution_profit_(0), best_solution_() {} KnapsackGenericSolver::~KnapsackGenericSolver() { Clear(); } -void KnapsackGenericSolver::Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { +void +KnapsackGenericSolver::Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { CHECK_EQ(capacities.size(), weights.size()); Clear(); @@ -357,7 +346,7 @@ void KnapsackGenericSolver::Init(const std::vector& profits, for (int i = 0; i < number_of_dimensions; ++i) { CHECK_EQ(number_of_items, weights[i].size()); - KnapsackCapacityPropagator* propagator = + KnapsackCapacityPropagator *propagator = new KnapsackCapacityPropagator(state_, capacities[i]); propagator->Init(profits, weights[i]); propagators_.push_back(propagator); @@ -367,8 +356,8 @@ void KnapsackGenericSolver::Init(const std::vector& profits, void KnapsackGenericSolver::GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, - int64* lower_bound, - int64* upper_bound) { + int64 *lower_bound, + int64 *upper_bound) { CHECK(lower_bound != nullptr); CHECK(upper_bound != nullptr); KnapsackAssignment assignment(item_id, is_item_in); @@ -377,10 +366,9 @@ void KnapsackGenericSolver::GetLowerAndUpperBoundWhenItem(int item_id, *lower_bound = 0LL; *upper_bound = 0LL; } else { - *lower_bound = - (HasOnePropagator()) - ? propagators_[master_propagator_id_]->profit_lower_bound() - : 0LL; + *lower_bound = (HasOnePropagator()) ? propagators_[master_propagator_id_] + ->profit_lower_bound() + : 0LL; *upper_bound = GetAggregatedProfitUpperBound(); } @@ -391,8 +379,8 @@ void KnapsackGenericSolver::GetLowerAndUpperBoundWhenItem(int item_id, } } -int64 KnapsackGenericSolver::Solve(TimeLimit* time_limit, - bool* is_solution_optimal) { +int64 KnapsackGenericSolver::Solve(TimeLimit *time_limit, + bool *is_solution_optimal) { DCHECK(time_limit != nullptr); DCHECK(is_solution_optimal != nullptr); best_solution_profit_ = 0LL; @@ -400,7 +388,7 @@ int64 KnapsackGenericSolver::Solve(TimeLimit* time_limit, SearchQueue search_queue; const KnapsackAssignment assignment(kNoSelection, true); - KnapsackSearchNode* root_node = new KnapsackSearchNode(nullptr, assignment); + KnapsackSearchNode *root_node = new KnapsackSearchNode(nullptr, assignment); root_node->set_current_profit(GetCurrentProfit()); root_node->set_profit_upper_bound(GetAggregatedProfitUpperBound()); root_node->set_next_item_id(GetNextItemId()); @@ -413,14 +401,14 @@ int64 KnapsackGenericSolver::Solve(TimeLimit* time_limit, search_queue.push(search_nodes_.back()); } - KnapsackSearchNode* current_node = root_node; + KnapsackSearchNode *current_node = root_node; while (!search_queue.empty() && search_queue.top()->profit_upper_bound() > best_solution_profit_) { if (time_limit->LimitReached()) { *is_solution_optimal = false; break; } - KnapsackSearchNode* const node = search_queue.top(); + KnapsackSearchNode *const node = search_queue.top(); search_queue.pop(); if (node != current_node) { @@ -447,11 +435,11 @@ void KnapsackGenericSolver::Clear() { } // Returns false when at least one propagator fails. -bool KnapsackGenericSolver::UpdatePropagators(const KnapsackSearchPath& path) { +bool KnapsackGenericSolver::UpdatePropagators(const KnapsackSearchPath &path) { bool no_fail = true; // Revert previous changes. - const KnapsackSearchNode* node = &path.from(); - const KnapsackSearchNode* via = &path.via(); + const KnapsackSearchNode *node = &path.from(); + const KnapsackSearchNode *via = &path.via(); while (node != via) { no_fail = IncrementalUpdate(true, node->assignment()) && no_fail; node = node->parent(); @@ -467,7 +455,7 @@ bool KnapsackGenericSolver::UpdatePropagators(const KnapsackSearchPath& path) { int64 KnapsackGenericSolver::GetAggregatedProfitUpperBound() const { int64 upper_bound = kint64max; - for (KnapsackPropagator* const prop : propagators_) { + for (KnapsackPropagator *const prop : propagators_) { prop->ComputeProfitBounds(); const int64 propagator_upper_bound = prop->profit_upper_bound(); upper_bound = std::min(upper_bound, propagator_upper_bound); @@ -475,7 +463,7 @@ int64 KnapsackGenericSolver::GetAggregatedProfitUpperBound() const { return upper_bound; } -bool KnapsackGenericSolver::MakeNewNode(const KnapsackSearchNode& node, +bool KnapsackGenericSolver::MakeNewNode(const KnapsackSearchNode &node, bool is_in) { if (node.next_item_id() == kNoSelection) { return false; @@ -503,7 +491,7 @@ bool KnapsackGenericSolver::MakeNewNode(const KnapsackSearchNode& node, } // The node is relevant. - KnapsackSearchNode* relevant_node = new KnapsackSearchNode(&node, assignment); + KnapsackSearchNode *relevant_node = new KnapsackSearchNode(&node, assignment); relevant_node->set_current_profit(new_node.current_profit()); relevant_node->set_profit_upper_bound(new_node.profit_upper_bound()); relevant_node->set_next_item_id(new_node.next_item_id()); @@ -512,12 +500,13 @@ bool KnapsackGenericSolver::MakeNewNode(const KnapsackSearchNode& node, return true; } -bool KnapsackGenericSolver::IncrementalUpdate( - bool revert, const KnapsackAssignment& assignment) { +bool +KnapsackGenericSolver::IncrementalUpdate(bool revert, + const KnapsackAssignment &assignment) { // Do not stop on a failure: To be able to be incremental on the update, // partial solution (state) and propagators must all be in the same state. bool no_fail = state_.UpdateState(revert, assignment); - for (KnapsackPropagator* const prop : propagators_) { + for (KnapsackPropagator *const prop : propagators_) { no_fail = prop->Update(revert, assignment) && no_fail; } return no_fail; @@ -531,8 +520,8 @@ void KnapsackGenericSolver::UpdateBestSolution() { if (best_solution_profit_ < profit_lower_bound) { best_solution_profit_ = profit_lower_bound; - propagators_[master_propagator_id_]->CopyCurrentStateToSolution( - HasOnePropagator(), &best_solution_); + propagators_[master_propagator_id_] + ->CopyCurrentStateToSolution(HasOnePropagator(), &best_solution_); } } @@ -542,23 +531,23 @@ void KnapsackGenericSolver::UpdateBestSolution() { // Experiments show better results than KnapsackGenericSolver when the // number of items is less than 15. class KnapsackBruteForceSolver : public BaseKnapsackSolver { - public: - explicit KnapsackBruteForceSolver(const std::string& solver_name); +public: + explicit KnapsackBruteForceSolver(const std::string &solver_name); // Initializes the solver and enters the problem to be solved. - void Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) override; + void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) override; // Solves the problem and returns the profit of the optimal solution. - int64 Solve(TimeLimit* time_limit, bool* is_solution_optimal) override; + int64 Solve(TimeLimit *time_limit, bool *is_solution_optimal) override; // Returns true if the item 'item_id' is packed in the optimal knapsack. bool best_solution(int item_id) const override { return (best_solution_ & OneBit32(item_id)) != 0U; } - private: +private: int num_items_; int64 profits_weights_[kMaxNumberOfBruteForceItems * 2]; int64 capacity_; @@ -569,17 +558,14 @@ class KnapsackBruteForceSolver : public BaseKnapsackSolver { }; KnapsackBruteForceSolver::KnapsackBruteForceSolver( - const std::string& solver_name) - : BaseKnapsackSolver(solver_name), - num_items_(0), - capacity_(0LL), - best_solution_profit_(0LL), - best_solution_(0U) {} + const std::string &solver_name) + : BaseKnapsackSolver(solver_name), num_items_(0), capacity_(0LL), + best_solution_profit_(0LL), best_solution_(0U) {} -void KnapsackBruteForceSolver::Init( - const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { +void +KnapsackBruteForceSolver::Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { // TODO(user): Implement multi-dimensional brute force solver. CHECK_EQ(weights.size(), 1) << "Brute force solver only works with one dimension."; @@ -599,8 +585,8 @@ void KnapsackBruteForceSolver::Init( capacity_ = capacities.at(0); } -int64 KnapsackBruteForceSolver::Solve(TimeLimit* time_limit, - bool* is_solution_optimal) { +int64 KnapsackBruteForceSolver::Solve(TimeLimit *time_limit, + bool *is_solution_optimal) { DCHECK(is_solution_optimal != nullptr); *is_solution_optimal = true; best_solution_profit_ = 0LL; @@ -620,12 +606,12 @@ int64 KnapsackBruteForceSolver::Solve(TimeLimit* time_limit, local_state = state; item_id = 0; while (diff_state) { - if (diff_state & 1U) { // There is a diff. - if (local_state & 1U) { // This item is now in the knapsack. + if (diff_state & 1U) { // There is a diff. + if (local_state & 1U) { // This item is now in the knapsack. sum_profit += profits_weights_[item_id]; sum_weight += profits_weights_[item_id + 1]; CHECK_LT(item_id + 1, 2 * num_items_); - } else { // This item has been removed of the knapsack. + } else { // This item has been removed of the knapsack. sum_profit -= profits_weights_[item_id]; sum_weight -= profits_weights_[item_id + 1]; CHECK_LT(item_id + 1, 2 * num_items_); @@ -654,9 +640,7 @@ int64 KnapsackBruteForceSolver::Solve(TimeLimit* time_limit, struct KnapsackItemWithEfficiency { KnapsackItemWithEfficiency(int _id, int64 _profit, int64 _weight, int64 _profit_max) - : id(_id), - profit(_profit), - weight(_weight), + : id(_id), profit(_profit), weight(_weight), efficiency((weight > 0) ? static_cast(_profit) / static_cast(_weight) : static_cast(_profit_max)) {} @@ -672,25 +656,25 @@ struct KnapsackItemWithEfficiency { // items is less or equal to 64. This implementation is about 4 times faster // than KnapsackGenericSolver. class Knapsack64ItemsSolver : public BaseKnapsackSolver { - public: - explicit Knapsack64ItemsSolver(const std::string& solver_name); +public: + explicit Knapsack64ItemsSolver(const std::string &solver_name); // Initializes the solver and enters the problem to be solved. - void Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) override; + void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) override; // Solves the problem and returns the profit of the optimal solution. - int64 Solve(TimeLimit* time_limit, bool* is_solution_optimal) override; + int64 Solve(TimeLimit *time_limit, bool *is_solution_optimal) override; // Returns true if the item 'item_id' is packed in the optimal knapsack. bool best_solution(int item_id) const override { return (best_solution_ & OneBit64(item_id)) != 0ULL; } - private: +private: int GetBreakItemId(int64 capacity) const; - void GetLowerAndUpperBound(int64* lower_bound, int64* upper_bound) const; + void GetLowerAndUpperBound(int64 *lower_bound, int64 *upper_bound) const; void GoToNextState(bool has_failed); void BuildBestSolution(); @@ -715,30 +699,23 @@ class Knapsack64ItemsSolver : public BaseKnapsackSolver { // Comparator used to sort item in decreasing efficiency order bool CompareKnapsackItemWithEfficiencyInDecreasingEfficiencyOrder( - const KnapsackItemWithEfficiency& item1, - const KnapsackItemWithEfficiency& item2) { + const KnapsackItemWithEfficiency &item1, + const KnapsackItemWithEfficiency &item2) { return item1.efficiency > item2.efficiency; } // ----- Knapsack64ItemsSolver ----- -Knapsack64ItemsSolver::Knapsack64ItemsSolver(const std::string& solver_name) - : BaseKnapsackSolver(solver_name), - sorted_items_(), - sum_profits_(), - sum_weights_(), - capacity_(0LL), - state_(0ULL), - state_depth_(0), - best_solution_profit_(0LL), - best_solution_(0ULL), - best_solution_depth_(0), - state_weight_(0LL), - rejected_items_profit_(0LL), +Knapsack64ItemsSolver::Knapsack64ItemsSolver(const std::string &solver_name) + : BaseKnapsackSolver(solver_name), sorted_items_(), sum_profits_(), + sum_weights_(), capacity_(0LL), state_(0ULL), state_depth_(0), + best_solution_profit_(0LL), best_solution_(0ULL), best_solution_depth_(0), + state_weight_(0LL), rejected_items_profit_(0LL), rejected_items_weight_(0LL) {} -void Knapsack64ItemsSolver::Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { +void +Knapsack64ItemsSolver::Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { CHECK_EQ(weights.size(), 1) << "Brute force solver only works with one dimension."; CHECK_EQ(capacities.size(), weights.size()); @@ -776,8 +753,8 @@ void Knapsack64ItemsSolver::Init(const std::vector& profits, } } -int64 Knapsack64ItemsSolver::Solve(TimeLimit* time_limit, - bool* is_solution_optimal) { +int64 Knapsack64ItemsSolver::Solve(TimeLimit *time_limit, + bool *is_solution_optimal) { DCHECK(is_solution_optimal != nullptr); *is_solution_optimal = true; const int num_items = sorted_items_.size(); @@ -826,8 +803,8 @@ int Knapsack64ItemsSolver::GetBreakItemId(int64 capacity) const { // Unfortunately, experiments show equivalent results with or without this // code optimization (only 1/7 of calls can be reused). // In order to simplify the code, this optimization is not implemented. -void Knapsack64ItemsSolver::GetLowerAndUpperBound(int64* lower_bound, - int64* upper_bound) const { +void Knapsack64ItemsSolver::GetLowerAndUpperBound(int64 *lower_bound, + int64 *upper_bound) const { const int64 available_capacity = capacity_ + rejected_items_weight_; const int break_item_id = GetBreakItemId(available_capacity); const int num_items = sorted_items_.size(); @@ -854,23 +831,23 @@ void Knapsack64ItemsSolver::GetLowerAndUpperBound(int64* lower_bound, // (10% speed-up). That's the reason why the loop version is implemented. void Knapsack64ItemsSolver::GoToNextState(bool has_failed) { uint64 mask = OneBit64(state_depth_); - if (!has_failed) { // Go to next item. + if (!has_failed) { // Go to next item. ++state_depth_; state_ = state_ | (mask << 1); state_weight_ += sorted_items_[state_depth_].weight; } else { // Backtrack to last item in. while ((state_ & mask) == 0ULL && state_depth_ >= 0) { - const KnapsackItemWithEfficiency& item = sorted_items_[state_depth_]; + const KnapsackItemWithEfficiency &item = sorted_items_[state_depth_]; rejected_items_profit_ -= item.profit; rejected_items_weight_ -= item.weight; --state_depth_; mask = mask >> 1ULL; } - if (state_ & mask) { // Item was in, remove it. + if (state_ & mask) { // Item was in, remove it. state_ = state_ & ~mask; - const KnapsackItemWithEfficiency& item = sorted_items_[state_depth_]; + const KnapsackItemWithEfficiency &item = sorted_items_[state_depth_]; rejected_items_profit_ += item.profit; rejected_items_weight_ += item.weight; state_weight_ -= item.weight; @@ -928,23 +905,23 @@ void Knapsack64ItemsSolver::BuildBestSolution() { // The implemented algorithm is 'DP-3' in "Knapsack problems", Hans Kellerer, // Ulrich Pferschy and David Pisinger, Springer book (ISBN 978-3540402862). class KnapsackDynamicProgrammingSolver : public BaseKnapsackSolver { - public: - explicit KnapsackDynamicProgrammingSolver(const std::string& solver_name); +public: + explicit KnapsackDynamicProgrammingSolver(const std::string &solver_name); // Initializes the solver and enters the problem to be solved. - void Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) override; + void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) override; // Solves the problem and returns the profit of the optimal solution. - int64 Solve(TimeLimit* time_limit, bool* is_solution_optimal) override; + int64 Solve(TimeLimit *time_limit, bool *is_solution_optimal) override; // Returns true if the item 'item_id' is packed in the optimal knapsack. bool best_solution(int item_id) const override { return best_solution_.at(item_id); } - private: +private: int64 SolveSubProblem(int64 capacity, int num_items); std::vector profits_; @@ -957,19 +934,14 @@ class KnapsackDynamicProgrammingSolver : public BaseKnapsackSolver { // ----- KnapsackDynamicProgrammingSolver ----- KnapsackDynamicProgrammingSolver::KnapsackDynamicProgrammingSolver( - const std::string& solver_name) - : BaseKnapsackSolver(solver_name), - profits_(), - weights_(), - capacity_(0), - computed_profits_(), - selected_item_ids_(), - best_solution_() {} + const std::string &solver_name) + : BaseKnapsackSolver(solver_name), profits_(), weights_(), capacity_(0), + computed_profits_(), selected_item_ids_(), best_solution_() {} void KnapsackDynamicProgrammingSolver::Init( - const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { + const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { CHECK_EQ(weights.size(), 1) << "Current implementation of the dynamic programming solver only deals" << " with one dimension."; @@ -984,7 +956,9 @@ int64 KnapsackDynamicProgrammingSolver::SolveSubProblem(int64 capacity, int num_items) { const int64 capacity_plus_1 = capacity + 1; std::fill_n(selected_item_ids_.begin(), capacity_plus_1, 0); - std::fill_n(computed_profits_.begin(), capacity_plus_1, int64{0}); + std::fill_n(computed_profits_.begin(), capacity_plus_1, int64 { + 0 + }); for (int item_id = 0; item_id < num_items; ++item_id) { const int64 item_weight = weights_[item_id]; const int64 item_profit = profits_[item_id]; @@ -1001,8 +975,8 @@ int64 KnapsackDynamicProgrammingSolver::SolveSubProblem(int64 capacity, return selected_item_ids_.at(capacity); } -int64 KnapsackDynamicProgrammingSolver::Solve(TimeLimit* time_limit, - bool* is_solution_optimal) { +int64 KnapsackDynamicProgrammingSolver::Solve(TimeLimit *time_limit, + bool *is_solution_optimal) { DCHECK(is_solution_optimal != nullptr); *is_solution_optimal = true; const int64 capacity_plus_1 = capacity_ + 1; @@ -1027,57 +1001,53 @@ int64 KnapsackDynamicProgrammingSolver::Solve(TimeLimit* time_limit, // ----- KnapsackMIPSolver ----- class KnapsackMIPSolver : public BaseKnapsackSolver { - public: +public: KnapsackMIPSolver(MPSolver::OptimizationProblemType problem_type, - const std::string& solver_name); + const std::string &solver_name); // Initializes the solver and enters the problem to be solved. - void Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) override; + void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) override; // Solves the problem and returns the profit of the optimal solution. - int64 Solve(TimeLimit* time_limit, bool* is_solution_optimal) override; + int64 Solve(TimeLimit *time_limit, bool *is_solution_optimal) override; // Returns true if the item 'item_id' is packed in the optimal knapsack. bool best_solution(int item_id) const override { return best_solution_.at(item_id); } - private: +private: MPSolver::OptimizationProblemType problem_type_; std::vector profits_; - std::vector> weights_; + std::vector > weights_; std::vector capacities_; std::vector best_solution_; }; KnapsackMIPSolver::KnapsackMIPSolver( MPSolver::OptimizationProblemType problem_type, - const std::string& solver_name) - : BaseKnapsackSolver(solver_name), - problem_type_(problem_type), - profits_(), - weights_(), - capacities_(), - best_solution_() {} + const std::string &solver_name) + : BaseKnapsackSolver(solver_name), problem_type_(problem_type), profits_(), + weights_(), capacities_(), best_solution_() {} -void KnapsackMIPSolver::Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { +void KnapsackMIPSolver::Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { profits_ = profits; weights_ = weights; capacities_ = capacities; } -int64 KnapsackMIPSolver::Solve(TimeLimit* time_limit, - bool* is_solution_optimal) { +int64 KnapsackMIPSolver::Solve(TimeLimit *time_limit, + bool *is_solution_optimal) { DCHECK(is_solution_optimal != nullptr); *is_solution_optimal = true; MPSolver solver(GetName(), problem_type_); const int num_items = profits_.size(); - std::vector variables; + std::vector variables; solver.MakeBoolVarArray(num_items, "x", &variables); // Add constraints. @@ -1086,7 +1056,7 @@ int64 KnapsackMIPSolver::Solve(TimeLimit* time_limit, << "Weights should be vector of num_dimensions (" << num_dimensions << ") vectors of size num_items (" << num_items << ")."; for (int i = 0; i < num_dimensions; ++i) { - MPConstraint* const ct = solver.MakeRowConstraint(0LL, capacities_.at(i)); + MPConstraint *const ct = solver.MakeRowConstraint(0LL, capacities_.at(i)); for (int j = 0; j < num_items; ++j) { ct->SetCoefficient(variables.at(j), weights_.at(i).at(j)); } @@ -1095,7 +1065,7 @@ int64 KnapsackMIPSolver::Solve(TimeLimit* time_limit, // Define objective to minimize. Minimization is used instead of maximization // because of an issue with CBC solver which does not always find the optimal // solution on maximization problems. - MPObjective* const objective = solver.MutableObjective(); + MPObjective *const objective = solver.MutableObjective(); for (int j = 0; j < num_items; ++j) { objective->SetCoefficient(variables.at(j), -profits_.at(j)); } @@ -1116,75 +1086,69 @@ int64 KnapsackMIPSolver::Solve(TimeLimit* time_limit, } // ----- KnapsackSolver ----- -KnapsackSolver::KnapsackSolver(const std::string& solver_name) +KnapsackSolver::KnapsackSolver(const std::string &solver_name) : KnapsackSolver(KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, solver_name) {} KnapsackSolver::KnapsackSolver(SolverType solver_type, - const std::string& solver_name) - : solver_(), - known_value_(), - best_solution_(), - mapping_reduced_item_id_(), - is_problem_solved_(false), - additional_profit_(0LL), - use_reduction_(true), + const std::string &solver_name) + : solver_(), known_value_(), best_solution_(), mapping_reduced_item_id_(), + is_problem_solved_(false), additional_profit_(0LL), use_reduction_(true), time_limit_seconds_(std::numeric_limits::infinity()) { switch (solver_type) { - case KNAPSACK_BRUTE_FORCE_SOLVER: - solver_ = absl::make_unique(solver_name); - break; - case KNAPSACK_64ITEMS_SOLVER: - solver_ = absl::make_unique(solver_name); - break; - case KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER: - solver_ = - absl::make_unique(solver_name); - break; - case KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER: - solver_ = absl::make_unique(solver_name); - break; + case KNAPSACK_BRUTE_FORCE_SOLVER: + solver_ = absl::make_unique(solver_name); + break; + case KNAPSACK_64ITEMS_SOLVER: + solver_ = absl::make_unique(solver_name); + break; + case KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER: + solver_ = absl::make_unique(solver_name); + break; + case KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER: + solver_ = absl::make_unique(solver_name); + break; #if defined(USE_CBC) - case KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER: - solver_ = absl::make_unique( - MPSolver::CBC_MIXED_INTEGER_PROGRAMMING, solver_name); - break; -#endif // USE_CBC + case KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER: + solver_ = absl::make_unique( + MPSolver::CBC_MIXED_INTEGER_PROGRAMMING, solver_name); + break; +#endif // USE_CBC #if defined(USE_SCIP) - case KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER: - solver_ = absl::make_unique( - MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING, solver_name); - break; -#endif // USE_SCIP + case KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER: + solver_ = absl::make_unique( + MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING, solver_name); + break; +#endif // USE_SCIP #if defined(USE_XPRESS) - case KNAPSACK_MULTIDIMENSION_XPRESS_MIP_SOLVER: - solver_ = absl::make_unique( - MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING, solver_name); - break; + case KNAPSACK_MULTIDIMENSION_XPRESS_MIP_SOLVER: + solver_ = absl::make_unique( + MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING, solver_name); + break; #endif #if defined(USE_CPLEX) - case KNAPSACK_MULTIDIMENSION_CPLEX_MIP_SOLVER: - solver_ = absl::make_unique( - MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING, solver_name); - break; + case KNAPSACK_MULTIDIMENSION_CPLEX_MIP_SOLVER: + solver_ = absl::make_unique( + MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING, solver_name); + break; #endif - default: - LOG(FATAL) << "Unknown knapsack solver type."; + default: + LOG(FATAL) << "Unknown knapsack solver type."; } } KnapsackSolver::~KnapsackSolver() {} -void KnapsackSolver::Init(const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { +void KnapsackSolver::Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { time_limit_ = absl::make_unique(time_limit_seconds_); is_solution_optimal_ = false; additional_profit_ = 0LL; is_problem_solved_ = false; const int num_items = profits.size(); - std::vector> reduced_weights; + std::vector > reduced_weights; std::vector reduced_capacities; if (use_reduction_) { const int num_reduced_items = ReduceCapacities( @@ -1216,10 +1180,10 @@ void KnapsackSolver::Init(const std::vector& profits, } int KnapsackSolver::ReduceCapacities( - int num_items, const std::vector>& weights, - const std::vector& capacities, - std::vector>* reduced_weights, - std::vector* reduced_capacities) { + int num_items, const std::vector > &weights, + const std::vector &capacities, + std::vector > *reduced_weights, + std::vector *reduced_capacities) { known_value_.assign(num_items, false); best_solution_.assign(num_items, false); mapping_reduced_item_id_.assign(num_items, 0); @@ -1306,8 +1270,8 @@ int KnapsackSolver::ReduceProblem(int num_items) { return num_reduced_items; } -void KnapsackSolver::ComputeAdditionalProfit( - const std::vector& profits) { +void +KnapsackSolver::ComputeAdditionalProfit(const std::vector &profits) { const int num_items = profits.size(); additional_profit_ = 0LL; for (int item_id = 0; item_id < num_items; ++item_id) { @@ -1318,9 +1282,9 @@ void KnapsackSolver::ComputeAdditionalProfit( } void KnapsackSolver::InitReducedProblem( - const std::vector& profits, - const std::vector>& weights, - const std::vector& capacities) { + const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) { const int num_items = profits.size(); const int num_dimensions = capacities.size(); @@ -1332,10 +1296,10 @@ void KnapsackSolver::InitReducedProblem( } } - std::vector> reduced_weights; + std::vector > reduced_weights; std::vector reduced_capacities = capacities; for (int dim = 0; dim < num_dimensions; ++dim) { - const std::vector& one_dimension_weights = weights[dim]; + const std::vector &one_dimension_weights = weights[dim]; std::vector one_dimension_reduced_weights; for (int item_id = 0; item_id < num_items; ++item_id) { if (known_value_[item_id]) { @@ -1353,9 +1317,8 @@ void KnapsackSolver::InitReducedProblem( int64 KnapsackSolver::Solve() { return additional_profit_ + - ((is_problem_solved_) - ? 0 - : solver_->Solve(time_limit_.get(), &is_solution_optimal_)); + ((is_problem_solved_) ? 0 : solver_->Solve(time_limit_.get(), + &is_solution_optimal_)); } bool KnapsackSolver::BestSolutionContains(int item_id) const { @@ -1371,12 +1334,12 @@ std::string KnapsackSolver::GetName() const { return solver_->GetName(); } // ----- BaseKnapsackSolver ----- void BaseKnapsackSolver::GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, - int64* lower_bound, - int64* upper_bound) { + int64 *lower_bound, + int64 *upper_bound) { CHECK(lower_bound != nullptr); CHECK(upper_bound != nullptr); *lower_bound = 0LL; *upper_bound = kint64max; } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/knapsack_solver.h b/ortools/algorithms/knapsack_solver.h index ea2a8223ee..fa8a8827c4 100644 --- a/ortools/algorithms/knapsack_solver.h +++ b/ortools/algorithms/knapsack_solver.h @@ -118,7 +118,7 @@ class BaseKnapsackSolver; */ class KnapsackSolver { - public: +public: /** Enum controlling which underlying algorithm is used. * * This enum is passed to the constructor of the KnapsackSolver object. @@ -156,7 +156,7 @@ class KnapsackSolver { * dimensions. This solver is based on Integer Programming solver CBC. */ KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER = 3, -#endif // USE_CBC +#endif // USE_CBC /** Generic Solver. * @@ -172,7 +172,7 @@ class KnapsackSolver { * dimensions. This solver is based on Integer Programming solver SCIP. */ KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER = 6, -#endif // USE_SCIP +#endif // USE_SCIP #if defined(USE_XPRESS) /** XPRESS based solver @@ -193,16 +193,16 @@ class KnapsackSolver { #endif }; - explicit KnapsackSolver(const std::string& solver_name); - KnapsackSolver(SolverType solver_type, const std::string& solver_name); + explicit KnapsackSolver(const std::string &solver_name); + KnapsackSolver(SolverType solver_type, const std::string &solver_name); virtual ~KnapsackSolver(); /** * Initializes the solver and enters the problem to be solved. */ - void Init(const std::vector& profits, - const std::vector >& weights, - const std::vector& capacities); + void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities); /** * Solves the problem and returns the profit of the optimal solution. @@ -232,19 +232,19 @@ class KnapsackSolver { time_limit_ = absl::make_unique(time_limit_seconds_); } - private: +private: // Trivial reduction of capacity constraints when the capacity is higher than // the sum of the weights of the items. Returns the number of reduced items. int ReduceCapacities(int num_items, - const std::vector >& weights, - const std::vector& capacities, - std::vector >* reduced_weights, - std::vector* reduced_capacities); + const std::vector > &weights, + const std::vector &capacities, + std::vector > *reduced_weights, + std::vector *reduced_capacities); int ReduceProblem(int num_items); - void ComputeAdditionalProfit(const std::vector& profits); - void InitReducedProblem(const std::vector& profits, - const std::vector >& weights, - const std::vector& capacities); + void ComputeAdditionalProfit(const std::vector &profits); + void InitReducedProblem(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities); std::unique_ptr solver_; std::vector known_value_; @@ -321,7 +321,7 @@ struct KnapsackItem { const int64 weight; const int64 profit; }; -typedef KnapsackItem* KnapsackItemPtr; +typedef KnapsackItem *KnapsackItemPtr; // ----- KnapsackSearchNode ----- // KnapsackSearchNode is a class used to describe a decision in the decision @@ -332,12 +332,12 @@ typedef KnapsackItem* KnapsackItemPtr; // go through the search tree to incrementally build a partial solution from // a previous search node. class KnapsackSearchNode { - public: - KnapsackSearchNode(const KnapsackSearchNode* const parent, - const KnapsackAssignment& assignment); +public: + KnapsackSearchNode(const KnapsackSearchNode *const parent, + const KnapsackAssignment &assignment); int depth() const { return depth_; } - const KnapsackSearchNode* const parent() const { return parent_; } - const KnapsackAssignment& assignment() const { return assignment_; } + const KnapsackSearchNode *const parent() const { return parent_; } + const KnapsackAssignment &assignment() const { return assignment_; } int64 current_profit() const { return current_profit_; } void set_current_profit(int64 profit) { current_profit_ = profit; } @@ -348,11 +348,11 @@ class KnapsackSearchNode { int next_item_id() const { return next_item_id_; } void set_next_item_id(int id) { next_item_id_ = id; } - private: +private: // 'depth' field is used to navigate efficiently through the search tree // (see KnapsackSearchPath). int depth_; - const KnapsackSearchNode* const parent_; + const KnapsackSearchNode *const parent_; KnapsackAssignment assignment_; // 'current_profit' and 'profit_upper_bound' fields are used to sort search @@ -386,20 +386,20 @@ class KnapsackSearchNode { // So the state can be built by reverting all decisions from 'from' to 'via' // and then applying all decisions from 'via' to 'to'. class KnapsackSearchPath { - public: - KnapsackSearchPath(const KnapsackSearchNode& from, - const KnapsackSearchNode& to); +public: + KnapsackSearchPath(const KnapsackSearchNode &from, + const KnapsackSearchNode &to); void Init(); - const KnapsackSearchNode& from() const { return from_; } - const KnapsackSearchNode& via() const { return *via_; } - const KnapsackSearchNode& to() const { return to_; } - const KnapsackSearchNode* MoveUpToDepth(const KnapsackSearchNode& node, + const KnapsackSearchNode &from() const { return from_; } + const KnapsackSearchNode &via() const { return *via_; } + const KnapsackSearchNode &to() const { return to_; } + const KnapsackSearchNode *MoveUpToDepth(const KnapsackSearchNode &node, int depth) const; - private: - const KnapsackSearchNode& from_; - const KnapsackSearchNode* via_; // Computed in 'Init'. - const KnapsackSearchNode& to_; +private: + const KnapsackSearchNode &from_; + const KnapsackSearchNode *via_; // Computed in 'Init'. + const KnapsackSearchNode &to_; DISALLOW_COPY_AND_ASSIGN(KnapsackSearchPath); }; @@ -407,7 +407,7 @@ class KnapsackSearchPath { // ----- KnapsackState ----- // KnapsackState represents a partial solution to the knapsack problem. class KnapsackState { - public: +public: KnapsackState(); // Initializes vectors with number_of_items set to false (i.e. not bound yet). @@ -415,13 +415,13 @@ class KnapsackState { // Updates the state by applying or reverting a decision. // Returns false if fails, i.e. trying to apply an inconsistent decision // to an already assigned item. - bool UpdateState(bool revert, const KnapsackAssignment& assignment); + bool UpdateState(bool revert, const KnapsackAssignment &assignment); int GetNumberOfItems() const { return is_bound_.size(); } bool is_bound(int id) const { return is_bound_.at(id); } bool is_in(int id) const { return is_in_.at(id); } - private: +private: // Vectors 'is_bound_' and 'is_in_' contain a boolean value for each item. // 'is_bound_(item_i)' is false when there is no decision for item_i yet. // When item_i is bound, 'is_in_(item_i)' represents the presence (true) or @@ -441,17 +441,17 @@ class KnapsackState { // For instance, 'Init' creates a vector of items, and then calls // 'InitPropagator' to let the derived class perform its own initialization. class KnapsackPropagator { - public: - explicit KnapsackPropagator(const KnapsackState& state); +public: + explicit KnapsackPropagator(const KnapsackState &state); virtual ~KnapsackPropagator(); // Initializes data structure and then calls InitPropagator. - void Init(const std::vector& profits, - const std::vector& weights); + void Init(const std::vector &profits, + const std::vector &weights); // Updates data structure and then calls UpdatePropagator. // Returns false when failure. - bool Update(bool revert, const KnapsackAssignment& assignment); + bool Update(bool revert, const KnapsackAssignment &assignment); // ComputeProfitBounds should set 'profit_lower_bound_' and // 'profit_upper_bound_' which are constraint specific. virtual void ComputeProfitBounds() = 0; @@ -470,9 +470,9 @@ class KnapsackPropagator { // there is no need to check the solution with other propagators, so the // partial solution can be smartly completed. void CopyCurrentStateToSolution(bool has_one_propagator, - std::vector* solution) const; + std::vector *solution) const; - protected: +protected: // Initializes data structure. This method is called after initialization // of KnapsackPropagator data structure. virtual void InitPropagator() = 0; @@ -480,7 +480,7 @@ class KnapsackPropagator { // Updates internal data structure incrementally. This method is called // after update of KnapsackPropagator data structure. virtual bool UpdatePropagator(bool revert, - const KnapsackAssignment& assignment) = 0; + const KnapsackAssignment &assignment) = 0; // Copies the current state into 'solution'. // Only unbound items have to be copied as CopyCurrentSolution was already @@ -488,20 +488,20 @@ class KnapsackPropagator { // This method is useful when a propagator is able to find a better solution // than the blind instantiation to false of unbound items. virtual void CopyCurrentStateToSolutionPropagator( - std::vector* solution) const = 0; + std::vector *solution) const = 0; - const KnapsackState& state() const { return state_; } - const std::vector& items() const { return items_; } + const KnapsackState &state() const { return state_; } + const std::vector &items() const { return items_; } void set_profit_lower_bound(int64 profit) { profit_lower_bound_ = profit; } void set_profit_upper_bound(int64 profit) { profit_upper_bound_ = profit; } - private: +private: std::vector items_; int64 current_profit_; int64 profit_lower_bound_; int64 profit_upper_bound_; - const KnapsackState& state_; + const KnapsackState &state_; DISALLOW_COPY_AND_ASSIGN(KnapsackPropagator); }; @@ -527,24 +527,24 @@ class KnapsackPropagator { // For incrementality reasons, the ith item should be accessible in O(1). That's // the reason why the item vector has to be duplicated 'sorted_items_'. class KnapsackCapacityPropagator : public KnapsackPropagator { - public: - KnapsackCapacityPropagator(const KnapsackState& state, int64 capacity); +public: + KnapsackCapacityPropagator(const KnapsackState &state, int64 capacity); ~KnapsackCapacityPropagator() override; void ComputeProfitBounds() override; int GetNextItemId() const override { return break_item_id_; } - protected: +protected: // Initializes KnapsackCapacityPropagator (e.g., sort items in decreasing // order). void InitPropagator() override; // Updates internal data structure incrementally (i.e., 'consumed_capacity_') // to avoid a O(number_of_items) scan. - bool UpdatePropagator(bool revert, - const KnapsackAssignment& assignment) override; - void CopyCurrentStateToSolutionPropagator( - std::vector* solution) const override; + bool UpdatePropagator(bool revert, const KnapsackAssignment &assignment) + override; + void CopyCurrentStateToSolutionPropagator(std::vector *solution) const + override; - private: +private: // An obvious additional profit upper bound corresponds to the linear // relaxation: remaining_capacity * efficiency of the break item. // It is possible to do better in O(1), using Martello-Toth bound U2. @@ -567,32 +567,32 @@ class KnapsackCapacityPropagator : public KnapsackPropagator { // ----- BaseKnapsackSolver ----- // This is the base class for knapsack solvers. class BaseKnapsackSolver { - public: - explicit BaseKnapsackSolver(const std::string& solver_name) +public: + explicit BaseKnapsackSolver(const std::string &solver_name) : solver_name_(solver_name) {} virtual ~BaseKnapsackSolver() {} // Initializes the solver and enters the problem to be solved. - virtual void Init(const std::vector& profits, - const std::vector >& weights, - const std::vector& capacities) = 0; + virtual void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) = 0; // Gets the lower and upper bound when the item is in or out of the knapsack. // To ensure objects are correctly initialized, this method should not be // called before ::Init. virtual void GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, - int64* lower_bound, - int64* upper_bound); + int64 *lower_bound, + int64 *upper_bound); // Solves the problem and returns the profit of the optimal solution. - virtual int64 Solve(TimeLimit* time_limit, bool* is_solution_optimal) = 0; + virtual int64 Solve(TimeLimit *time_limit, bool *is_solution_optimal) = 0; // Returns true if the item 'item_id' is packed in the optimal knapsack. virtual bool best_solution(int item_id) const = 0; virtual std::string GetName() const { return solver_name_; } - private: +private: const std::string solver_name_; }; @@ -606,18 +606,18 @@ class BaseKnapsackSolver { // an aggregated propagator to combine all dimensions and give a better guide // to select the next item (see, for instance, Dobson's aggregated efficiency). class KnapsackGenericSolver : public BaseKnapsackSolver { - public: - explicit KnapsackGenericSolver(const std::string& solver_name); +public: + explicit KnapsackGenericSolver(const std::string &solver_name); ~KnapsackGenericSolver() override; // Initializes the solver and enters the problem to be solved. - void Init(const std::vector& profits, - const std::vector >& weights, - const std::vector& capacities) override; + void Init(const std::vector &profits, + const std::vector > &weights, + const std::vector &capacities) override; int GetNumberOfItems() const { return state_.GetNumberOfItems(); } void GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, - int64* lower_bound, - int64* upper_bound) override; + int64 *lower_bound, int64 *upper_bound) + override; // Sets which propagator should be used to guide the search. // 'master_propagator_id' should be in 0..p-1 with p the number of @@ -627,30 +627,30 @@ class KnapsackGenericSolver : public BaseKnapsackSolver { } // Solves the problem and returns the profit of the optimal solution. - int64 Solve(TimeLimit* time_limit, bool* is_solution_optimal) override; + int64 Solve(TimeLimit *time_limit, bool *is_solution_optimal) override; // Returns true if the item 'item_id' is packed in the optimal knapsack. bool best_solution(int item_id) const override { return best_solution_.at(item_id); } - private: +private: // Clears internal data structure. void Clear(); // Updates all propagators reverting/applying all decision on the path. // Returns true if fails. Note that, even if fails, all propagators should // be updated to be in a stable state in order to stay incremental. - bool UpdatePropagators(const KnapsackSearchPath& path); + bool UpdatePropagators(const KnapsackSearchPath &path); // Updates all propagators reverting/applying one decision. // Return true if fails. Note that, even if fails, all propagators should // be updated to be in a stable state in order to stay incremental. - bool IncrementalUpdate(bool revert, const KnapsackAssignment& assignment); + bool IncrementalUpdate(bool revert, const KnapsackAssignment &assignment); // Updates the best solution if the current solution has a better profit. void UpdateBestSolution(); // Returns true if new relevant search node was added to the nodes array, that // means this node should be added to the search queue too. - bool MakeNewNode(const KnapsackSearchNode& node, bool is_in); + bool MakeNewNode(const KnapsackSearchNode &node, bool is_in); // Gets the aggregated (min) profit upper bound among all propagators. int64 GetAggregatedProfitUpperBound() const; @@ -662,16 +662,16 @@ class KnapsackGenericSolver : public BaseKnapsackSolver { return propagators_.at(master_propagator_id_)->GetNextItemId(); } - std::vector propagators_; + std::vector propagators_; int master_propagator_id_; - std::vector search_nodes_; + std::vector search_nodes_; KnapsackState state_; int64 best_solution_profit_; std::vector best_solution_; DISALLOW_COPY_AND_ASSIGN(KnapsackGenericSolver); }; -#endif // SWIG -} // namespace operations_research +#endif // SWIG +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_ +#endif // OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_ diff --git a/ortools/algorithms/knapsack_solver_for_cuts.cc b/ortools/algorithms/knapsack_solver_for_cuts.cc index 842a0fe1f6..2729f54f40 100644 --- a/ortools/algorithms/knapsack_solver_for_cuts.cc +++ b/ortools/algorithms/knapsack_solver_for_cuts.cc @@ -31,8 +31,8 @@ const double kInfinity = std::numeric_limits::infinity(); struct CompareKnapsackItemsInDecreasingEfficiencyOrder { explicit CompareKnapsackItemsInDecreasingEfficiencyOrder(double _profit_max) : profit_max(_profit_max) {} - bool operator()(const KnapsackItemForCutsPtr& item1, - const KnapsackItemForCutsPtr& item2) const { + bool operator()(const KnapsackItemForCutsPtr &item1, + const KnapsackItemForCutsPtr &item2) const { return item1->GetEfficiency(profit_max) > item2->GetEfficiency(profit_max); } const double profit_max; @@ -44,8 +44,8 @@ struct CompareKnapsackItemsInDecreasingEfficiencyOrder { // prefer the one with the highest current profit. This is usually the one // closer to a leaf. In practice, the main advantage is to have smaller path. struct CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder { - bool operator()(const KnapsackSearchNodeForCuts* node_1, - const KnapsackSearchNodeForCuts* node_2) const { + bool operator()(const KnapsackSearchNodeForCuts *node_1, + const KnapsackSearchNodeForCuts *node_2) const { const double profit_upper_bound_1 = node_1->profit_upper_bound(); const double profit_upper_bound_2 = node_2->profit_upper_bound(); if (profit_upper_bound_1 == profit_upper_bound_2) { @@ -56,31 +56,28 @@ struct CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder { }; using SearchQueue = std::priority_queue< - KnapsackSearchNodeForCuts*, std::vector, + KnapsackSearchNodeForCuts *, std::vector, CompareKnapsackSearchNodePtrInDecreasingUpperBoundOrder>; -} // namespace +} // namespace // ----- KnapsackSearchNodeForCuts ----- KnapsackSearchNodeForCuts::KnapsackSearchNodeForCuts( - const KnapsackSearchNodeForCuts* const parent, - const KnapsackAssignmentForCuts& assignment) - : depth_(parent == nullptr ? 0 : parent->depth() + 1), - parent_(parent), - assignment_(assignment), - current_profit_(0), - profit_upper_bound_(kInfinity), - next_item_id_(kNoSelection) {} + const KnapsackSearchNodeForCuts *const parent, + const KnapsackAssignmentForCuts &assignment) + : depth_(parent == nullptr ? 0 : parent->depth() + 1), parent_(parent), + assignment_(assignment), current_profit_(0), + profit_upper_bound_(kInfinity), next_item_id_(kNoSelection) {} // ----- KnapsackSearchPathForCuts ----- KnapsackSearchPathForCuts::KnapsackSearchPathForCuts( - const KnapsackSearchNodeForCuts* from, const KnapsackSearchNodeForCuts* to) + const KnapsackSearchNodeForCuts *from, const KnapsackSearchNodeForCuts *to) : from_(from), via_(nullptr), to_(to) {} void KnapsackSearchPathForCuts::Init() { - const KnapsackSearchNodeForCuts* node_from = + const KnapsackSearchNodeForCuts *node_from = MoveUpToDepth(from_, to_->depth()); - const KnapsackSearchNodeForCuts* node_to = MoveUpToDepth(to_, from_->depth()); + const KnapsackSearchNodeForCuts *node_to = MoveUpToDepth(to_, from_->depth()); DCHECK_EQ(node_from->depth(), node_to->depth()); // Find common parent. @@ -91,8 +88,8 @@ void KnapsackSearchPathForCuts::Init() { via_ = node_from; } -const KnapsackSearchNodeForCuts* MoveUpToDepth( - const KnapsackSearchNodeForCuts* node, int depth) { +const KnapsackSearchNodeForCuts * +MoveUpToDepth(const KnapsackSearchNodeForCuts *node, int depth) { while (node->depth() > depth) { node = node->parent(); } @@ -108,8 +105,9 @@ void KnapsackStateForCuts::Init(int number_of_items) { } // Returns false when the state is invalid. -bool KnapsackStateForCuts::UpdateState( - bool revert, const KnapsackAssignmentForCuts& assignment) { +bool +KnapsackStateForCuts::UpdateState(bool revert, + const KnapsackAssignmentForCuts &assignment) { if (revert) { is_bound_[assignment.item_id] = false; } else { @@ -125,17 +123,14 @@ bool KnapsackStateForCuts::UpdateState( // ----- KnapsackPropagatorForCuts ----- KnapsackPropagatorForCuts::KnapsackPropagatorForCuts( - const KnapsackStateForCuts* state) - : items_(), - current_profit_(0), - profit_lower_bound_(0), - profit_upper_bound_(kInfinity), - state_(state) {} + const KnapsackStateForCuts *state) + : items_(), current_profit_(0), profit_lower_bound_(0), + profit_upper_bound_(kInfinity), state_(state) {} KnapsackPropagatorForCuts::~KnapsackPropagatorForCuts() {} -void KnapsackPropagatorForCuts::Init(const std::vector& profits, - const std::vector& weights, +void KnapsackPropagatorForCuts::Init(const std::vector &profits, + const std::vector &weights, const double capacity) { const int number_of_items = profits.size(); items_.clear(); @@ -151,8 +146,9 @@ void KnapsackPropagatorForCuts::Init(const std::vector& profits, InitPropagator(); } -bool KnapsackPropagatorForCuts::Update( - bool revert, const KnapsackAssignmentForCuts& assignment) { +bool +KnapsackPropagatorForCuts::Update(bool revert, + const KnapsackAssignmentForCuts &assignment) { if (assignment.is_in) { if (revert) { current_profit_ -= items_[assignment.item_id]->profit; @@ -169,14 +165,14 @@ bool KnapsackPropagatorForCuts::Update( } void KnapsackPropagatorForCuts::CopyCurrentStateToSolution( - std::vector* solution) const { + std::vector *solution) const { DCHECK(solution != nullptr); for (int i(0); i < items_.size(); ++i) { const int item_id = items_[i]->id; (*solution)[item_id] = state_->is_bound(item_id) && state_->is_in(item_id); } double remaining_capacity = capacity_ - consumed_capacity_; - for (const KnapsackItemForCutsPtr& item : sorted_items_) { + for (const KnapsackItemForCutsPtr &item : sorted_items_) { if (!state().is_bound(item->id)) { if (remaining_capacity >= item->weight) { remaining_capacity -= item->weight; @@ -196,7 +192,7 @@ void KnapsackPropagatorForCuts::ComputeProfitBounds() { int break_sorted_item_id = kNoSelection; for (int sorted_id(0); sorted_id < sorted_items_.size(); ++sorted_id) { if (!state().is_bound(sorted_items_[sorted_id]->id)) { - const KnapsackItemForCutsPtr& item = sorted_items_[sorted_id]; + const KnapsackItemForCutsPtr &item = sorted_items_[sorted_id]; break_item_id_ = item->id; if (remaining_capacity >= item->weight) { remaining_capacity -= item->weight; @@ -231,7 +227,7 @@ void KnapsackPropagatorForCuts::InitPropagator() { i, items()[i]->weight, items()[i]->profit)); } profit_max_ = 0; - for (const KnapsackItemForCutsPtr& item : sorted_items_) { + for (const KnapsackItemForCutsPtr &item : sorted_items_) { profit_max_ = std::max(profit_max_, item->profit); } profit_max_ += 1.0; @@ -279,12 +275,11 @@ double KnapsackPropagatorForCuts::GetAdditionalProfitUpperBound( // ----- KnapsackSolverForCuts ----- KnapsackSolverForCuts::KnapsackSolverForCuts(std::string solver_name) - : propagator_(&state_), - best_solution_profit_(0), + : propagator_(&state_), best_solution_profit_(0), solver_name_(std::move(solver_name)) {} -void KnapsackSolverForCuts::Init(const std::vector& profits, - const std::vector& weights, +void KnapsackSolverForCuts::Init(const std::vector &profits, + const std::vector &weights, const double capacity) { const int number_of_items(profits.size()); state_.Init(number_of_items); @@ -296,8 +291,8 @@ void KnapsackSolverForCuts::Init(const std::vector& profits, void KnapsackSolverForCuts::GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, - double* lower_bound, - double* upper_bound) { + double *lower_bound, + double *upper_bound) { DCHECK(lower_bound != nullptr); DCHECK(upper_bound != nullptr); KnapsackAssignmentForCuts assignment(item_id, is_item_in); @@ -317,8 +312,8 @@ void KnapsackSolverForCuts::GetLowerAndUpperBoundWhenItem(int item_id, } } -double KnapsackSolverForCuts::Solve(TimeLimit* time_limit, - bool* is_solution_optimal) { +double KnapsackSolverForCuts::Solve(TimeLimit *time_limit, + bool *is_solution_optimal) { DCHECK(time_limit != nullptr); DCHECK(is_solution_optimal != nullptr); best_solution_profit_ = 0; @@ -332,8 +327,8 @@ double KnapsackSolverForCuts::Solve(TimeLimit* time_limit, root_node->set_profit_upper_bound(GetAggregatedProfitUpperBound()); root_node->set_next_item_id(GetNextItemId()); search_nodes_.push_back(std::move(root_node)); - const KnapsackSearchNodeForCuts* current_node = - search_nodes_.back().get(); // Start with the root node. + const KnapsackSearchNodeForCuts *current_node = + search_nodes_.back().get(); // Start with the root node. if (MakeNewNode(*current_node, false)) { search_queue.push(search_nodes_.back().get()); @@ -362,7 +357,7 @@ double KnapsackSolverForCuts::Solve(TimeLimit* time_limit, *is_solution_optimal = false; break; } - KnapsackSearchNodeForCuts* const node = search_queue.top(); + KnapsackSearchNodeForCuts *const node = search_queue.top(); search_queue.pop(); if (node != current_node) { @@ -385,11 +380,11 @@ double KnapsackSolverForCuts::Solve(TimeLimit* time_limit, // Returns false when at least one propagator fails. bool KnapsackSolverForCuts::UpdatePropagators( - const KnapsackSearchPathForCuts& path) { + const KnapsackSearchPathForCuts &path) { bool no_fail = true; // Revert previous changes. - const KnapsackSearchNodeForCuts* node = &path.from(); - const KnapsackSearchNodeForCuts* const via = &path.via(); + const KnapsackSearchNodeForCuts *node = &path.from(); + const KnapsackSearchNodeForCuts *const via = &path.via(); while (node != via) { no_fail = IncrementalUpdate(true, node->assignment()) && no_fail; node = node->parent(); @@ -409,7 +404,7 @@ double KnapsackSolverForCuts::GetAggregatedProfitUpperBound() { return std::min(kInfinity, propagator_upper_bound); } -bool KnapsackSolverForCuts::MakeNewNode(const KnapsackSearchNodeForCuts& node, +bool KnapsackSolverForCuts::MakeNewNode(const KnapsackSearchNodeForCuts &node, bool is_in) { if (node.next_item_id() == kNoSelection) { return false; @@ -448,7 +443,7 @@ bool KnapsackSolverForCuts::MakeNewNode(const KnapsackSearchNodeForCuts& node, } bool KnapsackSolverForCuts::IncrementalUpdate( - bool revert, const KnapsackAssignmentForCuts& assignment) { + bool revert, const KnapsackAssignmentForCuts &assignment) { // Do not stop on a failure: To be able to be incremental on the update, // partial solution (state) and propagators must all be in the same state. bool no_fail = state_.UpdateState(revert, assignment); @@ -465,4 +460,4 @@ void KnapsackSolverForCuts::UpdateBestSolution() { } } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/knapsack_solver_for_cuts.h b/ortools/algorithms/knapsack_solver_for_cuts.h index df3a8e380d..c9c5440de9 100644 --- a/ortools/algorithms/knapsack_solver_for_cuts.h +++ b/ortools/algorithms/knapsack_solver_for_cuts.h @@ -100,17 +100,17 @@ using KnapsackItemForCutsPtr = std::unique_ptr; // go through the search tree to incrementally build a partial solution from // a previous search node. class KnapsackSearchNodeForCuts { - public: - KnapsackSearchNodeForCuts(const KnapsackSearchNodeForCuts* parent, - const KnapsackAssignmentForCuts& assignment); +public: + KnapsackSearchNodeForCuts(const KnapsackSearchNodeForCuts *parent, + const KnapsackAssignmentForCuts &assignment); - KnapsackSearchNodeForCuts(const KnapsackSearchNodeForCuts&) = delete; - KnapsackSearchNodeForCuts& operator=(const KnapsackSearchNodeForCuts&) = + KnapsackSearchNodeForCuts(const KnapsackSearchNodeForCuts &) = delete; + KnapsackSearchNodeForCuts &operator=(const KnapsackSearchNodeForCuts &) = delete; int depth() const { return depth_; } - const KnapsackSearchNodeForCuts* const parent() const { return parent_; } - const KnapsackAssignmentForCuts& assignment() const { return assignment_; } + const KnapsackSearchNodeForCuts *const parent() const { return parent_; } + const KnapsackAssignmentForCuts &assignment() const { return assignment_; } double current_profit() const { return current_profit_; } void set_current_profit(double profit) { current_profit_ = profit; } @@ -121,10 +121,10 @@ class KnapsackSearchNodeForCuts { int next_item_id() const { return next_item_id_; } void set_next_item_id(int id) { next_item_id_ = id; } - private: +private: // 'depth_' is used to navigate efficiently through the search tree. int depth_; - const KnapsackSearchNodeForCuts* const parent_; + const KnapsackSearchNodeForCuts *const parent_; KnapsackAssignmentForCuts assignment_; // 'current_profit_' and 'profit_upper_bound_' fields are used to sort search @@ -156,38 +156,38 @@ class KnapsackSearchNodeForCuts { // So the state can be built by reverting all decisions from 'from' to 'via' // and then applying all decisions from 'via' to 'to'. class KnapsackSearchPathForCuts { - public: - KnapsackSearchPathForCuts(const KnapsackSearchNodeForCuts* from, - const KnapsackSearchNodeForCuts* to); +public: + KnapsackSearchPathForCuts(const KnapsackSearchNodeForCuts *from, + const KnapsackSearchNodeForCuts *to); - KnapsackSearchPathForCuts(const KnapsackSearchPathForCuts&) = delete; - KnapsackSearchPathForCuts& operator=(const KnapsackSearchPathForCuts&) = + KnapsackSearchPathForCuts(const KnapsackSearchPathForCuts &) = delete; + KnapsackSearchPathForCuts &operator=(const KnapsackSearchPathForCuts &) = delete; void Init(); - const KnapsackSearchNodeForCuts& from() const { return *from_; } - const KnapsackSearchNodeForCuts& via() const { return *via_; } - const KnapsackSearchNodeForCuts& to() const { return *to_; } + const KnapsackSearchNodeForCuts &from() const { return *from_; } + const KnapsackSearchNodeForCuts &via() const { return *via_; } + const KnapsackSearchNodeForCuts &to() const { return *to_; } - private: - const KnapsackSearchNodeForCuts* from_; - const KnapsackSearchNodeForCuts* via_; // Computed in 'Init'. - const KnapsackSearchNodeForCuts* to_; +private: + const KnapsackSearchNodeForCuts *from_; + const KnapsackSearchNodeForCuts *via_; // Computed in 'Init'. + const KnapsackSearchNodeForCuts *to_; }; // From the given node, this method moves up the tree and returns the node at // given depth. -const KnapsackSearchNodeForCuts* MoveUpToDepth( - const KnapsackSearchNodeForCuts* node, int depth); +const KnapsackSearchNodeForCuts * + MoveUpToDepth(const KnapsackSearchNodeForCuts *node, int depth); // ----- KnapsackStateForCuts ----- // KnapsackStateForCuts represents a partial solution to the knapsack problem. class KnapsackStateForCuts { - public: +public: KnapsackStateForCuts(); - KnapsackStateForCuts(const KnapsackStateForCuts&) = delete; - KnapsackStateForCuts& operator=(const KnapsackStateForCuts&) = delete; + KnapsackStateForCuts(const KnapsackStateForCuts &) = delete; + KnapsackStateForCuts &operator=(const KnapsackStateForCuts &) = delete; // Initializes vectors with number_of_items set to false (i.e. not bound yet). void Init(int number_of_items); @@ -195,13 +195,13 @@ class KnapsackStateForCuts { // Updates the state by applying or reverting a decision. // Returns false if fails, i.e. trying to apply an inconsistent decision // to an already assigned item. - bool UpdateState(bool revert, const KnapsackAssignmentForCuts& assignment); + bool UpdateState(bool revert, const KnapsackAssignmentForCuts &assignment); int GetNumberOfItems() const { return is_bound_.size(); } bool is_bound(int id) const { return is_bound_.at(id); } bool is_in(int id) const { return is_in_.at(id); } - private: +private: // Vectors 'is_bound_' and 'is_in_' contain a boolean value for each item. // 'is_bound_(item_i)' is false when there is no decision for item_i yet. // When item_i is bound, 'is_in_(item_i)' represents the presence (true) or @@ -229,20 +229,20 @@ class KnapsackStateForCuts { // the ith item should be accessible in O(1). That's the reason why the item // vector has to be duplicated 'sorted_items_'. class KnapsackPropagatorForCuts { - public: - explicit KnapsackPropagatorForCuts(const KnapsackStateForCuts* state); +public: + explicit KnapsackPropagatorForCuts(const KnapsackStateForCuts *state); ~KnapsackPropagatorForCuts(); - KnapsackPropagatorForCuts(const KnapsackPropagatorForCuts&) = delete; - KnapsackPropagatorForCuts& operator=(const KnapsackPropagatorForCuts&) = + KnapsackPropagatorForCuts(const KnapsackPropagatorForCuts &) = delete; + KnapsackPropagatorForCuts &operator=(const KnapsackPropagatorForCuts &) = delete; // Initializes the data structure and then calls InitPropagator. - void Init(const std::vector& profits, - const std::vector& weights, double capacity); + void Init(const std::vector &profits, + const std::vector &weights, double capacity); // Updates data structure. Returns false on failure. - bool Update(bool revert, const KnapsackAssignmentForCuts& assignment); + bool Update(bool revert, const KnapsackAssignmentForCuts &assignment); // ComputeProfitBounds should set 'profit_lower_bound_' and // 'profit_upper_bound_' which are constraint specific. void ComputeProfitBounds(); @@ -256,19 +256,19 @@ class KnapsackPropagatorForCuts { // Copies the current state into 'solution'. // All unbound items are set to false (i.e. not in the knapsack). - void CopyCurrentStateToSolution(std::vector* solution) const; + void CopyCurrentStateToSolution(std::vector *solution) const; // Initializes the propagator. This method is called by Init() after filling // the fields defined in this class. void InitPropagator(); - const KnapsackStateForCuts& state() const { return *state_; } - const std::vector& items() const { return items_; } + const KnapsackStateForCuts &state() const { return *state_; } + const std::vector &items() const { return items_; } void set_profit_lower_bound(double profit) { profit_lower_bound_ = profit; } void set_profit_upper_bound(double profit) { profit_upper_bound_ = profit; } - private: +private: // An obvious additional profit upper bound corresponds to the linear // relaxation: remaining_capacity * efficiency of the break item. // It is possible to do better in O(1), using Martello-Toth bound U2. @@ -289,7 +289,7 @@ class KnapsackPropagatorForCuts { double current_profit_; double profit_lower_bound_; double profit_upper_bound_; - const KnapsackStateForCuts* const state_; + const KnapsackStateForCuts *const state_; }; // ----- KnapsackSolverForCuts ----- @@ -298,22 +298,22 @@ class KnapsackPropagatorForCuts { // master propagator. Using SetMasterPropagator allows changing the default // (propagator of the first dimension). class KnapsackSolverForCuts { - public: +public: explicit KnapsackSolverForCuts(std::string solver_name); - KnapsackSolverForCuts(const KnapsackSolverForCuts&) = delete; - KnapsackSolverForCuts& operator=(const KnapsackSolverForCuts&) = delete; + KnapsackSolverForCuts(const KnapsackSolverForCuts &) = delete; + KnapsackSolverForCuts &operator=(const KnapsackSolverForCuts &) = delete; // Initializes the solver and enters the problem to be solved. - void Init(const std::vector& profits, - const std::vector& weights, const double capacity); + void Init(const std::vector &profits, + const std::vector &weights, const double capacity); int GetNumberOfItems() const { return state_.GetNumberOfItems(); } // Gets the lower and the upper bound when the item is in or out of the // knapsack. To ensure objects are correctly initialized, this method should // not be called before Init(). void GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, - double* lower_bound, double* upper_bound); + double *lower_bound, double *upper_bound); // Get the best upper bound found so far. double GetUpperBound() { return GetAggregatedProfitUpperBound(); } @@ -336,31 +336,31 @@ class KnapsackSolverForCuts { void set_node_limit(const int64 node_limit) { node_limit_ = node_limit; } // Solves the problem and returns the profit of the best solution found. - double Solve(TimeLimit* time_limit, bool* is_solution_optimal); + double Solve(TimeLimit *time_limit, bool *is_solution_optimal); // Returns true if the item 'item_id' is packed in the optimal knapsack. bool best_solution(int item_id) const { DCHECK(item_id < best_solution_.size()); return best_solution_[item_id]; } - const std::string& GetName() const { return solver_name_; } + const std::string &GetName() const { return solver_name_; } - private: +private: // Updates propagator reverting/applying all decision on the path. Returns // true if the propagation fails. Note that even if it fails, propagator // should be updated to be in a stable state in order to stay incremental. - bool UpdatePropagators(const KnapsackSearchPathForCuts& path); + bool UpdatePropagators(const KnapsackSearchPathForCuts &path); // Updates propagator reverting/applying one decision. Returns true if // the propagation fails. Note that even if it fails, propagator should // be updated to be in a stable state in order to stay incremental. bool IncrementalUpdate(bool revert, - const KnapsackAssignmentForCuts& assignment); + const KnapsackAssignmentForCuts &assignment); // Updates the best solution if the current solution has a better profit. void UpdateBestSolution(); // Returns true if new relevant search node was added to the nodes array. That // means this node should be added to the search queue too. - bool MakeNewNode(const KnapsackSearchNodeForCuts& node, bool is_in); + bool MakeNewNode(const KnapsackSearchNodeForCuts &node, bool is_in); // Gets the aggregated (min) profit upper bound among all propagators. double GetAggregatedProfitUpperBound(); @@ -368,7 +368,7 @@ class KnapsackSolverForCuts { int GetNextItemId() const { return propagator_.GetNextItemId(); } KnapsackPropagatorForCuts propagator_; - std::vector> search_nodes_; + std::vector > search_nodes_; KnapsackStateForCuts state_; double best_solution_profit_; std::vector best_solution_; @@ -381,6 +381,6 @@ class KnapsackSolverForCuts { }; // TODO(user) : Add reduction algorithm. -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_FOR_CUTS_H_ +#endif // OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_FOR_CUTS_H_ diff --git a/ortools/algorithms/sparse_permutation.cc b/ortools/algorithms/sparse_permutation.cc index cdae55d18c..c86d0233e0 100644 --- a/ortools/algorithms/sparse_permutation.cc +++ b/ortools/algorithms/sparse_permutation.cc @@ -20,7 +20,7 @@ namespace operations_research { -void SparsePermutation::RemoveCycles(const std::vector& cycle_indices) { +void SparsePermutation::RemoveCycles(const std::vector &cycle_indices) { // TODO(user): make this a class member to avoid allocation if the complexity // becomes an issue. In this case, also optimize the loop below by not copying // the first cycles. @@ -32,8 +32,8 @@ void SparsePermutation::RemoveCycles(const std::vector& cycle_indices) { << "Duplicate index given to RemoveCycles(): " << i; should_be_deleted[i] = true; } - int new_cycles_size = 0; // new index in cycles_ - int new_cycle_ends_size = 0; // new index in cycle_ends_ + int new_cycles_size = 0; // new index in cycles_ + int new_cycle_ends_size = 0; // new index in cycle_ends_ int start = 0; for (int i = 0; i < NumCycles(); ++i) { const int end = cycle_ends_[i]; @@ -51,25 +51,30 @@ void SparsePermutation::RemoveCycles(const std::vector& cycle_indices) { std::string SparsePermutation::DebugString() const { DCHECK_EQ(cycles_.empty(), cycle_ends_.empty()); - if (!cycles_.empty()) DCHECK_EQ(cycles_.size(), cycle_ends_.back()); - std::vector> cycles; + if (!cycles_.empty()) + DCHECK_EQ(cycles_.size(), cycle_ends_.back()); + std::vector > cycles; int start = 0; for (const int end : cycle_ends_) { // Find the minimum. int min_pos = start; for (int i = start + 1; i < end; ++i) { - if (cycles_[i] < cycles_[min_pos]) min_pos = i; + if (cycles_[i] < cycles_[min_pos]) + min_pos = i; } std::vector cycle; - for (int i = min_pos; i < end; ++i) cycle.push_back(cycles_[i]); - for (int i = start; i < min_pos; ++i) cycle.push_back(cycles_[i]); + for (int i = min_pos; i < end; ++i) + cycle.push_back(cycles_[i]); + for (int i = start; i < min_pos; ++i) + cycle.push_back(cycles_[i]); cycles.push_back(cycle); start = end; } std::sort(cycles.begin(), cycles.end()); std::string out; - for (const std::vector& cycle : cycles) { - if (!out.empty()) out += " "; + for (const std::vector &cycle : cycles) { + if (!out.empty()) + out += " "; out += "("; out += absl::StrJoin(cycle, " "); out += ")"; @@ -77,4 +82,4 @@ std::string SparsePermutation::DebugString() const { return out; } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/algorithms/sparse_permutation.h b/ortools/algorithms/sparse_permutation.h index 52f5f12986..bc42a4c3a6 100644 --- a/ortools/algorithms/sparse_permutation.h +++ b/ortools/algorithms/sparse_permutation.h @@ -25,8 +25,9 @@ namespace operations_research { // elements: it needs only O(K) memory for a permutation that displaces // K elements. class SparsePermutation { - public: - explicit SparsePermutation(int size) : size_(size) {} // Identity. +public: + explicit SparsePermutation(int size) : size_(size) { + } // Identity. // TODO(user,user): complete the reader API. int Size() const { return size_; } @@ -34,7 +35,7 @@ class SparsePermutation { // Returns the "support" of this permutation; that is, the set of elements // displaced by it. - const std::vector& Support() const { return cycles_; } + const std::vector &Support() const { return cycles_; } // The permutation has NumCycles() cycles numbered 0 .. NumCycles()-1. // To iterate over cycle #i of the permutation, do this: @@ -66,7 +67,7 @@ class SparsePermutation { // Removes the cycles with given indices from the permutation. This // works in O(K) for a permutation displacing K elements. - void RemoveCycles(const std::vector& cycle_indices); + void RemoveCycles(const std::vector &cycle_indices); // Output all non-identity cycles of the permutation, sorted // lexicographically (each cycle is described starting by its smallest @@ -75,7 +76,7 @@ class SparsePermutation { // Example: "(1 4 3) (5 9) (6 8 7)". std::string DebugString() const; - private: +private: const int size_; std::vector cycles_; std::vector cycle_ends_; @@ -102,8 +103,8 @@ struct SparsePermutation::Iterator { typedef std::vector::const_iterator const_iterator; Iterator() {} - Iterator(const std::vector::const_iterator& b, - const std::vector::const_iterator& e) + Iterator(const std::vector::const_iterator &b, + const std::vector::const_iterator &e) : begin_(b), end_(e) {} std::vector::const_iterator begin() const { return begin_; } @@ -128,6 +129,6 @@ inline int SparsePermutation::LastElementInCycle(int i) const { return cycles_[cycle_ends_[i] - 1]; } -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_ALGORITHMS_SPARSE_PERMUTATION_H_ +#endif // OR_TOOLS_ALGORITHMS_SPARSE_PERMUTATION_H_ diff --git a/ortools/base/accurate_sum.h b/ortools/base/accurate_sum.h index 2ef23b5da4..c3b365ceff 100644 --- a/ortools/base/accurate_sum.h +++ b/ortools/base/accurate_sum.h @@ -19,14 +19,13 @@ namespace operations_research { // Kahan summation compensation algorithm. // // http://en.wikipedia.org/wiki/Kahan_summation_algorithm -template -class AccurateSum { - public: +template class AccurateSum { +public: // You may copy-construct an AccurateSum. AccurateSum() : sum_(), error_sum_() {} // Adds an FpNumber to the sum. - void Add(const FpNumber& value) { + void Add(const FpNumber &value) { error_sum_ += value; const FpNumber new_sum = sum_ + error_sum_; error_sum_ += sum_ - new_sum; @@ -36,11 +35,11 @@ class AccurateSum { // Gets the value of the sum. FpNumber Value() const { return sum_; } - private: +private: FpNumber sum_; FpNumber error_sum_; }; -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_BASE_ACCURATE_SUM_H_ +#endif // OR_TOOLS_BASE_ACCURATE_SUM_H_ diff --git a/ortools/base/adjustable_priority_queue-inl.h b/ortools/base/adjustable_priority_queue-inl.h index b6af4d4507..e3412d3e7c 100644 --- a/ortools/base/adjustable_priority_queue-inl.h +++ b/ortools/base/adjustable_priority_queue-inl.h @@ -16,4 +16,4 @@ #include "ortools/base/adjustable_priority_queue.h" -#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_INL_H_ +#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_INL_H_ diff --git a/ortools/base/adjustable_priority_queue.h b/ortools/base/adjustable_priority_queue.h index 925ad7b1dd..f23e6a8ccf 100644 --- a/ortools/base/adjustable_priority_queue.h +++ b/ortools/base/adjustable_priority_queue.h @@ -24,36 +24,35 @@ #include "ortools/base/logging.h" #include "ortools/base/macros.h" -template -class LowerPriorityThan { - public: - explicit LowerPriorityThan(Comparator* compare) : compare_(compare) {} - bool operator()(T* a, T* b) const { return (*compare_)(*a, *b); } +template class LowerPriorityThan { +public: + explicit LowerPriorityThan(Comparator *compare) : compare_(compare) {} + bool operator()(T *a, T *b) const { return (*compare_)(*a, *b); } - private: - Comparator* compare_; +private: + Comparator *compare_; }; template > class AdjustablePriorityQueue { - public: +public: // The objects references 'c' and 'm' are not required to be alive for the // lifetime of this object. AdjustablePriorityQueue() {} - AdjustablePriorityQueue(const Comp& c) : c_(c) {} - AdjustablePriorityQueue(const AdjustablePriorityQueue&) = delete; - AdjustablePriorityQueue& operator=(const AdjustablePriorityQueue&) = delete; - AdjustablePriorityQueue(AdjustablePriorityQueue&&) = default; - AdjustablePriorityQueue& operator=(AdjustablePriorityQueue&&) = default; + AdjustablePriorityQueue(const Comp &c) : c_(c) {} + AdjustablePriorityQueue(const AdjustablePriorityQueue &) = delete; + AdjustablePriorityQueue &operator=(const AdjustablePriorityQueue &) = delete; + AdjustablePriorityQueue(AdjustablePriorityQueue &&) = default; + AdjustablePriorityQueue &operator=(AdjustablePriorityQueue &&) = default; - void Add(T* val) { + void Add(T *val) { // Extend the size of the vector by one. We could just use // vector::resize(), but maybe T is not default-constructible. elems_.push_back(val); AdjustUpwards(elems_.size() - 1); } - void Remove(T* val) { + void Remove(T *val) { int end = elems_.size() - 1; int i = val->GetHeapIndex(); if (i == end) { @@ -66,12 +65,12 @@ class AdjustablePriorityQueue { NoteChangedPriority(elems_[i]); } - bool Contains(const T* val) const { + bool Contains(const T *val) const { int i = val->GetHeapIndex(); return (i >= 0 && i < elems_.size() && elems_[i] == val); } - void NoteChangedPriority(T* val) { + void NoteChangedPriority(T *val) { LowerPriorityThan lower_priority(&c_); int i = val->GetHeapIndex(); int parent = (i - 1) / 2; @@ -84,13 +83,14 @@ class AdjustablePriorityQueue { // If val ever changes its priority, you need to call this function // to notify the pq so it can move it in the heap accordingly. - T* Top() { return elems_[0]; } + T *Top() { return elems_[0]; } - const T* Top() const { return elems_[0]; } + const T *Top() const { return elems_[0]; } - void AllTop(std::vector* topvec) { + void AllTop(std::vector *topvec) { topvec->clear(); - if (Size() == 0) return; + if (Size() == 0) + return; std::list need_to_check_children; need_to_check_children.push_back(0); // Implements breadth-first search down tree, stopping whenever @@ -148,11 +148,11 @@ class AdjustablePriorityQueue { // This is for debugging, e.g. the caller can use it to // examine the heap for rationality w.r.t. other parts of the // program. - const std::vector* Raw() const { return &elems_; } + const std::vector *Raw() const { return &elems_; } - private: +private: void AdjustUpwards(int i) { - T* const t = elems_[i]; + T *const t = elems_[i]; while (i > 0) { const int parent = (i - 1) / 2; if (!c_(*elems_[parent], *t)) { @@ -167,7 +167,7 @@ class AdjustablePriorityQueue { } void AdjustDownwards(int i) { - T* const t = elems_[i]; + T *const t = elems_[i]; while (true) { const int left_child = 1 + 2 * i; if (left_child >= elems_.size()) { @@ -190,7 +190,7 @@ class AdjustablePriorityQueue { } Comp c_; - std::vector elems_; + std::vector elems_; }; -#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_ +#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_ diff --git a/ortools/base/base_export.h b/ortools/base/base_export.h index aab1828143..b834aafa77 100644 --- a/ortools/base/base_export.h +++ b/ortools/base/base_export.h @@ -22,21 +22,21 @@ #else #define BASE_EXPORT __declspec(dllimport) #define BASE_EXPORT_PRIVATE __declspec(dllimport) -#endif // defined(BASE_IMPLEMENTATION) +#endif // defined(BASE_IMPLEMENTATION) -#else // defined(WIN32) +#else // defined(WIN32) #if defined(BASE_IMPLEMENTATION) #define BASE_EXPORT __attribute__((visibility("default"))) #define BASE_EXPORT_PRIVATE __attribute__((visibility("default"))) #else #define BASE_EXPORT #define BASE_EXPORT_PRIVATE -#endif // defined(BASE_IMPLEMENTATION) +#endif // defined(BASE_IMPLEMENTATION) #endif -#else // defined(COMPONENT_BUILD) +#else // defined(COMPONENT_BUILD) #define BASE_EXPORT #define BASE_EXPORT_PRIVATE #endif -#endif // OR_TOOLS_BASE_BASE_EXPORT_H_ +#endif // OR_TOOLS_BASE_BASE_EXPORT_H_ diff --git a/ortools/base/basictypes.h b/ortools/base/basictypes.h index 12980c7901..d6705cd993 100644 --- a/ortools/base/basictypes.h +++ b/ortools/base/basictypes.h @@ -19,4 +19,4 @@ #include "ortools/base/integral_types.h" #include "ortools/base/logging.h" -#endif // OR_TOOLS_BASE_BASICTYPES_H_ +#endif // OR_TOOLS_BASE_BASICTYPES_H_ diff --git a/ortools/base/bitmap.cc b/ortools/base/bitmap.cc index 4834528a2d..51eda6b641 100644 --- a/ortools/base/bitmap.cc +++ b/ortools/base/bitmap.cc @@ -28,7 +28,7 @@ void Bitmap::Resize(uint32 size, bool fill) { const uint32 old_array_size = array_size_; array_size_ = new_array_size; max_size_ = size; - uint64* new_map = new uint64[array_size_]; + uint64 *new_map = new uint64[array_size_]; memcpy(new_map, map_, old_array_size * sizeof(*map_)); delete[] map_; map_ = new_map; @@ -38,4 +38,4 @@ void Bitmap::Resize(uint32 size, bool fill) { Set(index, fill); } } -} // namespace operations_research +} // namespace operations_research diff --git a/ortools/base/bitmap.h b/ortools/base/bitmap.h index d5e1a6f783..18ff5c9022 100644 --- a/ortools/base/bitmap.h +++ b/ortools/base/bitmap.h @@ -24,24 +24,23 @@ inline uint64 OneBit64(int pos) { return GG_ULONGLONG(1) << pos; } inline uint64 BitPos64(uint64 pos) { return (pos & 63); } inline uint64 BitOffset64(uint64 pos) { return (pos >> 6); } inline uint64 BitLength64(uint64 size) { return ((size + 63) >> 6); } -inline bool IsBitSet64(const uint64* const bitset, uint64 pos) { +inline bool IsBitSet64(const uint64 *const bitset, uint64 pos) { return (bitset[BitOffset64(pos)] & OneBit64(BitPos64(pos))); } -inline void SetBit64(uint64* const bitset, uint64 pos) { +inline void SetBit64(uint64 *const bitset, uint64 pos) { bitset[BitOffset64(pos)] |= OneBit64(BitPos64(pos)); } -inline void ClearBit64(uint64* const bitset, uint64 pos) { +inline void ClearBit64(uint64 *const bitset, uint64 pos) { bitset[BitOffset64(pos)] &= ~OneBit64(BitPos64(pos)); } -} // namespace internal +} // namespace internal class Bitmap { - public: +public: // Constructor : This allocates on a uint32 boundary. // fill: true = initialize with 1's, false = initialize with 0's. explicit Bitmap(uint32 size, bool fill = false) - : max_size_(size), - array_size_(internal::BitLength64(size)), + : max_size_(size), array_size_(internal::BitLength64(size)), map_(new uint64[array_size_]) { // initialize all of the bits SetAll(fill); @@ -76,12 +75,12 @@ class Bitmap { // Clears all bits in the bitmap void Clear() { SetAll(false); } - private: - uint32 max_size_; // the upper bound of the bitmap +private: + uint32 max_size_; // the upper bound of the bitmap uint32 array_size_; - uint64* map_; // the bitmap + uint64 *map_; // the bitmap }; -} // namespace operations_research +} // namespace operations_research -#endif // OR_TOOLS_BASE_BITMAP_H_ +#endif // OR_TOOLS_BASE_BITMAP_H_ diff --git a/ortools/base/cleanup.h b/ortools/base/cleanup.h index 80507f9f25..1d99411e24 100644 --- a/ortools/base/cleanup.h +++ b/ortools/base/cleanup.h @@ -23,31 +23,31 @@ namespace absl { namespace cleanup_internal { -template -class Storage { +template class Storage { using InvokeT = absl::base_internal::invoke_result_t; static_assert(std::is_same::value, ""); static_assert(!std::is_reference::value, ""); - public: +public: Storage() : contains_callback_(false), callback_() {} - Storage(Storage&& other_storage) + Storage(Storage &&other_storage) : contains_callback_(other_storage.ContainsCallback()), callback_(other_storage.ReleaseCallback()) {} template - explicit Storage(TheCallback&& the_callback) + explicit Storage(TheCallback &&the_callback) : contains_callback_(true), callback_(std::forward(the_callback)) {} template - Storage(Storage&& other_storage) // NOLINT + Storage(Storage &&other_storage) // NOLINT : contains_callback_(other_storage.ContainsCallback()), callback_(other_storage.ReleaseCallback()) {} - Storage& operator=(Storage&& other_storage) { - if (ContainsCallback()) std::move(callback_)(); + Storage &operator=(Storage &&other_storage) { + if (ContainsCallback()) + std::move(callback_)(); contains_callback_ = other_storage.ContainsCallback(); callback_ = other_storage.ReleaseCallback(); return *this; @@ -68,60 +68,60 @@ class Storage { std::move(callback_)(); } - private: +private: bool contains_callback_; Callback callback_; }; struct AccessStorage { template