From a28699198cb215839906a041db1a177d39372460 Mon Sep 17 00:00:00 2001 From: Trevor McKay Date: Fri, 11 Jul 2025 14:43:17 -0400 Subject: [PATCH 01/12] add a simple smoketest for cvxpy --- ci/external/cvxpy_smoketest.sh | 31 +++++++++++++++++++++++++++++++ ci/test_wheel_cuopt.sh | 1 + 2 files changed, 32 insertions(+) create mode 100755 ci/external/cvxpy_smoketest.sh diff --git a/ci/external/cvxpy_smoketest.sh b/ci/external/cvxpy_smoketest.sh new file mode 100755 index 000000000..f112a5481 --- /dev/null +++ b/ci/external/cvxpy_smoketest.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# 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. + + +git clone -b cuopt_solver https://github.com/tmckayus/cvxpy +pushd cvxpy || exit 1 +pip install pytest-error-for-skips +pip install -e . +python -m pytest --error-for-skips cvxpy/tests/test_conic_solvers.py -k "TestCUOPT" +EXITCODE="$?" +if [ "$EXITCODE" -eq 0 ]; then + echo PASSED smoketest +else + echo FAILED smoketest +fi +popd || exit 1 +exit $EXITCODE diff --git a/ci/test_wheel_cuopt.sh b/ci/test_wheel_cuopt.sh index 3c78c29f0..c1dc5dd32 100755 --- a/ci/test_wheel_cuopt.sh +++ b/ci/test_wheel_cuopt.sh @@ -59,3 +59,4 @@ timeout 10m bash ./python/libcuopt/libcuopt/tests/test_cli.sh # Run Python tests RAPIDS_DATASET_ROOT_DIR=./datasets timeout 30m python -m pytest --verbose --capture=no ./python/cuopt/cuopt/tests/ +timeout 3m ./ci/external/cvxpy_smoketest.sh From a609cfc2c881c2e01d36b04ddc70d0c4dde7b999 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Mon, 14 Jul 2025 20:51:19 -0500 Subject: [PATCH 02/12] refactor tests --- .github/workflows/pr.yaml | 2 +- ci/external/cvxpy_smoketest.sh | 31 ------------------------------- ci/test_wheel_cuopt.sh | 27 ++++++++++++++++++++++++++- 3 files changed, 27 insertions(+), 33 deletions(-) delete mode 100755 ci/external/cvxpy_smoketest.sh diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index d21d8e4d3..7aef0f9e1 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -188,7 +188,7 @@ jobs: package-type: python matrix_filter: map(select((.CUDA_VER | startswith("12")))) wheel-tests-cuopt: - needs: [wheel-build-cuopt, wheel-build-cuopt-mps-parser, changed-files] + needs: [wheel-build-cuopt, wheel-build-cuopt-mps-parser, wheel-build-cuopt-sh-client, changed-files] secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@branch-25.08 #if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_cuopt diff --git a/ci/external/cvxpy_smoketest.sh b/ci/external/cvxpy_smoketest.sh deleted file mode 100755 index f112a5481..000000000 --- a/ci/external/cvxpy_smoketest.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -# 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. - - -git clone -b cuopt_solver https://github.com/tmckayus/cvxpy -pushd cvxpy || exit 1 -pip install pytest-error-for-skips -pip install -e . -python -m pytest --error-for-skips cvxpy/tests/test_conic_solvers.py -k "TestCUOPT" -EXITCODE="$?" -if [ "$EXITCODE" -eq 0 ]; then - echo PASSED smoketest -else - echo FAILED smoketest -fi -popd || exit 1 -exit $EXITCODE diff --git a/ci/test_wheel_cuopt.sh b/ci/test_wheel_cuopt.sh index c1dc5dd32..0f13dfea4 100755 --- a/ci/test_wheel_cuopt.sh +++ b/ci/test_wheel_cuopt.sh @@ -59,4 +59,29 @@ timeout 10m bash ./python/libcuopt/libcuopt/tests/test_cli.sh # Run Python tests RAPIDS_DATASET_ROOT_DIR=./datasets timeout 30m python -m pytest --verbose --capture=no ./python/cuopt/cuopt/tests/ -timeout 3m ./ci/external/cvxpy_smoketest.sh +# run cvxpy integration tests +rapids-logger "building 'cvxpy' from source" +git clone -b cuopt_solver https://github.com/tmckayus/cvxpy +pushd ./cvxpy || exit 1 +python -m build \ + --wheel \ + --outdir dist \ + . + +# NOTE: installing cvxpy[CUOPT] alongside CI artifacts is helpful to catch dependency conflicts +rapids-logger "installing 'cvxpy' with cuopt" +CUOPT_SH_CLIENT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_sh_client" rapids-download-wheels-from-github python) +python -m pip install \ + --extra-index-url=https://pypi.nvidia.com \ + "${CUOPT_MPS_PARSER_WHEELHOUSE}"/cuopt_mps_parser*.whl \ + "${CUOPT_SH_CLIENT_WHEELHOUSE}"/cuopt_sh_client*.whl \ + "${CUOPT_WHEELHOUSE}"/cuopt*.whl \ + "${LIBCUOPT_WHEELHOUSE}"/libcuopt*.whl \ + 'pytest-error-for-skips>=2.0.2' \ + "$(echo ./dist/cvxpy*.whl)[CUOPT,testing]" + +rapids-logger "running 'cvxpy' tests" +python -m pytest \ + --error-for-skips \ + -k "TestCUOPT" \ + ./cvxpy/tests/test_conic_solvers.py From 1a715468fc0e8a5e154613e87efdfae3cbcf6213 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Mon, 14 Jul 2025 20:55:15 -0500 Subject: [PATCH 03/12] add 3 minute timeout on tests --- ci/test_wheel_cuopt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test_wheel_cuopt.sh b/ci/test_wheel_cuopt.sh index 0f13dfea4..9051571d8 100755 --- a/ci/test_wheel_cuopt.sh +++ b/ci/test_wheel_cuopt.sh @@ -81,7 +81,7 @@ python -m pip install \ "$(echo ./dist/cvxpy*.whl)[CUOPT,testing]" rapids-logger "running 'cvxpy' tests" -python -m pytest \ +timeout 3m python -m pytest \ --error-for-skips \ -k "TestCUOPT" \ ./cvxpy/tests/test_conic_solvers.py From 8c58eb329be4812f3d72731a52581f20329aafb9 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Wed, 16 Jul 2025 12:47:30 -0500 Subject: [PATCH 04/12] use pip wheel instead of build --- ci/test_wheel_cuopt.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ci/test_wheel_cuopt.sh b/ci/test_wheel_cuopt.sh index 9051571d8..290d2ebae 100755 --- a/ci/test_wheel_cuopt.sh +++ b/ci/test_wheel_cuopt.sh @@ -63,9 +63,8 @@ RAPIDS_DATASET_ROOT_DIR=./datasets timeout 30m python -m pytest --verbose --capt rapids-logger "building 'cvxpy' from source" git clone -b cuopt_solver https://github.com/tmckayus/cvxpy pushd ./cvxpy || exit 1 -python -m build \ - --wheel \ - --outdir dist \ +pip wheel \ + -w dist \ . # NOTE: installing cvxpy[CUOPT] alongside CI artifacts is helpful to catch dependency conflicts From d62cb038ea650455e1e1fb24b2e1c98dd5321120 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Fri, 18 Jul 2025 09:40:51 -0500 Subject: [PATCH 05/12] move cvxpy tests back into their own file --- ci/test_wheel_cuopt.sh | 37 ++++++++-------------- ci/thirdparty-testing/run_cvxpy_tests.sh | 39 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 24 deletions(-) create mode 100755 ci/thirdparty-testing/run_cvxpy_tests.sh diff --git a/ci/test_wheel_cuopt.sh b/ci/test_wheel_cuopt.sh index 290d2ebae..2bb5af435 100755 --- a/ci/test_wheel_cuopt.sh +++ b/ci/test_wheel_cuopt.sh @@ -17,14 +17,26 @@ set -euo pipefail +# sets up a constraints file for 'pip' and puts its location in an exported variable PIP_EXPORT, +# so those constraints will affect all future 'pip install' calls source rapids-init-pip # Download the packages built in the previous step RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen "${RAPIDS_CUDA_VERSION}")" CUOPT_MPS_PARSER_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_mps_parser" rapids-download-wheels-from-github python) +CUOPT_SH_CLIENT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_sh_client" rapids-download-wheels-from-github python) CUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-github python) LIBCUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="libcuopt_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-github cpp) +# update pip constraints.txt to ensure all future 'pip install' (including those in ci/thirdparty-testing) +# use these wheels for cuopt packages +cat > "${PIP_CONSTRAINT}" <=2.0.2' \ - "$(echo ./dist/cvxpy*.whl)[CUOPT,testing]" - -rapids-logger "running 'cvxpy' tests" -timeout 3m python -m pytest \ - --error-for-skips \ - -k "TestCUOPT" \ - ./cvxpy/tests/test_conic_solvers.py +./ci/thirdparty-testing/run_cvxpy_tests.sh diff --git a/ci/thirdparty-testing/run_cvxpy_tests.sh b/ci/thirdparty-testing/run_cvxpy_tests.sh new file mode 100755 index 000000000..4ab213af4 --- /dev/null +++ b/ci/thirdparty-testing/run_cvxpy_tests.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# 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. + +set -e -u -o pipefail + +echo "building 'cvxpy' from source" +git clone -b cuopt_solver https://github.com/tmckayus/cvxpy +pushd ./cvxpy || exit 1 +pip wheel \ + -w dist \ + . + +# NOTE: installing cvxpy[CUOPT] alongside CI artifacts is helpful to catch dependency conflicts +echo "installing 'cvxpy' with cuopt" +python -m pip install \ + --constraint "${PIP_CONSTRAINT}" \ + --extra-index-url=https://pypi.nvidia.com \ + --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple \ + 'pytest-error-for-skips>=2.0.2' \ + "$(echo ./dist/cvxpy*.whl)[CUOPT,testing]" + +echo "running 'cvxpy' tests" +timeout 3m python -m pytest \ + --error-for-skips \ + -k "TestCUOPT" \ + ./cvxpy/tests/test_conic_solvers.py From 43b69c1132ee0230dd0a64fa0c42d15aa1fa90a2 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 21 Jul 2025 12:23:53 -0500 Subject: [PATCH 06/12] fix cvxpy target branch --- ci/thirdparty-testing/run_cvxpy_tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/thirdparty-testing/run_cvxpy_tests.sh b/ci/thirdparty-testing/run_cvxpy_tests.sh index 4ab213af4..ae5f82e73 100755 --- a/ci/thirdparty-testing/run_cvxpy_tests.sh +++ b/ci/thirdparty-testing/run_cvxpy_tests.sh @@ -17,7 +17,7 @@ set -e -u -o pipefail echo "building 'cvxpy' from source" -git clone -b cuopt_solver https://github.com/tmckayus/cvxpy +git clone -b cuopt_solver https://github.com/cvxpy/cvxpy.git pushd ./cvxpy || exit 1 pip wheel \ -w dist \ @@ -36,4 +36,4 @@ echo "running 'cvxpy' tests" timeout 3m python -m pytest \ --error-for-skips \ -k "TestCUOPT" \ - ./cvxpy/tests/test_conic_solvers.py + ./tests/test_conic_solvers.py From 8ccfa802af238526b3c489380003e46560adfbac Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 21 Jul 2025 17:09:13 -0500 Subject: [PATCH 07/12] update test script --- ci/test_wheel_cuopt.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ci/test_wheel_cuopt.sh b/ci/test_wheel_cuopt.sh index 2bb5af435..7a16db43f 100755 --- a/ci/test_wheel_cuopt.sh +++ b/ci/test_wheel_cuopt.sh @@ -31,17 +31,19 @@ LIBCUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="libcuopt_${RAPIDS_PY_CUDA_SUFFIX}" r # update pip constraints.txt to ensure all future 'pip install' (including those in ci/thirdparty-testing) # use these wheels for cuopt packages cat > "${PIP_CONSTRAINT}" < Date: Tue, 22 Jul 2025 15:01:02 -0500 Subject: [PATCH 08/12] fix tests --- ci/thirdparty-testing/run_cvxpy_tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/thirdparty-testing/run_cvxpy_tests.sh b/ci/thirdparty-testing/run_cvxpy_tests.sh index ae5f82e73..1b96825db 100755 --- a/ci/thirdparty-testing/run_cvxpy_tests.sh +++ b/ci/thirdparty-testing/run_cvxpy_tests.sh @@ -17,7 +17,7 @@ set -e -u -o pipefail echo "building 'cvxpy' from source" -git clone -b cuopt_solver https://github.com/cvxpy/cvxpy.git +git clone https://github.com/cvxpy/cvxpy.git pushd ./cvxpy || exit 1 pip wheel \ -w dist \ @@ -36,4 +36,4 @@ echo "running 'cvxpy' tests" timeout 3m python -m pytest \ --error-for-skips \ -k "TestCUOPT" \ - ./tests/test_conic_solvers.py + ./cvxpy/tests/test_conic_solvers.py From a2d14fc2211bbce157d3a31de382dce1274fc0d6 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Thu, 24 Jul 2025 15:50:44 -0500 Subject: [PATCH 09/12] debug --- ci/thirdparty-testing/run_cvxpy_tests.sh | 2 ++ cpp/src/mip/problem/problem.cu | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ci/thirdparty-testing/run_cvxpy_tests.sh b/ci/thirdparty-testing/run_cvxpy_tests.sh index 1b96825db..df111c14f 100755 --- a/ci/thirdparty-testing/run_cvxpy_tests.sh +++ b/ci/thirdparty-testing/run_cvxpy_tests.sh @@ -34,6 +34,8 @@ python -m pip install \ echo "running 'cvxpy' tests" timeout 3m python -m pytest \ + --verbose \ + --capture=no \ --error-for-skips \ -k "TestCUOPT" \ ./cvxpy/tests/test_conic_solvers.py diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index 888388ef1..a06100ce7 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -1208,6 +1208,9 @@ void problem_t::remove_given_variables(problem_t& original_p { thrust::fill(handle_ptr->get_thrust_policy(), offsets.begin(), offsets.end(), 0); cuopt_assert(assignment.size() == n_variables, "Variable size mismatch"); + std::cout << "variable_map size " << variable_map.size() << std::endl; + std::cout << "n_variables " << n_variables << std::endl; + printf("variable_map size %zu n_variables %d\n", variable_map.size(), n_variables); cuopt_assert(variable_map.size() < n_variables, "Too many variables to fix"); rmm::device_uvector tmp_assignment(assignment, handle_ptr->get_stream()); From d85fd8efa7ff6845ada4040499d643218b9c8144 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 28 Jul 2025 17:23:25 -0500 Subject: [PATCH 10/12] fix style --- cpp/src/mip/problem/problem.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index a06100ce7..62b595487 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -1210,7 +1210,7 @@ void problem_t::remove_given_variables(problem_t& original_p cuopt_assert(assignment.size() == n_variables, "Variable size mismatch"); std::cout << "variable_map size " << variable_map.size() << std::endl; std::cout << "n_variables " << n_variables << std::endl; - printf("variable_map size %zu n_variables %d\n", variable_map.size(), n_variables); + printf("variable_map size %zu n_variables %d\n", variable_map.size(), n_variables); cuopt_assert(variable_map.size() < n_variables, "Too many variables to fix"); rmm::device_uvector tmp_assignment(assignment, handle_ptr->get_stream()); From 355bfd4875f0c1008fecb0c8a89c0ea976531c29 Mon Sep 17 00:00:00 2001 From: Ramakrishnap <42624703+rgsl888prabhu@users.noreply.github.com> Date: Wed, 30 Jul 2025 14:03:11 -0500 Subject: [PATCH 11/12] Update ci/thirdparty-testing/run_cvxpy_tests.sh Co-authored-by: James Lamb --- ci/thirdparty-testing/run_cvxpy_tests.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/thirdparty-testing/run_cvxpy_tests.sh b/ci/thirdparty-testing/run_cvxpy_tests.sh index df111c14f..523b2fea3 100755 --- a/ci/thirdparty-testing/run_cvxpy_tests.sh +++ b/ci/thirdparty-testing/run_cvxpy_tests.sh @@ -32,6 +32,9 @@ python -m pip install \ 'pytest-error-for-skips>=2.0.2' \ "$(echo ./dist/cvxpy*.whl)[CUOPT,testing]" +# ensure that environment is still consistent (i.e. cvxpy requirements do not conflict with cuopt's) +pip check + echo "running 'cvxpy' tests" timeout 3m python -m pytest \ --verbose \ From 99d0056f9c28995c0425ec0cf5143504b21b6a31 Mon Sep 17 00:00:00 2001 From: Ramakrishnap <42624703+rgsl888prabhu@users.noreply.github.com> Date: Wed, 30 Jul 2025 15:01:27 -0500 Subject: [PATCH 12/12] Update problem.cu --- cpp/src/mip/problem/problem.cu | 3 --- 1 file changed, 3 deletions(-) diff --git a/cpp/src/mip/problem/problem.cu b/cpp/src/mip/problem/problem.cu index 62b595487..888388ef1 100644 --- a/cpp/src/mip/problem/problem.cu +++ b/cpp/src/mip/problem/problem.cu @@ -1208,9 +1208,6 @@ void problem_t::remove_given_variables(problem_t& original_p { thrust::fill(handle_ptr->get_thrust_policy(), offsets.begin(), offsets.end(), 0); cuopt_assert(assignment.size() == n_variables, "Variable size mismatch"); - std::cout << "variable_map size " << variable_map.size() << std::endl; - std::cout << "n_variables " << n_variables << std::endl; - printf("variable_map size %zu n_variables %d\n", variable_map.size(), n_variables); cuopt_assert(variable_map.size() < n_variables, "Too many variables to fix"); rmm::device_uvector tmp_assignment(assignment, handle_ptr->get_stream());