From 18df536d12e79d3b76c752b406b7706600492639 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Thu, 24 Oct 2024 11:42:11 +0200 Subject: [PATCH] cherry-pick from the main branch --- cmake/dependencies/CMakeLists.txt | 12 +-- ortools/algorithms/knapsack_solver_test.cc | 4 + ortools/base/BUILD.bazel | 2 +- ortools/sat/cp_model_symmetries.cc | 9 +- ortools/sat/java/CpModelTest.java | 1 + ortools/sat/linear_programming_constraint.cc | 34 +++++++- ortools/sat/python/cp_model.py | 23 +++-- ortools/sat/python/cp_model_test.py | 29 ++++++- patches/{ZLIB.patch => ZLIB-v1.3.1.patch} | 0 patches/googletest-v1.15.2.patch | 29 ++++++- patches/highs-v1.8.0.patch | 77 +++++++++++++++++ patches/highs.patch | 88 -------------------- 12 files changed, 195 insertions(+), 113 deletions(-) rename patches/{ZLIB.patch => ZLIB-v1.3.1.patch} (100%) create mode 100644 patches/highs-v1.8.0.patch delete mode 100644 patches/highs.patch diff --git a/cmake/dependencies/CMakeLists.txt b/cmake/dependencies/CMakeLists.txt index 3cb8a62db5..868b5459eb 100644 --- a/cmake/dependencies/CMakeLists.txt +++ b/cmake/dependencies/CMakeLists.txt @@ -62,11 +62,12 @@ if(BUILD_ZLIB) list(APPEND CMAKE_MESSAGE_INDENT " ") set(ZLIB_BUILD_EXAMPLES OFF) FetchContent_Declare( - zlib + ZLIB GIT_REPOSITORY "https://github.com/madler/ZLIB.git" GIT_TAG "v1.3.1" - PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/ZLIB.patch") - FetchContent_MakeAvailable(zlib) + PATCH_COMMAND git apply --ignore-whitespace + "${CMAKE_CURRENT_LIST_DIR}/../../patches/ZLIB-v1.3.1.patch") + FetchContent_MakeAvailable(ZLIB) list(POP_BACK CMAKE_MESSAGE_INDENT) message(CHECK_PASS "fetched") endif() @@ -248,9 +249,10 @@ if(BUILD_HIGHS) FetchContent_Declare( highs GIT_REPOSITORY "https://github.com/ERGO-Code/HiGHS.git" - GIT_TAG "v1.7.2" + GIT_TAG "v1.8.0" GIT_SHALLOW TRUE - #PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/highs.patch" + PATCH_COMMAND git apply --ignore-whitespace + "${CMAKE_CURRENT_LIST_DIR}/../../patches/highs-v1.8.0.patch" ) FetchContent_MakeAvailable(highs) list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/ortools/algorithms/knapsack_solver_test.cc b/ortools/algorithms/knapsack_solver_test.cc index bce70b3e11..05efb92bd1 100644 --- a/ortools/algorithms/knapsack_solver_test.cc +++ b/ortools/algorithms/knapsack_solver_test.cc @@ -123,6 +123,7 @@ int64_t SolveKnapsackProblem( return kInvalidSolution; } +#ifdef USE_SCIP const int64_t scip_profit = SolveKnapsackProblemUsingSpecificSolver( profit_array, number_of_items, weight_array, capacity_array, number_of_dimensions, @@ -130,6 +131,9 @@ int64_t SolveKnapsackProblem( if (scip_profit != generic_profit) { return kInvalidSolution; } +#else +#warning SCIP support disable +#endif const int64_t cpsat_profit = SolveKnapsackProblemUsingSpecificSolver( profit_array, number_of_items, weight_array, capacity_array, diff --git a/ortools/base/BUILD.bazel b/ortools/base/BUILD.bazel index f67053959e..f1f205ec87 100644 --- a/ortools/base/BUILD.bazel +++ b/ortools/base/BUILD.bazel @@ -51,7 +51,7 @@ cc_library( ], copts = [ "-DOR_TOOLS_MAJOR=9", - "-DOR_TOOLS_MINOR=11", + "-DOR_TOOLS_MINOR=12", "-DOR_TOOLS_PATCH=9999", ], linkopts = select({ diff --git a/ortools/sat/cp_model_symmetries.cc b/ortools/sat/cp_model_symmetries.cc index ba07e97d1b..7713293410 100644 --- a/ortools/sat/cp_model_symmetries.cc +++ b/ortools/sat/cp_model_symmetries.cc @@ -1075,7 +1075,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { // TODO(user): Doing that is not always good, on cod105.mps, fixing variables // instead of letting the inner solver handle Boolean symmetries make the // problem unsolvable instead of easily solved. This is probably because this - // fixing do not exploit the full structure of these symmeteries. Note + // fixing do not exploit the full structure of these symmetries. Note // however that the fixing via propagation above close cod105 even more // efficiently. std::vector var_can_be_true_per_orbit(num_vars, -1); @@ -1526,6 +1526,11 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { } } + // The transformations below seems to hurt more than what they help. + // Especially when we handle symmetry during the search like with max_lp_sym + // worker. See for instance neos-948346.pb or map06.pb.gz. + if (params.symmetry_level() <= 3) return true; + // If we are left with a set of variable than can all be permuted, lets // break the symmetry by ordering them. if (orbitope.size() == 1) { @@ -1550,7 +1555,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { context->UpdateRuleStats("symmetry: added symmetry breaking inequality"); } context->UpdateNewConstraintsVariableUsage(); - } else if (orbitope.size() > 1 && params.symmetry_level() > 3) { + } else if (orbitope.size() > 1) { std::vector max_values(orbitope.size()); for (int i = 0; i < orbitope.size(); ++i) { const int var = orbitope[i][0]; diff --git a/ortools/sat/java/CpModelTest.java b/ortools/sat/java/CpModelTest.java index a2aced0009..fdc4454ff2 100644 --- a/ortools/sat/java/CpModelTest.java +++ b/ortools/sat/java/CpModelTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import com.google.ortools.Loader; import com.google.ortools.sat.CpSolverStatus; import com.google.ortools.sat.DecisionStrategyProto; +import com.google.ortools.sat.ElementConstraintProto; import com.google.ortools.sat.LinearArgumentProto; import com.google.ortools.util.Domain; import java.util.ArrayList; diff --git a/ortools/sat/linear_programming_constraint.cc b/ortools/sat/linear_programming_constraint.cc index 13bb74eb03..16ba825906 100644 --- a/ortools/sat/linear_programming_constraint.cc +++ b/ortools/sat/linear_programming_constraint.cc @@ -986,9 +986,30 @@ bool LinearProgrammingConstraint::SolveLp() { // are actually not part of the LP, they will just be at their bounds. for (const int orbit_index : orbit_indices_) { const IntegerVariable sum_var = symmetrizer_->OrbitSumVar(orbit_index); + const double lp_value = expanded_lp_solution_[sum_var]; const absl::Span orbit = symmetrizer_->Orbit(orbit_index); + // At level zero, we want to focus on the cuts, and we split the value + // evently across all the orbit. however at positive level we don't do + // cuts and we want values that make more sense to follow heuristically. + // In particular, if the sum_var is at its lower/upper bounds, we want + // the same for all variable from the orbit. This partially address the + // TODO below. + bool to_lower = false; + bool to_upper = false; + if (trail_->CurrentDecisionLevel() > 0) { + const double lb = + static_cast(integer_trail_->LowerBound(sum_var).value()); + const double ub = + static_cast(integer_trail_->UpperBound(sum_var).value()); + if (std::abs(lp_value - lb) < 1e-2) { + to_lower = true; + } else if (std::abs(lp_value - ub) < 1e-2) { + to_upper = true; + } + } + // We assign sum / orbit_size to each variables. // This is still an LP optimal, but not necessarily a good heuristic. // @@ -1002,8 +1023,7 @@ bool LinearProgrammingConstraint::SolveLp() { // domain for all variables in an orbit. Maybe we can generate two // solutions vectors, one for the cuts and one for the heuristics, or we // can add custom code to the cuts so that they don't depend on this. - const double new_value = - expanded_lp_solution_[sum_var] / static_cast(orbit.size()); + const double even_split = lp_value / static_cast(orbit.size()); // For the reduced costs, they are the same. There should be no // complication there. @@ -1011,6 +1031,16 @@ bool LinearProgrammingConstraint::SolveLp() { for (const IntegerVariable var : orbit) { const glop::ColIndex col = GetMirrorVariable(var); + + double new_value = even_split; + if (to_lower) { + new_value = + static_cast(integer_trail_->LowerBound(var).value()); + } else if (to_upper) { + new_value = + static_cast(integer_trail_->UpperBound(var).value()); + } + lp_solution_[col.value()] = new_value; expanded_lp_solution_[var] = new_value; expanded_lp_solution_[NegationOf(var)] = -new_value; diff --git a/ortools/sat/python/cp_model.py b/ortools/sat/python/cp_model.py index e6eca063a4..786aef5b9e 100644 --- a/ortools/sat/python/cp_model.py +++ b/ortools/sat/python/cp_model.py @@ -1578,9 +1578,12 @@ class CpModel: return ct def add_element( - self, index: VariableT, variables: Sequence[VariableT], target: VariableT + self, + index: LinearExprT, + expressions: Sequence[LinearExprT], + target: LinearExprT, ) -> Constraint: - """Adds the element constraint: `variables[index] == target`. + """Adds the element constraint: `expressions[index] == target`. Args: index: The index of the selected expression in the array. It must be an @@ -1593,18 +1596,20 @@ class CpModel: An instance of the `Constraint` class. """ - if not variables: - raise ValueError("add_element expects a non-empty variables array") + if not expressions: + raise ValueError("add_element expects a non-empty expressions array") if isinstance(index, IntegralTypes): - variable: VariableT = list(variables)[int(index)] - return self.add(variable == target) + expression: LinearExprT = list(expressions)[int(index)] + return self.add(expression == target) ct = Constraint(self) model_ct = self.__model.constraints[ct.index] - model_ct.element.index = self.get_or_make_index(index) - model_ct.element.vars.extend([self.get_or_make_index(x) for x in variables]) - model_ct.element.target = self.get_or_make_index(target) + model_ct.element.linear_index.CopyFrom(self.parse_linear_expression(index)) + model_ct.element.exprs.extend( + [self.parse_linear_expression(e) for e in expressions] + ) + model_ct.element.linear_target.CopyFrom(self.parse_linear_expression(target)) return ct def add_circuit(self, arcs: Sequence[ArcT]) -> Constraint: diff --git a/ortools/sat/python/cp_model_test.py b/ortools/sat/python/cp_model_test.py index 0843d6da38..61e1aea2f5 100644 --- a/ortools/sat/python/cp_model_test.py +++ b/ortools/sat/python/cp_model_test.py @@ -603,11 +603,11 @@ class CpModelTest(absltest.TestCase): model = cp_model.CpModel() x = [model.new_int_var(0, 4, "x%i" % i) for i in range(5)] model.add_element(x[0], [x[1], 2, 4, x[2]], x[4]) - self.assertLen(model.proto.variables, 7) + self.assertLen(model.proto.variables, 5) self.assertLen(model.proto.constraints, 1) - self.assertLen(model.proto.constraints[0].element.vars, 4) - self.assertEqual(0, model.proto.constraints[0].element.index) - self.assertEqual(4, model.proto.constraints[0].element.target) + self.assertLen(model.proto.constraints[0].element.exprs, 4) + self.assertEqual(0, model.proto.constraints[0].element.linear_index.vars[0]) + self.assertEqual(4, model.proto.constraints[0].element.linear_target.vars[0]) self.assertRaises(ValueError, model.add_element, x[0], [], x[4]) def testFixedElement(self) -> None: @@ -622,6 +622,27 @@ class CpModelTest(absltest.TestCase): self.assertEqual(1, model.proto.constraints[0].linear.coeffs[0]) self.assertEqual([2, 2], model.proto.constraints[0].linear.domain) + def testAffineElement(self) -> None: + print("testAffineElement") + model = cp_model.CpModel() + x = [model.new_int_var(0, 4, "x%i" % i) for i in range(5)] + model.add_element(x[0] + 1, [2 * x[1] - 2, 2, 4, x[2]], x[4] - 1) + self.assertLen(model.proto.variables, 5) + self.assertLen(model.proto.constraints, 1) + self.assertLen(model.proto.constraints[0].element.exprs, 4) + self.assertEqual(0, model.proto.constraints[0].element.linear_index.vars[0]) + self.assertEqual(1, model.proto.constraints[0].element.linear_index.coeffs[0]) + self.assertEqual(1, model.proto.constraints[0].element.linear_index.offset) + + self.assertEqual(4, model.proto.constraints[0].element.linear_target.vars[0]) + self.assertEqual(1, model.proto.constraints[0].element.linear_target.coeffs[0]) + self.assertEqual(-1, model.proto.constraints[0].element.linear_target.offset) + self.assertEqual(4, model.proto.constraints[0].element.linear_target.vars[0]) + expr0 = model.proto.constraints[0].element.exprs[0] + self.assertEqual(1, expr0.vars[0]) + self.assertEqual(2, expr0.coeffs[0]) + self.assertEqual(-2, expr0.offset) + def testCircuit(self) -> None: print("testCircuit") model = cp_model.CpModel() diff --git a/patches/ZLIB.patch b/patches/ZLIB-v1.3.1.patch similarity index 100% rename from patches/ZLIB.patch rename to patches/ZLIB-v1.3.1.patch diff --git a/patches/googletest-v1.15.2.patch b/patches/googletest-v1.15.2.patch index 1d5da3c1f9..7cc0f099b0 100644 --- a/patches/googletest-v1.15.2.patch +++ b/patches/googletest-v1.15.2.patch @@ -1,8 +1,33 @@ diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake -index 580ac1c..c6cc44c 100644 +index 580ac1c..96fe3ac 100644 --- a/googletest/cmake/internal_utils.cmake +++ b/googletest/cmake/internal_utils.cmake -@@ -190,6 +190,13 @@ function(cxx_library_with_type name type cxx_flags) +@@ -11,6 +11,7 @@ + # - The functions/macros defined in this file may depend on Google + # Test and Google Mock's option() definitions, and thus must be + # called *after* the options have been defined. ++include(GNUInstallDirs) + + # Tweaks CMake's default compiler/linker settings to suit Google Test's needs. + # +@@ -170,11 +171,11 @@ function(cxx_library_with_type name type cxx_flags) + # Set the output directory for build artifacts. + set_target_properties(${name} + PROPERTIES +- RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +- LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" +- ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" +- PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +- COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") ++ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" ++ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" ++ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" ++ PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" ++ COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + # Make PDBs match library name. + get_target_property(pdb_debug_postfix ${name} DEBUG_POSTFIX) + set_target_properties(${name} +@@ -190,6 +191,13 @@ function(cxx_library_with_type name type cxx_flags) COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1") target_compile_definitions(${name} INTERFACE $) diff --git a/patches/highs-v1.8.0.patch b/patches/highs-v1.8.0.patch new file mode 100644 index 0000000000..3914d9c455 --- /dev/null +++ b/patches/highs-v1.8.0.patch @@ -0,0 +1,77 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index aa593028..8103fef8 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -100,19 +100,19 @@ if (BUILD_CXX) + message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") + endif() + ++ # Layout build dir like install dir + include(GNUInstallDirs) +- + if(UNIX) + option(BUILD_SHARED_LIBS "Build shared libraries (.so or .dyld)." ON) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + # for multi-config build system (e.g. xcode) +- foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) +- string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG) +- set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_LIBDIR}) +- set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_LIBDIR}) +- set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR}) ++ foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) ++ string(TOUPPER ${OutputConfig} OUTPUTCONFIG) ++ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_LIBDIR}) ++ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_LIBDIR}) ++ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) + endforeach() + else() + option(BUILD_SHARED_LIBS "Build shared libraries (.dll)." OFF) +@@ -120,14 +120,11 @@ if (BUILD_CXX) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + # for multi-config builds (e.g. msvc) +- foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) +- string(TOLOWER ${OUTPUTCONFIG} OUTPUTCONFIG) +- set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/${OUTPUTCONFIG}) +- set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/${OUTPUTCONFIG}) +- set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/${OUTPUTCONFIG}) +- # set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR}) +- # set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR}) +- # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR}) ++ foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) ++ string(TOUPPER ${OutputConfig} OUTPUTCONFIG) ++ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) ++ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) ++ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) + endforeach() + endif() + +@@ -171,7 +168,7 @@ if (BUILD_CXX) + check_type_size("int *" SIZEOF_INT_P LANGUAGE CXX) + message(STATUS "Found int * size: ${SIZEOF_INT_P}") + cmake_pop_check_state() +- ++ + # Use current CMAKE_C_FLAGS and CMAKE_CXX_FLAGS when checking for IPO support, + # instead of defaults: https://cmake.org/cmake/help/latest/policy/CMP0138.html + if(MSVC AND BUILD_SHARED_LIBS) +@@ -189,7 +186,7 @@ if (BUILD_CXX) + set(ipo_supported NO) + message(STATUS "IPO / LTO not currently supported building HiGHS on MinGW") + else() +- if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") ++ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") + cmake_policy(SET CMP0138 NEW) + endif() + +@@ -320,7 +317,7 @@ if(MSVC) + add_compile_options("$<$:-D_CRT_SECURE_NO_WARNINGS>") + add_compile_options("$<$:/MP>") + +- # Try to split large pdb files into objects. ++ # Try to split large pdb files into objects. + # https://github.com/tensorflow/tensorflow/issues/31610 + add_compile_options("/Z7") + add_link_options("/DEBUG:FASTLINK") diff --git a/patches/highs.patch b/patches/highs.patch deleted file mode 100644 index 5975d50788..0000000000 --- a/patches/highs.patch +++ /dev/null @@ -1,88 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 22b0048cd..e8beb5db0 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -50,7 +50,7 @@ endif() - - option(PYTHON_BUILD_SETUP "Build Python interface from setup.py" OFF) - message(STATUS "Build Python: ${PYTHON_BUILD_SETUP}") --if (PYTHON_BUILD_SETUP) -+if (PYTHON_BUILD_SETUP) - set(BUILD_CXX OFF) - set(BUILD_TESTING OFF) - endif() -@@ -64,7 +64,7 @@ message(STATUS "Build all tests: ${ALL_TESTS}") - - option(ZLIB "ZLIB" ON) - message(STATUS "ZLIB: ${ZLIB}") --if (PYTHON_BUILD_SETUP) -+if (PYTHON_BUILD_SETUP) - set(ZLIB OFF) - endif() - -@@ -181,7 +181,7 @@ if (BUILD_CXX) - endif() - endif() - --endif() -+endif() - - include(CheckCXXSourceCompiles) - check_cxx_source_compiles( -@@ -297,7 +297,7 @@ if(MSVC) - add_compile_options("$<$:-D_CRT_SECURE_NO_WARNINGS>") - add_compile_options("$<$:/MP>") - -- # Try to split large pdb files into objects. -+ # Try to split large pdb files into objects. - # https://github.com/tensorflow/tensorflow/issues/31610 - add_compile_options("/Z7") - add_link_options("/DEBUG:FASTLINK") -@@ -353,7 +353,7 @@ endif() - # set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined") - - # if zlib is found, then we can enable reading zlib-compressed input --if(ZLIB) -+if(ZLIB AND NOT TARGET ZLIB::ZLIB) - find_package(ZLIB 1.2.3) - endif() - -@@ -455,7 +455,7 @@ if(NOT FAST_BUILD) - COMMENT "Resetting code coverage counters to zero.") - endif() - endif() -- -+ - include_directories( - ${HIGHS_BINARY_DIR} - ${HIGHS_SOURCE_DIR}/app -@@ -496,7 +496,7 @@ if(NOT FAST_BUILD) - - else(FAST_BUILD) - message(STATUS "FAST_BUILD set to on.") -- -+ - option(BUILD_EXAMPLES "Build examples" ON) - message(STATUS "Build examples: ${BUILD_EXAMPLES}") - -diff --git a/cmake/sources.cmake b/cmake/sources.cmake -index cdf109699..e9e1362af 100644 ---- a/cmake/sources.cmake -+++ b/cmake/sources.cmake -@@ -128,7 +128,7 @@ set(ipx_sources - ipm/ipx/symbolic_invert.cc - ipm/ipx/timer.cc - ipm/ipx/utils.cc) -- -+ - set(ipx_headers - ipm/ipx/basiclu_kernel.h - ipm/ipx/basiclu_wrapper.h -@@ -186,6 +186,7 @@ set(highs_sources - lp_data/HighsDebug.cpp - lp_data/HighsInfo.cpp - lp_data/HighsInfoDebug.cpp -+ lp_data/HighsDeprecated.cpp - lp_data/HighsInterface.cpp - lp_data/HighsLp.cpp - lp_data/HighsLpUtils.cpp