-
Notifications
You must be signed in to change notification settings - Fork 112
Add C api callbacks for getting and setting solutions #779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughAdds optional user_data propagation to MIP solution callbacks across C, C++, and Python layers. Introduces new C API MIP callback registration functions, extends callback interfaces and invocation sites to accept a user_data pointer, and updates tests and bindings to pass and validate this pointer. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
🔇 Additional comments (4)
✏️ Tip: You can disable this entire section by setting Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In `@cpp/include/cuopt/linear_programming/cuopt_c.h`:
- Around line 706-728: The Doxygen for cuOptSetMipGetSolutionCallback and
cuOptSetMipSetSolutionCallback is missing documentation for the new user_data
parameter; update both comment blocks to add a `@param`[in] user_data description
(e.g., "User-defined pointer passed through to the callback") and mention that
it will be forwarded to the respective
cuOptMipGetSolutionCallback/cuOptMipSetSolutionCallback when invoked so the
public API documents the parameter contract.
In `@cpp/include/cuopt/linear_programming/mip/solver_settings.hpp`:
- Around line 37-41: Update the Doxygen block for set_mip_callback to document
the new user_data parameter: add a brief `@param` description for user_data
explaining it is an opaque pointer passed to the callback (e.g., "pointer to
user-defined data forwarded to the callback"), and ensure the existing `@param`
for callback remains accurate; modify the comment above the function declaration
in solver_settings.hpp (the set_mip_callback declaration) so the public API docs
enumerate both callback and user_data.
In `@cpp/include/cuopt/linear_programming/utilities/internals.hpp`:
- Around line 34-36: Add brief Doxygen comments above the public accessor
methods set_user_data and get_user_data describing their purpose: annotate
set_user_data with "Store user-defined context data for callback invocation."
and get_user_data with "Retrieve user-defined context data passed to callbacks."
Place these comments immediately above the corresponding method declarations in
internals.hpp so the public solver callback interface methods are documented per
the header-file documentation guideline.
In `@cpp/src/mip/diversity/diversity_manager.cu`:
- Around line 446-450: There is an unconditional exit(0) that aborts the solver
flow and prevents LP solution handling; remove the exit(0) invocation so
execution continues into the subsequent LP handling (the if
(ls.lp_optimal_exists) block) after calling clamp_within_var_bounds, ensuring
normal callback and MIP behavior; search for the symbols
clamp_within_var_bounds, exit(0), and ls.lp_optimal_exists to locate and delete
the exit call so control can proceed.
In `@cpp/src/mip/solver_settings.cu`:
- Around line 27-31: The set_mip_callback function currently pushes a nullptr
into mip_callbacks_ because it only guards the set_user_data call; update
mip_solver_settings_t<i_t, f_t>::set_mip_callback to first check if callback is
nullptr and if so do not push it (either return early or ignore the call),
otherwise call callback->set_user_data(user_data) and then push_back(callback)
so mip_callbacks_ never contains null entries; this ensures later dereferences
of entries in mip_callbacks_ (e.g., where callbacks are invoked) are safe.
In `@python/cuopt/cuopt/linear_programming/internals/internals.pyx`:
- Around line 70-76: The runtime AttributeError happens because _user_data is
assigned dynamically in the cdef classes; declare the attribute in both callback
extension types (e.g., in the class body of GetSolutionCallback and
SetSolutionCallback) as a Cython Python-object attribute like "cdef object
_user_data" (or "cdef public object _user_data" if you need external access),
then keep the existing __init__ assignment and the get_user_data_ptr cast that
uses self._user_data; ensure the declaration appears in both classes so lines
assigning/reading _user_data no longer raise.
🧹 Nitpick comments (1)
cpp/include/cuopt/linear_programming/solver_settings.hpp (1)
84-85: Documentuser_dataownership/lifetime in the public API.Adding a brief Doxygen note will clarify that the pointer must remain valid for the duration of callback usage and that it’s passed through verbatim.
✍️ Suggested doc addition
- void set_mip_callback(internals::base_solution_callback_t* callback = nullptr, - void* user_data = nullptr); + /** + * Register a MIP solution callback. + * `@param` callback Callback instance (must outlive solver usage). + * `@param` user_data Opaque pointer passed back to the callback; must remain valid + * while the callback can be invoked. + */ + void set_mip_callback(internals::base_solution_callback_t* callback = nullptr, + void* user_data = nullptr);As per coding guidelines, public headers should keep docs in sync with API changes.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/include/cuopt/linear_programming/solver_settings.hppcpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/include/cuopt/linear_programming/utilities/internals.hppcpp/src/linear_programming/cuopt_c.cppcpp/src/math_optimization/solver_settings.cucpp/src/mip/diversity/diversity_manager.cucpp/src/mip/diversity/population.cucpp/src/mip/solver_settings.cucpp/tests/linear_programming/c_api_tests/c_api_test.ccpp/tests/mip/incumbent_callback_test.cupython/cuopt/cuopt/linear_programming/internals/internals.pyxpython/cuopt/cuopt/linear_programming/solver/solver.pxdpython/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyxpython/cuopt/cuopt/linear_programming/solver_settings/solver_settings.py
🚧 Files skipped from review as they are similar to previous changes (1)
- cpp/src/linear_programming/cuopt_c.cpp
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{cu,cuh,cpp,hpp,h}
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
**/*.{cu,cuh,cpp,hpp,h}: Track GPU device memory allocations and deallocations to prevent memory leaks; ensure cudaMalloc/cudaFree balance and cleanup of streams/events
Validate algorithm correctness in optimization logic: simplex pivots, branch-and-bound decisions, routing heuristics, and constraint/objective handling must produce correct results
Check numerical stability: prevent overflow/underflow, precision loss, division by zero/near-zero, and use epsilon comparisons for floating-point equality checks
Validate correct initialization of variable bounds, constraint coefficients, and algorithm state before solving; ensure reset when transitioning between algorithm phases (presolve, simplex, diving, crossover)
Ensure variables and constraints are accessed from the correct problem context (original vs presolve vs folded vs postsolve); verify index mapping consistency across problem transformations
For concurrent CUDA operations (barriers, async operations), explicitly create and manage dedicated streams instead of reusing the default stream; document stream lifecycle
Eliminate unnecessary host-device synchronization (cudaDeviceSynchronize) in hot paths that blocks GPU pipeline; use streams and events for async execution
Assess algorithmic complexity for large-scale problems (millions of variables/constraints); ensure O(n log n) or better complexity, not O(n²) or worse
Verify correct problem size checks before expensive GPU/CPU operations; prevent resource exhaustion on oversized problems
Identify assertions with overly strict numerical tolerances that fail on legitimate degenerate/edge cases (near-zero pivots, singular matrices, empty problems)
Ensure race conditions are absent in multi-GPU code and multi-threaded server implementations; verify proper synchronization of shared state
Refactor code duplication in solver components (3+ occurrences) into shared utilities; for GPU kernels, use templated device functions to avoid duplication
Check that hard-coded GPU de...
Files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cucpp/include/cuopt/linear_programming/utilities/internals.hpp
**/*.{h,hpp,py}
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
Verify C API does not break ABI stability (no struct layout changes, field reordering); maintain backward compatibility in Python and server APIs with deprecation warnings
Files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hpppython/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pycpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/include/cuopt/linear_programming/utilities/internals.hpp
**/*.{cpp,hpp,h}
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
**/*.{cpp,hpp,h}: Check for unclosed file handles when reading MPS/QPS problem files; ensure RAII patterns or proper cleanup in exception paths
Validate input sanitization to prevent buffer overflows and resource exhaustion attacks; avoid unsafe deserialization of problem files
Prevent thread-unsafe use of global and static variables; use proper mutex/synchronization in server code accessing shared solver state
Files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/include/cuopt/linear_programming/utilities/internals.hpp
**/*.{cu,cpp,hpp,h}
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
Avoid inappropriate use of exceptions in performance-critical GPU operation paths; prefer error codes or CUDA error checking for latency-sensitive code
Files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cucpp/include/cuopt/linear_programming/utilities/internals.hpp
cpp/include/cuopt/**/*
⚙️ CodeRabbit configuration file
cpp/include/cuopt/**/*: For public header files (C++ API):
- Check if new public functions/classes have documentation comments (Doxygen format)
- Flag API changes that may need corresponding docs/ updates
- Verify parameter descriptions match actual types/behavior
- Suggest documenting thread-safety, GPU requirements, and numerical behavior
- For breaking changes, recommend updating docs and migration guides
Files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/include/cuopt/linear_programming/utilities/internals.hpp
**/*.{cu,cuh}
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
**/*.{cu,cuh}: Every CUDA kernel launch and memory operation must have error checking with CUDA_CHECK or equivalent verification
Avoid reinventing functionality already available in Thrust, CCCL, or RMM libraries; prefer standard library utilities over custom implementations
Files:
cpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/src/mip/diversity/population.cucpp/src/mip/diversity/diversity_manager.cu
**/*.cu
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
**/*.cu: Verify race conditions and correctness of GPU kernel shared memory, atomics, and warp-level operations
Detect inefficient GPU kernel launches with low occupancy or poor memory access patterns; optimize for coalesced memory access and minimize warp divergence in hot paths
Files:
cpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/src/mip/diversity/population.cucpp/src/mip/diversity/diversity_manager.cu
**/*test*.{cpp,cu,py}
📄 CodeRabbit inference engine (.github/.coderabbit_review_guide.md)
**/*test*.{cpp,cu,py}: Write tests validating numerical correctness of optimization results (not just 'runs without error'); test degenerate cases (infeasible, unbounded, empty, singleton problems)
Ensure test isolation: prevent GPU state, cached memory, and global variables from leaking between test cases; verify each test independently initializes its environment
Add tests for algorithm phase transitions: verify correct initialization of bounds and state when transitioning from presolve to simplex to diving to crossover
Add tests for problem transformations: verify correctness of original→transformed→postsolve mappings and index consistency across problem representations
Test with free variables, singleton problems, and extreme problem dimensions near resource limits to validate edge case handling
Files:
cpp/tests/mip/incumbent_callback_test.cu
🧠 Learnings (23)
📚 Learning: 2025-10-22T14:25:22.899Z
Learnt from: aliceb-nv
Repo: NVIDIA/cuopt PR: 527
File: cpp/src/mip/diversity/lns/rins.cu:167-175
Timestamp: 2025-10-22T14:25:22.899Z
Learning: In MIP (Mixed Integer Programming) problems in the cuOPT codebase, `n_integer_vars == 0` is impossible by definition—MIP problems must have at least one integer variable. If there are no integer variables, it would be a pure Linear Programming (LP) problem, not a MIP problem.
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Validate algorithm correctness in optimization logic: simplex pivots, branch-and-bound decisions, routing heuristics, and constraint/objective handling must produce correct results
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Check that hard-coded GPU device IDs and resource limits are made configurable; abstract multi-backend support for different CUDA versions
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Track GPU device memory allocations and deallocations to prevent memory leaks; ensure cudaMalloc/cudaFree balance and cleanup of streams/events
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cu
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Ensure race conditions are absent in multi-GPU code and multi-threaded server implementations; verify proper synchronization of shared state
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cu
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cpp,hpp,h} : Avoid inappropriate use of exceptions in performance-critical GPU operation paths; prefer error codes or CUDA error checking for latency-sensitive code
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cu
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Refactor code duplication in solver components (3+ occurrences) into shared utilities; for GPU kernels, use templated device functions to avoid duplication
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Verify error propagation from CUDA to user-facing APIs is complete; ensure CUDA errors are caught and mapped to meaningful user error codes
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.cu : Verify race conditions and correctness of GPU kernel shared memory, atomics, and warp-level operations
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cu
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Verify correct problem size checks before expensive GPU/CPU operations; prevent resource exhaustion on oversized problems
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Eliminate unnecessary host-device synchronization (cudaDeviceSynchronize) in hot paths that blocks GPU pipeline; use streams and events for async execution
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/src/math_optimization/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hppcpp/src/mip/diversity/diversity_manager.cu
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : For concurrent CUDA operations (barriers, async operations), explicitly create and manage dedicated streams instead of reusing the default stream; document stream lifecycle
Applied to files:
cpp/include/cuopt/linear_programming/cuopt_c.hcpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/math_optimization/solver_settings.cucpp/src/mip/solver_settings.cucpp/tests/mip/incumbent_callback_test.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/include/cuopt/linear_programming/utilities/callbacks_implems.hpp
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*test*.{cpp,cu,py} : Ensure test isolation: prevent GPU state, cached memory, and global variables from leaking between test cases; verify each test independently initializes its environment
Applied to files:
cpp/include/cuopt/linear_programming/solver_settings.hppcpp/src/mip/solver_settings.cucpp/include/cuopt/linear_programming/mip/solver_settings.hppcpp/src/mip/diversity/population.cucpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Validate correct initialization of variable bounds, constraint coefficients, and algorithm state before solving; ensure reset when transitioning between algorithm phases (presolve, simplex, diving, crossover)
Applied to files:
cpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2026-01-15T20:41:51.616Z
Learnt from: chris-maes
Repo: NVIDIA/cuopt PR: 697
File: cpp/src/dual_simplex/diving_heuristics.cpp:200-228
Timestamp: 2026-01-15T20:41:51.616Z
Learning: In cpp/src/dual_simplex/diving_heuristics.cpp, the calculate_variable_locks function incorrectly indexes lp_problem.lower[nz_row] and lp_problem.upper[nz_row] where nz_row is a row index (0 to num_rows-1), but lower and upper are variable bounds of size num_cols indexed by column. This causes semantic errors and potential out-of-bounds access when num_rows > num_cols. Since lp_problem_t constraints are always equalities (A*x = rhs) after presolve, lock counting should treat each nonzero as contributing equally to both up_lock and down_lock, rather than checking constraint bounds.
Applied to files:
cpp/src/mip/diversity/diversity_manager.cu
📚 Learning: 2025-12-04T20:09:09.264Z
Learnt from: chris-maes
Repo: NVIDIA/cuopt PR: 602
File: cpp/src/linear_programming/solve.cu:732-742
Timestamp: 2025-12-04T20:09:09.264Z
Learning: In cpp/src/linear_programming/solve.cu, the barrier solver does not currently return INFEASIBLE or UNBOUNDED status. It only returns OPTIMAL, TIME_LIMIT, NUMERICAL_ISSUES, or CONCURRENT_LIMIT.
Applied to files:
cpp/src/mip/diversity/diversity_manager.cucpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*test*.{cpp,cu,py} : Add tests for algorithm phase transitions: verify correct initialization of bounds and state when transitioning from presolve to simplex to diving to crossover
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*test*.{cpp,cu,py} : Add tests for problem transformations: verify correctness of original→transformed→postsolve mappings and index consistency across problem representations
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*test*.{cpp,cu,py} : Test with free variables, singleton problems, and extreme problem dimensions near resource limits to validate edge case handling
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*test*.{cpp,cu,py} : Write tests validating numerical correctness of optimization results (not just 'runs without error'); test degenerate cases (infeasible, unbounded, empty, singleton problems)
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-11-25T10:20:49.822Z
Learnt from: CR
Repo: NVIDIA/cuopt PR: 0
File: .github/.coderabbit_review_guide.md:0-0
Timestamp: 2025-11-25T10:20:49.822Z
Learning: Applies to **/*.{cu,cuh,cpp,hpp,h} : Ensure variables and constraints are accessed from the correct problem context (original vs presolve vs folded vs postsolve); verify index mapping consistency across problem transformations
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-12-06T00:22:48.638Z
Learnt from: chris-maes
Repo: NVIDIA/cuopt PR: 500
File: cpp/tests/linear_programming/c_api_tests/c_api_test.c:1033-1048
Timestamp: 2025-12-06T00:22:48.638Z
Learning: In cuOPT's quadratic programming API, when a user provides a quadratic objective matrix Q via set_quadratic_objective_matrix or the C API functions cuOptCreateQuadraticProblem/cuOptCreateQuadraticRangedProblem, the API internally computes Q_symmetric = Q + Q^T and the barrier solver uses 0.5 * x^T * Q_symmetric * x. From the user's perspective, the convention is x^T Q x. For a diagonal Q with values [q1, q2, ...], the resulting quadratic terms are q1*x1^2 + q2*x2^2 + ...
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
📚 Learning: 2025-12-04T04:11:12.640Z
Learnt from: chris-maes
Repo: NVIDIA/cuopt PR: 500
File: cpp/src/dual_simplex/scaling.cpp:68-76
Timestamp: 2025-12-04T04:11:12.640Z
Learning: In the cuOPT dual simplex solver, CSR/CSC matrices (including the quadratic objective matrix Q) are required to have valid dimensions and indices by construction. Runtime bounds checking in performance-critical paths like matrix scaling is avoided to prevent slowdowns. Validation is performed via debug-only check_matrix() calls wrapped in `#ifdef` CHECK_MATRIX.
Applied to files:
cpp/tests/linear_programming/c_api_tests/c_api_test.c
🧬 Code graph analysis (7)
cpp/include/cuopt/linear_programming/cuopt_c.h (1)
cpp/src/linear_programming/cuopt_c.cpp (4)
cuOptSetMipGetSolutionCallback(753-764)cuOptSetMipGetSolutionCallback(753-755)cuOptSetMipSetSolutionCallback(766-777)cuOptSetMipSetSolutionCallback(766-768)
cpp/include/cuopt/linear_programming/solver_settings.hpp (2)
cpp/include/cuopt/linear_programming/mip/solver_settings.hpp (1)
callback(40-41)cpp/include/cuopt/linear_programming/utilities/internals.hpp (1)
user_data(35-35)
cpp/src/math_optimization/solver_settings.cu (5)
cpp/src/mip/solver_settings.cu (2)
set_mip_callback(27-32)set_mip_callback(27-28)python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.py (1)
set_mip_callback(248-305)cpp/include/cuopt/linear_programming/mip/solver_settings.hpp (1)
callback(40-41)cpp/include/cuopt/linear_programming/solver_settings.hpp (1)
callback(84-85)cpp/include/cuopt/linear_programming/utilities/internals.hpp (1)
user_data(35-35)
cpp/src/mip/solver_settings.cu (3)
cpp/include/cuopt/linear_programming/mip/solver_settings.hpp (1)
callback(40-41)cpp/include/cuopt/linear_programming/solver_settings.hpp (1)
callback(84-85)cpp/include/cuopt/linear_programming/utilities/internals.hpp (1)
user_data(35-35)
cpp/tests/mip/incumbent_callback_test.cu (3)
cpp/include/cuopt/linear_programming/utilities/callbacks_implems.hpp (12)
data(20-29)data(20-20)data(31-39)data(31-31)data(41-56)data(41-41)data(63-72)data(63-63)data(74-82)data(74-74)data(84-99)data(84-84)cpp/include/cuopt/linear_programming/utilities/internals.hpp (3)
data(47-47)data(56-56)user_data(35-35)cpp/src/linear_programming/cuopt_c.cpp (2)
data(57-63)data(57-57)
cpp/include/cuopt/linear_programming/utilities/internals.hpp (2)
cpp/include/cuopt/linear_programming/utilities/callbacks_implems.hpp (12)
data(20-29)data(20-20)data(31-39)data(31-31)data(41-56)data(41-41)data(63-72)data(63-63)data(74-82)data(74-74)data(84-99)data(84-84)cpp/src/linear_programming/cuopt_c.cpp (4)
data(57-63)data(57-57)data(73-78)data(73-73)
cpp/tests/linear_programming/c_api_tests/c_api_test.c (1)
cpp/src/linear_programming/cuopt_c.cpp (16)
cuOptCreateProblem(140-195)cuOptCreateProblem(140-153)cuOptCreateSolverSettings(619-625)cuOptCreateSolverSettings(619-619)cuOptSetMipGetSolutionCallback(753-764)cuOptSetMipGetSolutionCallback(753-755)cuOptSetMipSetSolutionCallback(766-777)cuOptSetMipSetSolutionCallback(766-768)cuOptSolve(792-840)cuOptSolve(792-794)cuOptDestroyProblem(387-393)cuOptDestroyProblem(387-387)cuOptDestroySolverSettings(627-632)cuOptDestroySolverSettings(627-627)cuOptDestroySolution(842-861)cuOptDestroySolution(842-842)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.10, arm64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.12, amd64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.11, arm64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.12, arm64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.13, amd64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.13, arm64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.11, amd64, rockylinux8
- GitHub Check: wheel-build-cuopt-mps-parser / 13.1.0, 3.10, amd64, rockylinux8
- GitHub Check: wheel-build-cuopt-sh-client / 13.1.0, 3.10, amd64, rockylinux8
🔇 Additional comments (16)
python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx (1)
185-198: LGTM — user_data is forwarded to the native callback.Nice, this preserves backward compatibility while wiring the user context into
set_mip_callback.python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.py (1)
248-305: LGTM — user_data is preserved on the callback.This keeps the user context alive and aligns with the new callback plumbing.
cpp/src/math_optimization/solver_settings.cu (2)
3-3: No review comment needed.
385-388: LGTM: user_data is forwarded to MIP settings.Clean passthrough that aligns with the new callback API.
cpp/include/cuopt/linear_programming/solver_settings.hpp (1)
3-3: No review comment needed.cpp/src/mip/solver_settings.cu (1)
3-3: No review comment needed.python/cuopt/cuopt/linear_programming/solver/solver.pxd (2)
1-1: No review comment needed.
80-82: LGTM: Cython declaration matches the updated C++ API.The user_data parameter is correctly surfaced here.
cpp/src/mip/diversity/population.cu (2)
3-3: No review comment needed.
302-303: LGTM: user_data is forwarded to both GET and SET callbacks.This keeps the callback context intact through the MIP solution pipeline.
Also applies to: 324-326
python/cuopt/cuopt/linear_programming/internals/internals.pyx (1)
24-32: Signature alignment with native callbacks looks correct.cpp/tests/mip/incumbent_callback_test.cu (2)
43-45: LGTM for the updated set_solution signature.
68-70: LGTM for the updated get_solution signature.cpp/tests/linear_programming/c_api_tests/c_api_test.c (2)
12-12: No issues with the CUDA runtime include.
135-296: Good callback test coverage and cleanup flow.cpp/include/cuopt/linear_programming/utilities/callbacks_implems.hpp (1)
41-55: Backward-compatible user_data handling looks good.Also applies to: 84-98
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@python/cuopt/cuopt/linear_programming/internals/internals.pyx`:
- Around line 86-97: The _user_data attribute and get_user_data_ptr() are
duplicated and lack a setter in GetSolutionCallback/SetSolutionCallback; move
_user_data, its initialization and the get_user_data_ptr() implementation into
the PyCallback base class (add initialization in PyCallback.__init__ and expose
a setter there), remove the duplicated _user_data and get_user_data_ptr() from
GetSolutionCallback and SetSolutionCallback, and ensure subclasses call
super().__init__() (or otherwise inherit) so the native_callback.pyCallbackClass
assignment in their __init__ still references the correct self.
- Around line 66-77: The Cython cdef attribute _user_data is currently C-level
only so Python assigns a shadow attribute (making user_data passed to
set_mip_callback ignored); expose it to Python by adding a Python-accessible
property or declaring it cdef public (e.g., provide a user_data property with
getter/setter that stores the C-level _user_data and returns/accepts a Python
object) in the cdef class (adjust __init__ to use the new property if needed),
ensure get_user_data_ptr() reads the same backing field, and update caller sites
(solver_settings.set_mip_callback and the analogous SetSolutionCallback usage)
to set callback.user_data = user_data instead of callback._user_data = user_data
so the Python-assigned value is visible to get_user_data_ptr().
🧹 Nitpick comments (1)
python/cuopt/cuopt/linear_programming/internals/internals.pyx (1)
72-77: Document the lifetime contract for the returned pointer.The returned
uintptr_tis a borrowed reference — noPy_INCREFis performed. The pointer remains valid only whileself(the callback object) is alive. If C code caches this pointer beyond the callback's lifetime, it risks use-after-free.Consider adding a docstring clarifying that the caller must keep the callback object alive while using the pointer:
cpdef uintptr_t get_user_data_ptr(self): """Return raw pointer to user_data. Valid only while this callback is alive."""
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
python/cuopt/cuopt/linear_programming/internals/internals.pyxpython/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx
🚧 Files skipped from review as they are similar to previous changes (1)
- python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx
🔇 Additional comments (2)
python/cuopt/cuopt/linear_programming/internals/internals.pyx (2)
11-11: LGTM!Using
cpython.ref cimport PyObjectis the idiomatic Cython approach, cleaner than a manual extern declaration.
21-29: LGTM!The extern declarations correctly extend the callback signatures to include the
user_dataparameter, enabling per-callback user context propagation.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
This PR adds callbacks to C API. Users can now use C API to implement get_solution and set_solution callbacks.
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.