-
Notifications
You must be signed in to change notification settings - Fork 115
C api additions #721
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: release/26.02
Are you sure you want to change the base?
C api additions #721
Changes from all commits
77a936e
d39f231
7b0739c
e247109
5fabb48
a7b2fe2
177b638
69eca52
b520001
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /* clang-format off */ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| /* clang-format on */ | ||
|
|
@@ -111,6 +111,20 @@ cuopt_int_t cuOptGetVersion(cuopt_int_t* version_major, | |
| */ | ||
| cuopt_int_t cuOptReadProblem(const char* filename, cuOptOptimizationProblem* problem_ptr); | ||
|
|
||
| /** | ||
| * @brief Write an optimization problem to a file. | ||
| * | ||
| * @param[in] problem - The optimization problem to write. | ||
| * @param[in] filename - The path to the output file. | ||
| * @param[in] format - The file format to use. Currently only CUOPT_FILE_FORMAT_MPS is supported. | ||
| * | ||
| * @return A status code indicating success or failure. Returns CUOPT_INVALID_ARGUMENT | ||
| * if an unsupported format is specified. | ||
| */ | ||
| cuopt_int_t cuOptWriteProblem(cuOptOptimizationProblem problem, | ||
| const char* filename, | ||
| cuopt_int_t format); | ||
|
|
||
| /** @brief Create an optimization problem of the form | ||
| * | ||
| * @verbatim | ||
|
|
@@ -681,6 +695,53 @@ cuopt_int_t cuOptGetFloatParameter(cuOptSolverSettings settings, | |
| const char* parameter_name, | ||
| cuopt_float_t* parameter_value); | ||
|
|
||
| /** | ||
| * @brief Set the initial primal solution for an LP solve. | ||
| * | ||
| * @param[in] settings - The solver settings object. | ||
| * @param[in] primal_solution - A pointer to an array of type cuopt_float_t | ||
| * of size num_variables containing the initial primal values. | ||
| * @param[in] num_variables - The number of variables (size of the primal_solution array). | ||
| * | ||
| * @return A status code indicating success or failure. | ||
| */ | ||
| cuopt_int_t cuOptSetInitialPrimalSolution(cuOptSolverSettings settings, | ||
| const cuopt_float_t* primal_solution, | ||
| cuopt_int_t num_variables); | ||
|
|
||
| /** | ||
| * @brief Set the initial dual solution for an LP solve. | ||
| * | ||
| * @param[in] settings - The solver settings object. | ||
| * @param[in] dual_solution - A pointer to an array of type cuopt_float_t | ||
| * of size num_constraints containing the initial dual values. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
| * @param[in] num_constraints - The number of constraints (size of the dual_solution array). | ||
| * | ||
| * @return A status code indicating success or failure. | ||
| */ | ||
| cuopt_int_t cuOptSetInitialDualSolution(cuOptSolverSettings settings, | ||
| const cuopt_float_t* dual_solution, | ||
| cuopt_int_t num_constraints); | ||
|
|
||
| /** | ||
| * @brief Add an initial solution (MIP start) for MIP solving. | ||
| * | ||
| * This function can be called multiple times to add multiple MIP starts. | ||
| * The solver will use these as starting points for the MIP search. | ||
| * | ||
| * @param[in] settings - The solver settings object. | ||
| * @param[in] solution - A pointer to an array of type cuopt_float_t | ||
| * of size num_variables containing the solution values. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
| * @param[in] num_variables - The number of variables (size of the solution array). | ||
| * | ||
| * @attention Currently unsupported with presolve on. | ||
| * | ||
| * @return A status code indicating success or failure. | ||
| */ | ||
| cuopt_int_t cuOptAddMIPStart(cuOptSolverSettings settings, | ||
| const cuopt_float_t* solution, | ||
| cuopt_int_t num_variables); | ||
|
|
||
| /** @brief Check if an optimization problem is a mixed integer programming problem. | ||
| * | ||
| * @param[in] problem - The optimization problem. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /* clang-format off */ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| /* clang-format on */ | ||
|
|
@@ -11,6 +11,7 @@ | |
| #include <cuopt/linear_programming/solve.hpp> | ||
| #include <cuopt/linear_programming/solver_settings.hpp> | ||
| #include <cuopt/utilities/timestamp_utils.hpp> | ||
| #include <linear_programming/cuopt_c_internal.hpp> | ||
| #include <utilities/logger.hpp> | ||
|
|
||
| #include <mps_parser/parser.hpp> | ||
|
|
@@ -24,31 +25,6 @@ | |
| using namespace cuopt::mps_parser; | ||
| using namespace cuopt::linear_programming; | ||
|
|
||
| struct problem_and_stream_view_t { | ||
| problem_and_stream_view_t() | ||
| : op_problem(nullptr), stream_view(rmm::cuda_stream_per_thread), handle(stream_view) | ||
| { | ||
| } | ||
| raft::handle_t* get_handle_ptr() { return &handle; } | ||
| cuopt::linear_programming::optimization_problem_t<cuopt_int_t, cuopt_float_t>* op_problem; | ||
| rmm::cuda_stream_view stream_view; | ||
| raft::handle_t handle; | ||
| }; | ||
|
|
||
| struct solution_and_stream_view_t { | ||
| solution_and_stream_view_t(bool solution_for_mip, rmm::cuda_stream_view stream_view) | ||
| : is_mip(solution_for_mip), | ||
| mip_solution_ptr(nullptr), | ||
| lp_solution_ptr(nullptr), | ||
| stream_view(stream_view) | ||
| { | ||
| } | ||
| bool is_mip; | ||
| mip_solution_t<cuopt_int_t, cuopt_float_t>* mip_solution_ptr; | ||
| optimization_problem_solution_t<cuopt_int_t, cuopt_float_t>* lp_solution_ptr; | ||
| rmm::cuda_stream_view stream_view; | ||
| }; | ||
|
|
||
| int8_t cuOptGetFloatSize() { return sizeof(cuopt_float_t); } | ||
|
|
||
| int8_t cuOptGetIntSize() { return sizeof(cuopt_int_t); } | ||
|
|
@@ -92,6 +68,26 @@ cuopt_int_t cuOptReadProblem(const char* filename, cuOptOptimizationProblem* pro | |
| return CUOPT_SUCCESS; | ||
| } | ||
|
|
||
| cuopt_int_t cuOptWriteProblem(cuOptOptimizationProblem problem, | ||
| const char* filename, | ||
| cuopt_int_t format) | ||
| { | ||
| if (problem == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
aliceb-nv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (filename == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (strlen(filename) == 0) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (format != CUOPT_FILE_FORMAT_MPS) { return CUOPT_INVALID_ARGUMENT; } | ||
|
|
||
| problem_and_stream_view_t* problem_and_stream_view = | ||
| static_cast<problem_and_stream_view_t*>(problem); | ||
| try { | ||
| problem_and_stream_view->op_problem->write_to_mps(std::string(filename)); | ||
| } catch (const std::exception& e) { | ||
| CUOPT_LOG_INFO("Error writing MPS file: %s", e.what()); | ||
| return CUOPT_MPS_FILE_ERROR; | ||
| } | ||
| return CUOPT_SUCCESS; | ||
| } | ||
|
|
||
| cuopt_int_t cuOptCreateProblem(cuopt_int_t num_constraints, | ||
| cuopt_int_t num_variables, | ||
| cuopt_int_t objective_sense, | ||
|
|
@@ -706,6 +702,60 @@ cuopt_int_t cuOptGetFloatParameter(cuOptSolverSettings settings, | |
| return CUOPT_SUCCESS; | ||
| } | ||
|
|
||
| cuopt_int_t cuOptSetInitialPrimalSolution(cuOptSolverSettings settings, | ||
| const cuopt_float_t* primal_solution, | ||
| cuopt_int_t num_variables) | ||
| { | ||
| if (settings == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (primal_solution == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (num_variables <= 0) { return CUOPT_INVALID_ARGUMENT; } | ||
|
|
||
| solver_settings_t<cuopt_int_t, cuopt_float_t>* solver_settings = | ||
| static_cast<solver_settings_t<cuopt_int_t, cuopt_float_t>*>(settings); | ||
| try { | ||
| solver_settings->set_initial_pdlp_primal_solution(primal_solution, num_variables); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only valid for PDLP right? How about for MIP or other LP solvers? If this is only for PDLP, then C API should also be explicit. |
||
| } catch (const std::exception& e) { | ||
| return CUOPT_INVALID_ARGUMENT; | ||
| } | ||
| return CUOPT_SUCCESS; | ||
| } | ||
|
|
||
| cuopt_int_t cuOptSetInitialDualSolution(cuOptSolverSettings settings, | ||
| const cuopt_float_t* dual_solution, | ||
| cuopt_int_t num_constraints) | ||
| { | ||
| if (settings == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (dual_solution == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (num_constraints <= 0) { return CUOPT_INVALID_ARGUMENT; } | ||
|
|
||
| solver_settings_t<cuopt_int_t, cuopt_float_t>* solver_settings = | ||
| static_cast<solver_settings_t<cuopt_int_t, cuopt_float_t>*>(settings); | ||
| try { | ||
| solver_settings->set_initial_pdlp_dual_solution(dual_solution, num_constraints); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
| } catch (const std::exception& e) { | ||
| return CUOPT_INVALID_ARGUMENT; | ||
| } | ||
| return CUOPT_SUCCESS; | ||
| } | ||
|
|
||
| cuopt_int_t cuOptAddMIPStart(cuOptSolverSettings settings, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Combine MIP and LP API? |
||
| const cuopt_float_t* solution, | ||
| cuopt_int_t num_variables) | ||
| { | ||
| if (settings == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (solution == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
| if (num_variables <= 0) { return CUOPT_INVALID_ARGUMENT; } | ||
|
|
||
| solver_settings_t<cuopt_int_t, cuopt_float_t>* solver_settings = | ||
| static_cast<solver_settings_t<cuopt_int_t, cuopt_float_t>*>(settings); | ||
| try { | ||
| solver_settings->get_mip_settings().add_initial_solution(solution, num_variables); | ||
| } catch (const std::exception& e) { | ||
| return CUOPT_INVALID_ARGUMENT; | ||
| } | ||
| return CUOPT_SUCCESS; | ||
| } | ||
|
|
||
| cuopt_int_t cuOptIsMIP(cuOptOptimizationProblem problem, cuopt_int_t* is_mip_ptr) | ||
| { | ||
| if (problem == nullptr) { return CUOPT_INVALID_ARGUMENT; } | ||
|
|
||
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.
Do we want to specify if data should be on the CPU and/or GPU?
Uh oh!
There was an error while loading. Please reload this page.
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.
My understanding is that the C API abstracts away the reality of a GPU implementation - therefore all pointers involved are host pointers (as a result, we do not expose the stream(s) involved)
I think that if the need arises, we could create alternative versions of these functions to upload GPU data, or use something similar to cuSparse's pointer mode flag
Uh oh!
There was an error while loading. Please reload this page.
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.
I'll note that as a new cuOpt user, I had the exact same question about host/device pointer for inputs.
I think it would be helpful to explicitly say they expect host pointers (either in the individual docstrings or in some high level place in the user guide "all C API pointers are expected to be pointers to host memory").