diff --git a/cmake/python.cmake b/cmake/python.cmake index ac3a7ef237..7c0e6979f8 100644 --- a/cmake/python.cmake +++ b/cmake/python.cmake @@ -698,10 +698,6 @@ add_custom_command( $ ${PYTHON_PROJECT}/routing/python COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_PROJECT}/sat/python - COMMAND ${CMAKE_COMMAND} -E copy - $ ${PYTHON_PROJECT}/sat/python - COMMAND ${CMAKE_COMMAND} -E copy - $ ${PYTHON_PROJECT}/sat/python COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_PROJECT}/scheduling/python COMMAND ${CMAKE_COMMAND} -E copy @@ -727,9 +723,7 @@ add_custom_command( $<$:math_opt_elemental_pybind11> $<$:math_opt_io_pybind11> $ - cp_model_builder_pybind cp_model_helper_pybind11 - sat_parameters_builder_pybind rcpsp_pybind11 set_cover_pybind11 sorted_interval_list_pybind11 diff --git a/ortools/python/BUILD.bazel b/ortools/python/BUILD.bazel index ceb9ff8cbf..b393d8ae6c 100644 --- a/ortools/python/BUILD.bazel +++ b/ortools/python/BUILD.bazel @@ -23,9 +23,7 @@ py_binary( "//ortools/graph/python:linear_sum_assignment.so", "//ortools/graph/python:max_flow.so", "//ortools/graph/python:min_cost_flow.so", - "//ortools/sat/python:cp_model_builder_pybind.so", "//ortools/sat/python:cp_model_helper.so", - "//ortools/sat/python:sat_parameters_builder_pybind.so", ], tags = ["manual"], deps = [ diff --git a/ortools/python/setup.py.in b/ortools/python/setup.py.in index 7a240263e9..d148a1b0a3 100644 --- a/ortools/python/setup.py.in +++ b/ortools/python/setup.py.in @@ -126,8 +126,6 @@ setup( '@PYTHON_PROJECT@.sat.colab':['*.pyi', 'py.typed'], '@PYTHON_PROJECT@.sat.python':[ '$', - '$', - '$', '*.pyi', 'py.typed' ], diff --git a/ortools/sat/python/BUILD.bazel b/ortools/sat/python/BUILD.bazel index 20c4da59f1..ff0364fcba 100644 --- a/ortools/sat/python/BUILD.bazel +++ b/ortools/sat/python/BUILD.bazel @@ -57,55 +57,12 @@ cc_library( ) cc_binary( - name = "gen_cp_model_builder_pybind", - srcs = ["gen_cp_model_builder_pybind.cc"], + name = "gen_proto_builder_pybind11", + srcs = ["gen_proto_builder_pybind11.cc"], deps = [ ":wrappers", "//ortools/base", "//ortools/sat:cp_model_cc_proto", - "@abseil-cpp//absl/log:die_if_null", - "@abseil-cpp//absl/strings:str_format", - ], -) - -genrule( - name = "run_gen_cp_model_builder_pybind", - outs = ["cp_model_builder_pybind.cc"], - cmd = "$(location :gen_cp_model_builder_pybind) > $@", - tools = [":gen_cp_model_builder_pybind"], -) - -pybind_extension( - name = "cp_model_builder", - srcs = [ - "cp_model_builder_pybind.cc", - ], - visibility = ["//visibility:public"], - deps = [ - "//ortools/port:proto_utils", - "//ortools/sat:cp_model_cc_proto", - "@abseil-cpp//absl/base:nullability", - "@abseil-cpp//absl/strings", - "@protobuf", - ], -) - -py_test( - name = "cp_model_builder_test", - srcs = ["cp_model_builder_test.py"], - deps = [ - ":cp_model_builder", - requirement("absl-py"), - "//ortools/sat:cp_model_py_pb2", - ], -) - -cc_binary( - name = "gen_sat_parameters_builder_pybind", - srcs = ["gen_sat_parameters_builder_pybind.cc"], - deps = [ - ":wrappers", - "//ortools/base", "//ortools/sat:sat_parameters_cc_proto", "@abseil-cpp//absl/log:die_if_null", "@abseil-cpp//absl/strings:str_format", @@ -113,34 +70,15 @@ cc_binary( ) genrule( - name = "run_gen_sat_parameters_builder_pybind", - outs = ["sat_parameters_builder_pybind.cc"], - cmd = "$(location :gen_sat_parameters_builder_pybind) > $@", - tools = [":gen_sat_parameters_builder_pybind"], + name = "run_gen_proto_builder_pybind11", + outs = ["proto_builder_pybind11.h"], + cmd = "$(location :gen_proto_builder_pybind11) > $@", + tools = [":gen_proto_builder_pybind11"], ) -pybind_extension( - name = "sat_parameters_builder", - srcs = [ - "sat_parameters_builder_pybind.cc", - ], - visibility = ["//visibility:public"], - deps = [ - "//ortools/port:proto_utils", - "//ortools/sat:sat_parameters_cc_proto", - "@abseil-cpp//absl/base:nullability", - "@abseil-cpp//absl/strings", - "@protobuf", - ], -) - -py_test( - name = "sat_parameters_builder_test", - srcs = ["sat_parameters_builder_test.py"], - deps = [ - ":sat_parameters_builder", - requirement("absl-py"), - ], +cc_library( + name = "proto_builder_pybind11", + hdrs = ["proto_builder_pybind11.h"], ) pybind_extension( @@ -150,6 +88,7 @@ pybind_extension( deps = [ ":linear_expr", ":linear_expr_doc", + ":proto_builder_pybind11", "//ortools/sat:cp_model_cc_proto", "//ortools/sat:cp_model_utils", "//ortools/sat:sat_parameters_cc_proto", @@ -162,9 +101,7 @@ py_test( name = "cp_model_helper_test", srcs = ["cp_model_helper_test.py"], deps = [ - ":cp_model_builder", ":cp_model_helper", - ":sat_parameters_builder", "//ortools/util/python:sorted_interval_list", requirement("absl-py"), ], @@ -175,9 +112,7 @@ py_library( srcs = ["cp_model.py"], visibility = ["//visibility:public"], deps = [ - ":cp_model_builder", ":cp_model_helper", - ":sat_parameters_builder", requirement("numpy"), requirement("pandas"), "//ortools/util/python:sorted_interval_list", diff --git a/ortools/sat/python/CMakeLists.txt b/ortools/sat/python/CMakeLists.txt index 147eb3f34d..fca07c1421 100644 --- a/ortools/sat/python/CMakeLists.txt +++ b/ortools/sat/python/CMakeLists.txt @@ -26,12 +26,12 @@ target_link_libraries(${WRAPPERS_NAME} PUBLIC protobuf::libprotobuf) add_library(${PROJECT_NAMESPACE}::${WRAPPERS_NAME} ALIAS ${WRAPPERS_NAME}) -# gen_cp_model_builder_pybind code generator. -add_executable(gen_cp_model_builder_pybind) -target_sources(gen_cp_model_builder_pybind PRIVATE "gen_cp_model_builder_pybind.cc") -target_include_directories(gen_cp_model_builder_pybind PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_features(gen_cp_model_builder_pybind PRIVATE cxx_std_17) -target_link_libraries(gen_cp_model_builder_pybind PRIVATE +# gen_proto_builder_pybind11 code generator. +add_executable(gen_proto_builder_pybind11) +target_sources(gen_proto_builder_pybind11 PRIVATE "gen_proto_builder_pybind11.cc") +target_include_directories(gen_proto_builder_pybind11 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_features(gen_proto_builder_pybind11 PRIVATE cxx_std_17) +target_link_libraries(gen_proto_builder_pybind11 PRIVATE absl::flags_commandlineflag absl::flags_parse absl::flags_usage @@ -43,101 +43,25 @@ target_link_libraries(gen_cp_model_builder_pybind PRIVATE include(GNUInstallDirs) if(APPLE) - set_target_properties(gen_cp_model_builder_pybind PROPERTIES INSTALL_RPATH + set_target_properties(gen_proto_builder_pybind11 PROPERTIES INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") elseif(UNIX) cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR} OUTPUT_VARIABLE libdir_relative_path) - set_target_properties(gen_cp_model_builder_pybind PROPERTIES + set_target_properties(gen_proto_builder_pybind11 PROPERTIES INSTALL_RPATH "$ORIGIN/${libdir_relative_path}") endif() -install(TARGETS gen_cp_model_builder_pybind) +install(TARGETS gen_proto_builder_pybind11) add_custom_command( - OUTPUT cp_model_builder_pybind.cc - COMMAND gen_cp_model_builder_pybind > cp_model_builder_pybind.cc - COMMENT "Generate C++ cp_model_builder_pybind.cc" + OUTPUT proto_builder_pybind11.h + COMMAND gen_proto_builder_pybind11 > proto_builder_pybind11.h + COMMENT "Generate C++ proto_builder_pybind11.h" VERBATIM) -# gen_sat_parameters_builder_pybind code generator. -add_executable(gen_sat_parameters_builder_pybind) -target_sources(gen_sat_parameters_builder_pybind PRIVATE "gen_sat_parameters_builder_pybind.cc") -target_include_directories(gen_sat_parameters_builder_pybind PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_features(gen_sat_parameters_builder_pybind PRIVATE cxx_std_17) -target_link_libraries(gen_sat_parameters_builder_pybind PRIVATE - absl::flags_commandlineflag - absl::flags_parse - absl::flags_usage - absl::die_if_null - absl::str_format - protobuf::libprotobuf - ${PROJECT_NAMESPACE}::ortools_proto - ${PROJECT_NAMESPACE}::${WRAPPERS_NAME}) - -include(GNUInstallDirs) -if(APPLE) - set_target_properties(gen_sat_parameters_builder_pybind PROPERTIES INSTALL_RPATH - "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") -elseif(UNIX) - cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR - BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR} - OUTPUT_VARIABLE libdir_relative_path) - set_target_properties(gen_sat_parameters_builder_pybind PROPERTIES - INSTALL_RPATH "$ORIGIN/${libdir_relative_path}") -endif() - -install(TARGETS gen_sat_parameters_builder_pybind) - -add_custom_command( - OUTPUT sat_parameters_builder_pybind.cc - COMMAND gen_sat_parameters_builder_pybind > sat_parameters_builder_pybind.cc - COMMENT "Generate C++ sat_parameters_builder_pybind.cc" - VERBATIM) - -# Generate both pybind extensins (cp_model_builder and sat_parameters_builder). -pybind11_add_module(cp_model_builder_pybind MODULE cp_model_builder_pybind.cc) -set_target_properties(cp_model_builder_pybind PROPERTIES - LIBRARY_OUTPUT_NAME "cp_model_builder") - -# note: macOS is APPLE and also UNIX ! -if(APPLE) - set_target_properties(cp_model_builder_pybind PROPERTIES - SUFFIX ".so" - INSTALL_RPATH "@loader_path;@loader_path/../../../${PYTHON_PROJECT}/.libs") -elseif(UNIX) - set_target_properties(cp_model_builder_pybind PROPERTIES - INSTALL_RPATH "$ORIGIN:$ORIGIN/../../../${PYTHON_PROJECT}/.libs") -endif() -target_link_libraries(cp_model_builder_pybind PRIVATE - ${PROJECT_NAMESPACE}::ortools - protobuf::libprotobuf) - -target_include_directories(cp_model_builder_pybind PRIVATE ${protobuf_SOURCE_DIR}) -add_library(${PROJECT_NAMESPACE}::cp_model_builder_pybind ALIAS cp_model_builder_pybind) - -pybind11_add_module(sat_parameters_builder_pybind MODULE sat_parameters_builder_pybind.cc) -set_target_properties(sat_parameters_builder_pybind PROPERTIES - LIBRARY_OUTPUT_NAME "sat_parameters_builder") - -# note: macOS is APPLE and also UNIX ! -if(APPLE) - set_target_properties(sat_parameters_builder_pybind PROPERTIES - SUFFIX ".so" - INSTALL_RPATH "@loader_path;@loader_path/../../../${PYTHON_PROJECT}/.libs") -elseif(UNIX) - set_target_properties(sat_parameters_builder_pybind PROPERTIES - INSTALL_RPATH "$ORIGIN:$ORIGIN/../../../${PYTHON_PROJECT}/.libs") -endif() -target_link_libraries(sat_parameters_builder_pybind PRIVATE - ${PROJECT_NAMESPACE}::ortools - protobuf::libprotobuf) - -target_include_directories(sat_parameters_builder_pybind PRIVATE ${protobuf_SOURCE_DIR}) -add_library(${PROJECT_NAMESPACE}::sat_parameters_builder_pybind ALIAS sat_parameters_builder_pybind) - -pybind11_add_module(cp_model_helper_pybind11 MODULE cp_model_helper.cc) +pybind11_add_module(cp_model_helper_pybind11 MODULE cp_model_helper.cc proto_builder_pybind11.h) set_target_properties(cp_model_helper_pybind11 PROPERTIES LIBRARY_OUTPUT_NAME "cp_model_helper") diff --git a/ortools/sat/python/cp_model.py b/ortools/sat/python/cp_model.py index a24a0fb9db..6ca70378c1 100644 --- a/ortools/sat/python/cp_model.py +++ b/ortools/sat/python/cp_model.py @@ -64,14 +64,7 @@ import warnings import numpy as np import pandas as pd -# Make sure the generated cp_model_helper is imported before the builder -# modules as the import duplicates versions of the protobufs. -from ortools.sat.python import ( - cp_model_helper as cmh, -) # pylint: disable=g-bad-import-order - -from ortools.sat.python import cp_model_builder as cmb -from ortools.sat.python import sat_parameters_builder as spb +from ortools.sat.python import cp_model_helper as cmh from ortools.util.python import sorted_interval_list # Import external types. @@ -82,6 +75,10 @@ FlatIntExpr = cmh.FlatIntExpr LinearExpr = cmh.LinearExpr IntVar = cmh.IntVar NotBooleanVariable = cmh.NotBooleanVariable +CpModelProto = cmh.CpModelProto +CpSolverStatus = cmh.CpSolverStatus +CpSolverResponse = cmh.CpSolverResponse +SatParameters = cmh.SatParameters # The classes below allow linear expressions to be expressed naturally with the @@ -94,52 +91,52 @@ INT32_MIN = -(2**31) INT32_MAX = 2**31 - 1 # CpSolver status (exported to avoid importing cp_model_cp2). -UNKNOWN = cmb.CpSolverStatus.UNKNOWN -UNKNOWN = cmb.CpSolverStatus.UNKNOWN -MODEL_INVALID = cmb.CpSolverStatus.MODEL_INVALID -FEASIBLE = cmb.CpSolverStatus.FEASIBLE -INFEASIBLE = cmb.CpSolverStatus.INFEASIBLE -OPTIMAL = cmb.CpSolverStatus.OPTIMAL +UNKNOWN = cmh.CpSolverStatus.UNKNOWN +UNKNOWN = cmh.CpSolverStatus.UNKNOWN +MODEL_INVALID = cmh.CpSolverStatus.MODEL_INVALID +FEASIBLE = cmh.CpSolverStatus.FEASIBLE +INFEASIBLE = cmh.CpSolverStatus.INFEASIBLE +OPTIMAL = cmh.CpSolverStatus.OPTIMAL # Variable selection strategy -CHOOSE_FIRST = cmb.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_FIRST +CHOOSE_FIRST = cmh.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_FIRST CHOOSE_LOWEST_MIN = ( - cmb.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_LOWEST_MIN + cmh.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_LOWEST_MIN ) CHOOSE_HIGHEST_MAX = ( - cmb.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_HIGHEST_MAX + cmh.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_HIGHEST_MAX ) CHOOSE_MIN_DOMAIN_SIZE = ( - cmb.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_MIN_DOMAIN_SIZE + cmh.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_MIN_DOMAIN_SIZE ) CHOOSE_MAX_DOMAIN_SIZE = ( - cmb.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_MAX_DOMAIN_SIZE + cmh.DecisionStrategyProto.VariableSelectionStrategy.CHOOSE_MAX_DOMAIN_SIZE ) # Domain reduction strategy -SELECT_MIN_VALUE = cmb.DecisionStrategyProto.DomainReductionStrategy.SELECT_MIN_VALUE -SELECT_MAX_VALUE = cmb.DecisionStrategyProto.DomainReductionStrategy.SELECT_MAX_VALUE -SELECT_LOWER_HALF = cmb.DecisionStrategyProto.DomainReductionStrategy.SELECT_LOWER_HALF -SELECT_UPPER_HALF = cmb.DecisionStrategyProto.DomainReductionStrategy.SELECT_UPPER_HALF +SELECT_MIN_VALUE = cmh.DecisionStrategyProto.DomainReductionStrategy.SELECT_MIN_VALUE +SELECT_MAX_VALUE = cmh.DecisionStrategyProto.DomainReductionStrategy.SELECT_MAX_VALUE +SELECT_LOWER_HALF = cmh.DecisionStrategyProto.DomainReductionStrategy.SELECT_LOWER_HALF +SELECT_UPPER_HALF = cmh.DecisionStrategyProto.DomainReductionStrategy.SELECT_UPPER_HALF SELECT_MEDIAN_VALUE = ( - cmb.DecisionStrategyProto.DomainReductionStrategy.SELECT_MEDIAN_VALUE + cmh.DecisionStrategyProto.DomainReductionStrategy.SELECT_MEDIAN_VALUE ) SELECT_RANDOM_HALF = ( - cmb.DecisionStrategyProto.DomainReductionStrategy.SELECT_RANDOM_HALF + cmh.DecisionStrategyProto.DomainReductionStrategy.SELECT_RANDOM_HALF ) # Search branching -AUTOMATIC_SEARCH = spb.SatParameters.SearchBranching.AUTOMATIC_SEARCH -FIXED_SEARCH = spb.SatParameters.SearchBranching.FIXED_SEARCH -PORTFOLIO_SEARCH = spb.SatParameters.SearchBranching.PORTFOLIO_SEARCH -LP_SEARCH = spb.SatParameters.SearchBranching.LP_SEARCH -PSEUDO_COST_SEARCH = spb.SatParameters.SearchBranching.PSEUDO_COST_SEARCH +AUTOMATIC_SEARCH = cmh.SatParameters.SearchBranching.AUTOMATIC_SEARCH +FIXED_SEARCH = cmh.SatParameters.SearchBranching.FIXED_SEARCH +PORTFOLIO_SEARCH = cmh.SatParameters.SearchBranching.PORTFOLIO_SEARCH +LP_SEARCH = cmh.SatParameters.SearchBranching.LP_SEARCH +PSEUDO_COST_SEARCH = cmh.SatParameters.SearchBranching.PSEUDO_COST_SEARCH PORTFOLIO_WITH_QUICK_RESTART_SEARCH = ( - spb.SatParameters.SearchBranching.PORTFOLIO_WITH_QUICK_RESTART_SEARCH + cmh.SatParameters.SearchBranching.PORTFOLIO_WITH_QUICK_RESTART_SEARCH ) -HINT_SEARCH = spb.SatParameters.SearchBranching.HINT_SEARCH -PARTIAL_FIXED_SEARCH = spb.SatParameters.SearchBranching.PARTIAL_FIXED_SEARCH -RANDOMIZED_SEARCH = spb.SatParameters.SearchBranching.RANDOMIZED_SEARCH +HINT_SEARCH = cmh.SatParameters.SearchBranching.HINT_SEARCH +PARTIAL_FIXED_SEARCH = cmh.SatParameters.SearchBranching.PARTIAL_FIXED_SEARCH +RANDOMIZED_SEARCH = cmh.SatParameters.SearchBranching.RANDOMIZED_SEARCH # Type aliases IntegralT = Union[int, np.int8, np.uint8, np.int32, np.uint32, np.int64, np.uint64] @@ -187,7 +184,7 @@ ArcT = Tuple[IntegralT, IntegralT, LiteralT] _IndexOrSeries = Union[pd.Index, pd.Series] -def short_name(model: cmb.CpModelProto, i: int) -> str: +def short_name(model: cmh.CpModelProto, i: int) -> str: """Returns a short name of an integer variable, or its negation.""" if i >= 0: return str(IntVar(model, i)) @@ -196,8 +193,8 @@ def short_name(model: cmb.CpModelProto, i: int) -> str: def short_expr_name( - model: cmb.CpModelProto, - e: cmb.LinearExpressionProto, + model: cmh.CpModelProto, + e: cmh.LinearExpressionProto, ) -> str: """Pretty-print LinearExpressionProto instances.""" if not e.vars: @@ -231,8 +228,8 @@ def arg_is_boolean(x: Any) -> bool: def rebuild_from_linear_expression_proto( - proto: cmb.LinearExpressionProto, - model_proto: cmb.CpModelProto, + proto: cmh.LinearExpressionProto, + model_proto: cmh.CpModelProto, ) -> LinearExprT: """Recreate a LinearExpr from a LinearExpressionProto.""" num_elements = len(proto.vars) @@ -344,7 +341,7 @@ class Constraint: return self.__index @property - def proto(self) -> cmb.ConstraintProto: + def proto(self) -> cmh.ConstraintProto: """Returns the constraint protobuf.""" return self.__cp_model.proto.constraints[self.__index] @@ -365,7 +362,7 @@ class Constraint: def Index(self) -> int: return self.index - def Proto(self) -> cmb.ConstraintProto: + def Proto(self) -> cmh.ConstraintProto: return self.proto # pylint: enable=invalid-name @@ -394,16 +391,16 @@ class IntervalVar: def __init__( self, - model: cmb.CpModelProto, - start: Union[cmb.LinearExpressionProto, int], - size: Optional[cmb.LinearExpressionProto], - end: Optional[cmb.LinearExpressionProto], + model: cmh.CpModelProto, + start: Union[cmh.LinearExpressionProto, int], + size: Optional[cmh.LinearExpressionProto], + end: Optional[cmh.LinearExpressionProto], is_present_index: Optional[int], name: Optional[str], ) -> None: - self.__model: cmb.CpModelProto = model + self.__model: cmh.CpModelProto = model self.__index: int - self.__ct: cmb.ConstraintProto + self.__ct: cmh.ConstraintProto # As with the IntVar::__init__ method, we hack the __init__ method to # support two use cases: # case 1: called when creating a new interval variable. @@ -443,12 +440,12 @@ class IntervalVar: return self.__index @property - def proto(self) -> cmb.ConstraintProto: + def proto(self) -> cmh.ConstraintProto: """Returns the interval protobuf.""" return self.__model.constraints[self.__index] @property - def model_proto(self) -> cmb.CpModelProto: + def model_proto(self) -> cmh.CpModelProto: """Returns the model protobuf.""" return self.__model @@ -502,7 +499,7 @@ class IntervalVar: def Index(self) -> int: return self.index - def Proto(self) -> cmb.ConstraintProto: + def Proto(self) -> cmh.ConstraintProto: return self.proto StartExpr = start_expr @@ -548,7 +545,7 @@ class CpModel: """ def __init__(self) -> None: - self.__model: cmb.CpModelProto = cmb.CpModelProto() + self.__model: cmh.CpModelProto = cmh.CpModelProto() self.__constant_map: Dict[IntegralT, int] = {} # Naming. @@ -1966,7 +1963,7 @@ class CpModel: return str(self.__model) @property - def proto(self) -> cmb.CpModelProto: + def proto(self) -> cmh.CpModelProto: """Returns the underlying CpModelProto.""" return self.__model @@ -2022,9 +2019,9 @@ class CpModel: def parse_linear_expression( self, linear_expr: LinearExprT, negate: bool = False - ) -> cmb.LinearExpressionProto: + ) -> cmh.LinearExpressionProto: """Returns a LinearExpressionProto built from a LinearExpr instance.""" - result: cmb.LinearExpressionProto = cmb.LinearExpressionProto() + result: cmh.LinearExpressionProto = cmh.LinearExpressionProto() mult = -1 if negate else 1 if isinstance(linear_expr, IntegralTypes): result.offset = int(linear_expr) * mult @@ -2091,8 +2088,8 @@ class CpModel: def add_decision_strategy( self, variables: Sequence[IntVar], - var_strategy: cmb.DecisionStrategyProto.VariableSelectionStrategy, - domain_strategy: cmb.DecisionStrategyProto.DomainReductionStrategy, + var_strategy: cmh.DecisionStrategyProto.VariableSelectionStrategy, + domain_strategy: cmh.DecisionStrategyProto.DomainReductionStrategy, ) -> None: """Adds a search strategy to the model. @@ -2105,7 +2102,7 @@ class CpModel: solve() will fail. """ - strategy: cmb.DecisionStrategyProto = self.__model.search_strategy.add() + strategy: cmh.DecisionStrategyProto = self.__model.search_strategy.add() for v in variables: expr = strategy.exprs.add() if v.index >= 0: @@ -2223,7 +2220,7 @@ class CpModel: def SetName(self, name: str) -> None: self.name = name - def Proto(self) -> cmb.CpModelProto: + def Proto(self) -> cmh.CpModelProto: return self.proto NewIntVar = new_int_var @@ -2314,7 +2311,7 @@ class CpSolver: def __init__(self) -> None: self.__response_wrapper: Optional[cmh.ResponseWrapper] = None - self.parameters: spb.SatParameters = spb.SatParameters() + self.parameters: cmh.SatParameters = cmh.SatParameters() self.log_callback: Optional[Callable[[str], None]] = None self.best_bound_callback: Optional[Callable[[float], None]] = None self.__solve_wrapper: Optional[cmh.SolveWrapper] = None @@ -2324,7 +2321,7 @@ class CpSolver: self, model: CpModel, solution_callback: Optional["CpSolverSolutionCallback"] = None, - ) -> cmb.CpSolverStatus: + ) -> cmh.CpSolverStatus: """Solves a problem and passes each solution to the callback if not null.""" with self.__lock: self.__solve_wrapper = cmh.SolveWrapper() @@ -2497,7 +2494,7 @@ class CpSolver: return self._checked_response.user_time() @property - def response_proto(self) -> cmb.CpSolverResponse: + def response_proto(self) -> cmh.CpSolverResponse: """Returns the response object.""" return self._checked_response.response() @@ -2557,7 +2554,7 @@ class CpSolver: def ObjectiveValue(self) -> float: return self.objective_value - def ResponseProto(self) -> cmb.CpSolverResponse: + def ResponseProto(self) -> cmh.CpSolverResponse: return self.response_proto def ResponseStats(self) -> str: @@ -2567,7 +2564,7 @@ class CpSolver: self, model: CpModel, solution_callback: Optional["CpSolverSolutionCallback"] = None, - ) -> cmb.CpSolverStatus: + ) -> cmh.CpSolverStatus: return self.solve(model, solution_callback) def SolutionInfo(self) -> str: @@ -2596,7 +2593,7 @@ class CpSolver: def SolveWithSolutionCallback( self, model: CpModel, callback: "CpSolverSolutionCallback" - ) -> cmb.CpSolverStatus: + ) -> cmh.CpSolverStatus: """DEPRECATED Use solve() with the callback argument.""" warnings.warn( "solve_with_solution_callback is deprecated; use solve() with" @@ -2607,7 +2604,7 @@ class CpSolver: def SearchForAllSolutions( self, model: CpModel, callback: "CpSolverSolutionCallback" - ) -> cmb.CpSolverStatus: + ) -> cmh.CpSolverStatus: """DEPRECATED Use solve() with the right parameter. Search for all solutions of a satisfiability problem. @@ -2641,7 +2638,7 @@ class CpSolver: enumerate_all = self.parameters.enumerate_all_solutions self.parameters.enumerate_all_solutions = True - status: cmb.CpSolverStatus = self.solve(model, callback) + status: cmh.CpSolverStatus = self.solve(model, callback) # Restore parameter. self.parameters.enumerate_all_solutions = enumerate_all @@ -2802,7 +2799,7 @@ class CpSolverSolutionCallback(cmh.SolutionCallback): return self.UserTime() @property - def response_proto(self) -> cmb.CpSolverResponse: + def response_proto(self) -> cmh.CpSolverResponse: """Returns the response object.""" if not self.has_response(): raise RuntimeError("solve() has not been called.") diff --git a/ortools/sat/python/cp_model_builder_test.py b/ortools/sat/python/cp_model_builder_test.py deleted file mode 100644 index 05293b37ca..0000000000 --- a/ortools/sat/python/cp_model_builder_test.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2010-2025 Google LLC -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from absl.testing import absltest -from ortools.sat import cp_model_pb2 -from ortools.sat.python import cp_model_builder - - -class CpModelBuilderTest(absltest.TestCase): - - def test_basic(self): - model_proto = cp_model_builder.CpModelProto() - - # Singular message. - objective = model_proto.objective - - # Singular int. - self.assertEqual(objective.offset, 0) - objective.offset = 123 - self.assertEqual(objective.offset, 123) - - # Set a message. - new_obj = cp_model_builder.CpObjectiveProto() - new_obj.offset = 456 - model_proto.objective = new_obj - self.assertEqual(objective.offset, 456) - - # Large int. - objective.offset = 500000000000 - self.assertEqual(objective.offset, 500000000000) - - # Repeated message. - my_var = model_proto.variables.add() - - # Singular string. - self.assertEqual(my_var.name, "") - my_var.name = "my_var" - self.assertEqual(my_var.name, "my_var") - my_var.domain.extend([0, 1]) - domain = list(my_var.domain) - self.assertLen(domain, 2) - self.assertEqual(domain[0], 0) - self.assertEqual(domain[1], 1) - - # Repeated int. - objective.vars.append(0) - self.assertLen(objective.vars, 1) - self.assertEqual(objective.vars[0], 0) - objective.vars[0] = 42 - self.assertEqual(objective.vars[0], 42) - - # Singular enum - search_strategy = model_proto.search_strategy.add() - self.assertEqual( - search_strategy.variable_selection_strategy, - cp_model_builder.DecisionStrategyProto.CHOOSE_FIRST, - ) - search_strategy.variable_selection_strategy = ( - cp_model_builder.DecisionStrategyProto.CHOOSE_LOWEST_MIN - ) - self.assertEqual( - search_strategy.variable_selection_strategy, - cp_model_pb2.DecisionStrategyProto.CHOOSE_LOWEST_MIN, - ) - - -if __name__ == "__main__": - absltest.main() diff --git a/ortools/sat/python/cp_model_helper.cc b/ortools/sat/python/cp_model_helper.cc index 3fe72f69cc..ea84245220 100644 --- a/ortools/sat/python/cp_model_helper.cc +++ b/ortools/sat/python/cp_model_helper.cc @@ -25,6 +25,7 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" +#include "ortools/port/proto_utils.h" // IWYU: keep #include "ortools/sat/cp_model.pb.h" #include "ortools/sat/cp_model_utils.h" #include "ortools/sat/python/linear_expr.h" @@ -500,8 +501,6 @@ void ClearCtName(int index, std::shared_ptr model_proto) { } PYBIND11_MODULE(cp_model_helper, m) { - py::module::import("ortools.sat.python.cp_model_builder"); - py::module::import("ortools.sat.python.sat_parameters_builder"); py::module::import("ortools.util.python.sorted_interval_list"); // We keep the CamelCase name for the SolutionCallback class to be @@ -1303,6 +1302,9 @@ PYBIND11_MODULE(cp_model_helper, m) { "not supported.")); return false; }); +#define IMPORT_PROTO_WRAPPER_CODE +#include "ortools/sat/python/proto_builder_pybind11.h" +#undef IMPORT_PROTO_WRAPPER_CODE } // NOLINT(readability/fn_size) } // namespace operations_research::sat::python diff --git a/ortools/sat/python/cp_model_helper_test.py b/ortools/sat/python/cp_model_helper_test.py index 09a39afc1d..71b90845f2 100644 --- a/ortools/sat/python/cp_model_helper_test.py +++ b/ortools/sat/python/cp_model_helper_test.py @@ -18,9 +18,7 @@ import sys from absl.testing import absltest -from ortools.sat.python import cp_model_builder from ortools.sat.python import cp_model_helper as cmh -from ortools.sat.python import sat_parameters_builder from ortools.util.python import sorted_interval_list @@ -58,7 +56,7 @@ class CpModelHelperTest(absltest.TestCase): variables { domain: [ -10, 10 ] } variables { domain: [ -5, -5, 3, 6 ] } """ - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() self.assertTrue(model.parse_text_format(model_string)) d0 = cmh.CpSatHelper.variable_domain(model.variables[0]) @@ -99,13 +97,13 @@ class CpModelHelperTest(absltest.TestCase): coeffs: -1 scaling_factor: -1 }""" - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() self.assertTrue(model.parse_text_format(model_string)) solve_wrapper = cmh.SolveWrapper() response_wrapper = solve_wrapper.solve_and_return_response_wrapper(model) - self.assertEqual(cp_model_builder.OPTIMAL, response_wrapper.status()) + self.assertEqual(cmh.OPTIMAL, response_wrapper.status()) self.assertEqual(30.0, response_wrapper.objective_value()) def test_simple_solve_with_core(self): @@ -140,21 +138,21 @@ class CpModelHelperTest(absltest.TestCase): coeffs: -1 scaling_factor: -1 }""" - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() self.assertTrue(model.parse_text_format(model_string)) - parameters = sat_parameters_builder.SatParameters() + parameters = cmh.SatParameters() parameters.optimize_with_core = True solve_wrapper = cmh.SolveWrapper() solve_wrapper.set_parameters(parameters) response_wrapper = solve_wrapper.solve_and_return_response_wrapper(model) - self.assertEqual(cp_model_builder.OPTIMAL, response_wrapper.status()) + self.assertEqual(cmh.OPTIMAL, response_wrapper.status()) self.assertEqual(30.0, response_wrapper.objective_value()) def test_simple_solve_with_proto_api(self): - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() x = model.variables.add() x.domain.extend([-10, 10]) y = model.variables.add() @@ -172,7 +170,7 @@ class CpModelHelperTest(absltest.TestCase): solve_wrapper = cmh.SolveWrapper() response_wrapper = solve_wrapper.solve_and_return_response_wrapper(model) - self.assertEqual(cp_model_builder.OPTIMAL, response_wrapper.status()) + self.assertEqual(cmh.OPTIMAL, response_wrapper.status()) self.assertEqual(30.0, response_wrapper.objective_value()) self.assertEqual(30.0, response_wrapper.best_objective_bound()) self.assertRaises(TypeError, response_wrapper.value, None) @@ -186,19 +184,19 @@ class CpModelHelperTest(absltest.TestCase): constraints { linear { vars: 0 vars: 1 coeffs: 1 coeffs: 1 domain: 6 domain: 6 } } """ - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() self.assertTrue(model.parse_text_format(model_string)) solve_wrapper = cmh.SolveWrapper() callback = Callback() solve_wrapper.add_solution_callback(callback) - params = sat_parameters_builder.SatParameters() + params = cmh.SatParameters() params.enumerate_all_solutions = True solve_wrapper.set_parameters(params) response_wrapper = solve_wrapper.solve_and_return_response_wrapper(model) self.assertEqual(5, callback.solution_count()) - self.assertEqual(cp_model_builder.OPTIMAL, response_wrapper.status()) + self.assertEqual(cmh.OPTIMAL, response_wrapper.status()) def test_best_bound_callback(self): model_string = """ @@ -213,13 +211,13 @@ class CpModelHelperTest(absltest.TestCase): offset: 0.6 } """ - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() self.assertTrue(model.parse_text_format(model_string)) solve_wrapper = cmh.SolveWrapper() best_bound_callback = BestBoundCallback() solve_wrapper.add_best_bound_callback(best_bound_callback.new_best_bound) - params = sat_parameters_builder.SatParameters() + params = cmh.SatParameters() params.num_workers = 1 params.linearization_level = 2 params.log_search_progress = True @@ -227,7 +225,7 @@ class CpModelHelperTest(absltest.TestCase): response_wrapper = solve_wrapper.solve_and_return_response_wrapper(model) self.assertEqual(2.6, best_bound_callback.best_bound) - self.assertEqual(cp_model_builder.OPTIMAL, response_wrapper.status()) + self.assertEqual(cmh.OPTIMAL, response_wrapper.status()) def test_model_stats(self): model_string = """ @@ -263,13 +261,13 @@ class CpModelHelperTest(absltest.TestCase): } name: 'testModelStats' """ - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() self.assertTrue(model.parse_text_format(model_string)) stats = cmh.CpSatHelper.model_stats(model) self.assertTrue(stats) def test_int_lin_expr(self): - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() x = cmh.IntVar(model).with_name("x") self.assertTrue(x.is_integer()) self.assertIsInstance(x, cmh.IntVar) @@ -316,7 +314,7 @@ class CpModelHelperTest(absltest.TestCase): self.assertEqual(str(e12), "(x + (-y) + (-2 * z))") def test_float_lin_expr(self): - model = cp_model_builder.CpModelProto() + model = cmh.CpModelProto() x = cmh.IntVar(model).with_name("x") self.assertTrue(x.is_integer()) self.assertIsInstance(x, cmh.IntVar) @@ -362,5 +360,89 @@ class CpModelHelperTest(absltest.TestCase): self.assertEqual(str(e12), "(3.1 * (x + 2))") +class CpModelBuilderTest(absltest.TestCase): + + def test_basic(self): + model_proto = cmh.CpModelProto() + + # Singular message. + objective = model_proto.objective + + # Singular int. + self.assertEqual(objective.offset, 0) + objective.offset = 123 + self.assertEqual(objective.offset, 123) + + # Set a message. + new_obj = cmh.CpObjectiveProto() + new_obj.offset = 456 + model_proto.objective = new_obj + self.assertEqual(objective.offset, 456) + + # Large int. + objective.offset = 500000000000 + self.assertEqual(objective.offset, 500000000000) + + # Repeated message. + my_var = model_proto.variables.add() + + # Singular string. + self.assertEqual(my_var.name, "") + my_var.name = "my_var" + self.assertEqual(my_var.name, "my_var") + my_var.domain.extend([0, 1]) + domain = list(my_var.domain) + self.assertLen(domain, 2) + self.assertEqual(domain[0], 0) + self.assertEqual(domain[1], 1) + + # Repeated int. + objective.vars.append(0) + self.assertLen(objective.vars, 1) + self.assertEqual(objective.vars[0], 0) + objective.vars[0] = 42 + self.assertEqual(objective.vars[0], 42) + + # Singular enum + search_strategy = model_proto.search_strategy.add() + self.assertEqual( + search_strategy.variable_selection_strategy, + cmh.DecisionStrategyProto.CHOOSE_FIRST, + ) + search_strategy.variable_selection_strategy = ( + cmh.DecisionStrategyProto.CHOOSE_LOWEST_MIN + ) + self.assertEqual( + search_strategy.variable_selection_strategy, + cmh.DecisionStrategyProto.CHOOSE_LOWEST_MIN, + ) + + +class SatParametersBuilderTest(absltest.TestCase): + + def test_basic_api(self) -> None: + params = cmh.SatParameters() + + # Test that we can set and get an integer parameter. + params.num_workers = 10 + self.assertEqual(params.num_workers, 10) + + # Test that we can set and get an enum parameter. + self.assertEqual( + params.clause_cleanup_ordering, + cmh.SatParameters.ClauseOrdering.CLAUSE_ACTIVITY, + ) + params.clause_cleanup_ordering = cmh.SatParameters.ClauseOrdering.CLAUSE_LBD + self.assertEqual( + params.clause_cleanup_ordering, + cmh.SatParameters.ClauseOrdering.CLAUSE_LBD, + ) + + # Test that we can set and get a repeated string parameter. + params.subsolvers.append("no_lp") + self.assertLen(params.subsolvers, 1) + self.assertEqual(params.subsolvers[0], "no_lp") + + if __name__ == "__main__": absltest.main() diff --git a/ortools/sat/python/cp_model_test.py b/ortools/sat/python/cp_model_test.py index aa647a6bb2..c7e154eec4 100644 --- a/ortools/sat/python/cp_model_test.py +++ b/ortools/sat/python/cp_model_test.py @@ -22,7 +22,6 @@ import numpy as np import pandas as pd from ortools.sat.python import cp_model -from ortools.sat.python import cp_model_builder from ortools.sat.python import cp_model_helper as cmh @@ -585,7 +584,7 @@ class CpModelTest(absltest.TestCase): model.add(3 <= -1) model.minimize(x) solver = cp_model.CpSolver() - status: cp_model_builder.CpSolverStatus = solver.solve(model) + status: cmh.CpSolverStatus = solver.solve(model) self.assertEqual("INFEASIBLE", status.name) def test_sum(self) -> None: @@ -1308,7 +1307,7 @@ class CpModelTest(absltest.TestCase): self.assertEqual(~i.size_expr(), ~y) self.assertRaises(TypeError, i.start_expr().negated) - proto = cp_model_builder.LinearExpressionProto() + proto = cmh.LinearExpressionProto() proto.vars.append(x.index) proto.coeffs.append(1) proto.vars.append(y.index) diff --git a/ortools/sat/python/gen_cp_model_builder_pybind.cc b/ortools/sat/python/gen_proto_builder_pybind11.cc similarity index 74% rename from ortools/sat/python/gen_cp_model_builder_pybind.cc rename to ortools/sat/python/gen_proto_builder_pybind11.cc index bc19b8f5d0..0857c01c89 100644 --- a/ortools/sat/python/gen_cp_model_builder_pybind.cc +++ b/ortools/sat/python/gen_proto_builder_pybind11.cc @@ -18,6 +18,7 @@ #include "absl/strings/str_format.h" #include "ortools/sat/cp_model.pb.h" #include "ortools/sat/python/wrappers.h" +#include "ortools/sat/sat_parameters.pb.h" namespace operations_research::sat::python { @@ -26,28 +27,13 @@ void ParseAndGenerate() { R"( // This is a generated file, do not edit. -#include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" -#include "google/protobuf/text_format.h" -#include "pybind11/numpy.h" -#include "pybind11/pybind11.h" -#include "pybind11/pytypes.h" -#include "pybind11/stl.h" -#include "ortools/port/proto_utils.h" -#include "ortools/sat/cp_model.pb.h" - -namespace py = ::pybind11; - -namespace operations_research::sat::python { - -PYBIND11_MODULE(cp_model_builder, py_module) { +#if defined(IMPORT_PROTO_WRAPPER_CODE) %s -} // PYBIND11_MODULE - -} // namespace operations_research::sat::python +#endif // defined(IMPORT_PROTO_WRAPPER_CODE) )", GeneratePybindCode({ABSL_DIE_IF_NULL(CpModelProto::descriptor()), - ABSL_DIE_IF_NULL(CpSolverResponse::descriptor())})); + ABSL_DIE_IF_NULL(CpSolverResponse::descriptor()), + ABSL_DIE_IF_NULL(SatParameters::descriptor())})); } } // namespace operations_research::sat::python diff --git a/ortools/sat/python/gen_sat_parameters_builder_pybind.cc b/ortools/sat/python/gen_sat_parameters_builder_pybind.cc deleted file mode 100644 index cf2596abce..0000000000 --- a/ortools/sat/python/gen_sat_parameters_builder_pybind.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2010-2025 Google LLC -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/flags/parse.h" -#include "absl/flags/usage.h" -#include "absl/log/die_if_null.h" -#include "absl/log/initialize.h" -#include "absl/strings/str_format.h" -#include "ortools/sat/python/wrappers.h" -#include "ortools/sat/sat_parameters.pb.h" - -namespace operations_research::sat::python { - -void ParseAndGenerate() { - absl::PrintF( - R"( - -// This is a generated file, do not edit. -#include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" -#include "google/protobuf/text_format.h" -#include "pybind11/numpy.h" -#include "pybind11/pybind11.h" -#include "pybind11/pytypes.h" -#include "pybind11/stl.h" -#include "ortools/port/proto_utils.h" -#include "ortools/sat/sat_parameters.pb.h" - -namespace py = ::pybind11; -namespace operations_research::sat::python { -PYBIND11_MODULE(sat_parameters_builder, py_module) { -%s -} // PYBIND11_MODULE -} // namespace operations_research::sat::python -)", - GeneratePybindCode({ABSL_DIE_IF_NULL(SatParameters::descriptor())})); -} - -} // namespace operations_research::sat::python - -int main(int argc, char* argv[]) { - // We do not use InitGoogle() to avoid linking with or-tools as this would - // create a circular dependency. - absl::InitializeLog(); - absl::SetProgramUsageMessage(argv[0]); - absl::ParseCommandLine(argc, argv); - operations_research::sat::python::ParseAndGenerate(); - return 0; -} diff --git a/ortools/sat/python/sat_parameters_builder_test.py b/ortools/sat/python/sat_parameters_builder_test.py deleted file mode 100644 index 2be6d40b58..0000000000 --- a/ortools/sat/python/sat_parameters_builder_test.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2010-2025 Google LLC -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Test sat parameters builder.""" - -from absl.testing import absltest -from ortools.sat.python import sat_parameters_builder - - -class SatParametersBuilderTest(absltest.TestCase): - - def test_basic_api(self) -> None: - params = sat_parameters_builder.SatParameters() - - # Test that we can set and get an integer parameter. - params.num_workers = 10 - self.assertEqual(params.num_workers, 10) - - # Test that we can set and get an enum parameter. - self.assertEqual( - params.clause_cleanup_ordering, - sat_parameters_builder.SatParameters.ClauseOrdering.CLAUSE_ACTIVITY, - ) - params.clause_cleanup_ordering = ( - sat_parameters_builder.SatParameters.ClauseOrdering.CLAUSE_LBD - ) - self.assertEqual( - params.clause_cleanup_ordering, - sat_parameters_builder.SatParameters.ClauseOrdering.CLAUSE_LBD, - ) - - # Test that we can set and get a repeated string parameter. - params.subsolvers.append("no_lp") - self.assertLen(params.subsolvers, 1) - self.assertEqual(params.subsolvers[0], "no_lp") - - -if __name__ == "__main__": - absltest.main() diff --git a/ortools/sat/python/wrappers.cc b/ortools/sat/python/wrappers.cc index b7bef4e925..2fd1539199 100644 --- a/ortools/sat/python/wrappers.cc +++ b/ortools/sat/python/wrappers.cc @@ -232,7 +232,7 @@ class Generator { // ptr. void GenerateRepeatedPtrDecl(const google::protobuf::Descriptor& msg) { absl::SubstituteAndAppend(&out_, R"( - py::class_>(py_module, "repeated_$1") + py::class_>(m, "repeated_$1") .def("add", [](google::protobuf::RepeatedPtrField<$0>* self) { return self->Add(); @@ -265,7 +265,7 @@ class Generator { void GenerateRepeatedScalarDecl(absl::string_view scalar_type) { if (scalar_type == "std::string") { absl::StrAppend(&out_, R"( - py::class_>(py_module, "repeated_scalar_std_string") + py::class_>(m, "repeated_scalar_std_string") .def("append", [](google::protobuf::RepeatedPtrField* self, std::string str) { self->Add(std::move(str)); @@ -299,7 +299,7 @@ class Generator { } else { absl::SubstituteAndAppend( &out_, R"( - py::class_>(py_module, "repeated_scalar_$1") + py::class_>(m, "repeated_scalar_$1") .def("append", [](google::protobuf::RepeatedField<$0>* self, $0 value) { self->Add(value); }) @@ -404,13 +404,13 @@ class Generator { } } - // Returns the wrapper name for a message (or "py_module" if `msg` is null). + // Returns the wrapper name for a message (or "m" if `msg` is null). // Dies if the scope is not found. std::string GetWrapperName(const google::protobuf::Descriptor* msg) { const auto it = wrapper_id_.find(msg); CHECK(it != wrapper_id_.end()) << "wrapper id not found: " << msg->full_name(); - if (msg == nullptr) return "py_module"; + if (msg == nullptr) return "m"; return absl::StrCat("gen_", it->second); }