Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions cpp/src/grpc/client/solve_remote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <utilities/logger.hpp>
#include "grpc_client.hpp"

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <fstream>
Expand All @@ -22,8 +23,6 @@
#include <sstream>
#include <stdexcept>

#include <thrust/count.h>

namespace cuopt::mathematical_optimization {

// Buffer added to the solver's time_limit to account for worker startup,
Expand Down Expand Up @@ -152,7 +151,7 @@ std::unique_ptr<mip_solution_interface_t<i_t, f_t>> solve_mip_remote(
auto mip_callbacks = settings.get_mip_callbacks();
const auto var_types = cpu_problem.get_variable_types_host();
const bool has_sc_variables =
thrust::count(var_types.begin(), var_types.end(), var_t::SEMI_CONTINUOUS) > 0;
std::count(var_types.begin(), var_types.end(), var_t::SEMI_CONTINUOUS) > 0;
if (has_sc_variables && !mip_callbacks.empty()) {
CUOPT_LOG_WARN(
"Disabling remote MIP get/set callbacks: semi-continuous models are not "
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/math_optimization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

list(PREPEND
MATH_OPT_SRC_FILES
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings_gpu.cu
${CMAKE_CURRENT_SOURCE_DIR}/solution_reader.cu
${CMAKE_CURRENT_SOURCE_DIR}/solution_writer.cu
${CMAKE_CURRENT_SOURCE_DIR}/tic_toc.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,85 +412,6 @@ std::string solver_settings_t<i_t, f_t>::get_parameter_as_string(const std::stri
throw std::invalid_argument("Parameter " + name + " not found");
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_initial_pdlp_primal_solution(const f_t* solution,
i_t size,
rmm::cuda_stream_view stream)
{
pdlp_settings.set_initial_primal_solution(solution, size, stream);
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_initial_pdlp_dual_solution(const f_t* solution,
i_t size,
rmm::cuda_stream_view stream)
{
pdlp_settings.set_initial_dual_solution(solution, size, stream);
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_pdlp_warm_start_data(
const f_t* current_primal_solution,
const f_t* current_dual_solution,
const f_t* initial_primal_average,
const f_t* initial_dual_average,
const f_t* current_ATY,
const f_t* sum_primal_solutions,
const f_t* sum_dual_solutions,
const f_t* last_restart_duality_gap_primal_solution,
const f_t* last_restart_duality_gap_dual_solution,
i_t primal_size,
i_t dual_size,
f_t initial_primal_weight,
f_t initial_step_size,
i_t total_pdlp_iterations,
i_t total_pdhg_iterations,
f_t last_candidate_kkt_score,
f_t last_restart_kkt_score,
f_t sum_solution_weight,
i_t iterations_since_last_restart)
{
pdlp_settings.set_pdlp_warm_start_data(current_primal_solution,
current_dual_solution,
initial_primal_average,
initial_dual_average,
current_ATY,
sum_primal_solutions,
sum_dual_solutions,
last_restart_duality_gap_primal_solution,
last_restart_duality_gap_dual_solution,
primal_size,
dual_size,
initial_primal_weight,
initial_step_size,
total_pdlp_iterations,
total_pdhg_iterations,
last_candidate_kkt_score,
last_restart_kkt_score,
sum_solution_weight,
iterations_since_last_restart);
}

template <typename i_t, typename f_t>
const rmm::device_uvector<f_t>& solver_settings_t<i_t, f_t>::get_initial_pdlp_primal_solution()
const
{
return pdlp_settings.get_initial_primal_solution();
}

template <typename i_t, typename f_t>
const rmm::device_uvector<f_t>& solver_settings_t<i_t, f_t>::get_initial_pdlp_dual_solution() const
{
return pdlp_settings.get_initial_dual_solution();
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::add_initial_mip_solution(const f_t* solution,
i_t size,
rmm::cuda_stream_view stream)
{
mip_settings.add_initial_solution(solution, size, stream);
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_mip_callback(internals::base_solution_callback_t* callback,
Expand Down
135 changes: 135 additions & 0 deletions cpp/src/math_optimization/solver_settings_gpu.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */

// Device-facing members of solver_settings_t, split out of solver_settings.cu.
//
// Everything else in that class is host-only parameter handling, so the remainder now
// builds as solver_settings.cpp into the CUDA-free cuopt_client library. Only these
// members take an rmm::cuda_stream_view or hand back a device_uvector, so they are the
// only ones that must stay in a CUDA TU inside libcuopt.
//
// The `template class` instantiation in solver_settings.cpp cannot emit these members
// (their definitions are not visible there), so they are instantiated explicitly below.

#include <cuopt/mathematical_optimization/solver_settings.hpp>

#include <rmm/cuda_stream_view.hpp>
#include <rmm/device_uvector.hpp>

#include <mip_heuristics/mip_constants.hpp>

namespace cuopt {
namespace CUOPT_EXPORT mathematical_optimization {

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_initial_pdlp_primal_solution(const f_t* solution,
i_t size,
rmm::cuda_stream_view stream)
{
pdlp_settings.set_initial_primal_solution(solution, size, stream);
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_initial_pdlp_dual_solution(const f_t* solution,
i_t size,
rmm::cuda_stream_view stream)
{
pdlp_settings.set_initial_dual_solution(solution, size, stream);
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::set_pdlp_warm_start_data(
const f_t* current_primal_solution,
const f_t* current_dual_solution,
const f_t* initial_primal_average,
const f_t* initial_dual_average,
const f_t* current_ATY,
const f_t* sum_primal_solutions,
const f_t* sum_dual_solutions,
const f_t* last_restart_duality_gap_primal_solution,
const f_t* last_restart_duality_gap_dual_solution,
i_t primal_size,
i_t dual_size,
f_t initial_primal_weight,
f_t initial_step_size,
i_t total_pdlp_iterations,
i_t total_pdhg_iterations,
f_t last_candidate_kkt_score,
f_t last_restart_kkt_score,
f_t sum_solution_weight,
i_t iterations_since_last_restart)
{
pdlp_settings.set_pdlp_warm_start_data(current_primal_solution,
current_dual_solution,
initial_primal_average,
initial_dual_average,
current_ATY,
sum_primal_solutions,
sum_dual_solutions,
last_restart_duality_gap_primal_solution,
last_restart_duality_gap_dual_solution,
primal_size,
dual_size,
initial_primal_weight,
initial_step_size,
total_pdlp_iterations,
total_pdhg_iterations,
last_candidate_kkt_score,
last_restart_kkt_score,
sum_solution_weight,
iterations_since_last_restart);
}

template <typename i_t, typename f_t>
const rmm::device_uvector<f_t>& solver_settings_t<i_t, f_t>::get_initial_pdlp_primal_solution()
const
{
return pdlp_settings.get_initial_primal_solution();
}

template <typename i_t, typename f_t>
const rmm::device_uvector<f_t>& solver_settings_t<i_t, f_t>::get_initial_pdlp_dual_solution() const
{
return pdlp_settings.get_initial_dual_solution();
}

template <typename i_t, typename f_t>
void solver_settings_t<i_t, f_t>::add_initial_mip_solution(const f_t* solution,
i_t size,
rmm::cuda_stream_view stream)
{
mip_settings.add_initial_solution(solution, size, stream);
}

#if MIP_INSTANTIATE_FLOAT
template CUOPT_EXPORT void solver_settings_t<int, float>::set_initial_pdlp_primal_solution(
const float*, int, rmm::cuda_stream_view);
template CUOPT_EXPORT void solver_settings_t<int, float>::set_initial_pdlp_dual_solution(
const float*, int, rmm::cuda_stream_view);
template CUOPT_EXPORT const rmm::device_uvector<float>&
solver_settings_t<int, float>::get_initial_pdlp_primal_solution() const;
template CUOPT_EXPORT const rmm::device_uvector<float>&
solver_settings_t<int, float>::get_initial_pdlp_dual_solution() const;
template CUOPT_EXPORT void solver_settings_t<int, float>::add_initial_mip_solution(
const float*, int, rmm::cuda_stream_view);
#endif

#if MIP_INSTANTIATE_DOUBLE
template CUOPT_EXPORT void solver_settings_t<int, double>::set_initial_pdlp_primal_solution(
const double*, int, rmm::cuda_stream_view);
template CUOPT_EXPORT void solver_settings_t<int, double>::set_initial_pdlp_dual_solution(
const double*, int, rmm::cuda_stream_view);
template CUOPT_EXPORT const rmm::device_uvector<double>&
solver_settings_t<int, double>::get_initial_pdlp_primal_solution() const;
template CUOPT_EXPORT const rmm::device_uvector<double>&
solver_settings_t<int, double>::get_initial_pdlp_dual_solution() const;
template CUOPT_EXPORT void solver_settings_t<int, double>::add_initial_mip_solution(
const double*, int, rmm::cuda_stream_view);
#endif

} // namespace CUOPT_EXPORT mathematical_optimization
} // namespace cuopt
1 change: 1 addition & 0 deletions cpp/src/mip_heuristics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set(MIP_LP_NECESSARY_FILES
${CMAKE_CURRENT_SOURCE_DIR}/problem/problem.cu
${CMAKE_CURRENT_SOURCE_DIR}/problem/presolve_data.cu
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cu
${CMAKE_CURRENT_SOURCE_DIR}/solver_settings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/solver_solution.cu
${CMAKE_CURRENT_SOURCE_DIR}/local_search/rounding/simple_rounding.cu
${CMAKE_CURRENT_SOURCE_DIR}/presolve/third_party_presolve.cpp
Expand Down
67 changes: 67 additions & 0 deletions cpp/src/mip_heuristics/solver_settings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* clang-format off */
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
/* clang-format on */

// Host-only members of mip_solver_settings_t, split out of solver_settings.cu.
//
// Only add_initial_solution() touches the device (it copies into an rmm::device_uvector),
// so it stays in the CUDA TU while these build into the CUDA-free cuopt_client library.
// The gRPC client reaches get_mip_callbacks() via solve_remote's callback handling.
//
// Instantiated per-member rather than with `template class`: the class holds
// device_uvector-backed initial_solutions, so instantiating all of it here would pull
// device code into the client library.

#include <cuopt/export.hpp>
#include <cuopt/mathematical_optimization/mip/solver_settings.hpp>
#include <mip_heuristics/mip_constants.hpp>

#include <vector>

namespace cuopt::mathematical_optimization {

template <typename i_t, typename f_t>
void mip_solver_settings_t<i_t, f_t>::set_mip_callback(
internals::base_solution_callback_t* callback, void* user_data)
{
if (callback == nullptr) { return; }
callback->set_user_data(user_data);
mip_callbacks_.push_back(callback);
}

template <typename i_t, typename f_t>
const std::vector<internals::base_solution_callback_t*>
mip_solver_settings_t<i_t, f_t>::get_mip_callbacks() const
{
return mip_callbacks_;
}

template <typename i_t, typename f_t>
typename mip_solver_settings_t<i_t, f_t>::tolerances_t
mip_solver_settings_t<i_t, f_t>::get_tolerances() const noexcept
{
return tolerances;
}

#if MIP_INSTANTIATE_FLOAT
template CUOPT_EXPORT void mip_solver_settings_t<int, float>::set_mip_callback(
internals::base_solution_callback_t*, void*);
template CUOPT_EXPORT const std::vector<internals::base_solution_callback_t*>
mip_solver_settings_t<int, float>::get_mip_callbacks() const;
template CUOPT_EXPORT mip_solver_settings_t<int, float>::tolerances_t
mip_solver_settings_t<int, float>::get_tolerances() const noexcept;
#endif

#if MIP_INSTANTIATE_DOUBLE
template CUOPT_EXPORT void mip_solver_settings_t<int, double>::set_mip_callback(
internals::base_solution_callback_t*, void*);
template CUOPT_EXPORT const std::vector<internals::base_solution_callback_t*>
mip_solver_settings_t<int, double>::get_mip_callbacks() const;
template CUOPT_EXPORT mip_solver_settings_t<int, double>::tolerances_t
mip_solver_settings_t<int, double>::get_tolerances() const noexcept;
#endif

} // namespace cuopt::mathematical_optimization
23 changes: 0 additions & 23 deletions cpp/src/mip_heuristics/solver_settings.cu
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,6 @@ void mip_solver_settings_t<i_t, f_t>::add_initial_solution(const f_t* initial_so
raft::copy(initial_solutions.back()->data(), initial_solution, size, stream);
}

template <typename i_t, typename f_t>
void mip_solver_settings_t<i_t, f_t>::set_mip_callback(
internals::base_solution_callback_t* callback, void* user_data)
{
if (callback == nullptr) { return; }
callback->set_user_data(user_data);
mip_callbacks_.push_back(callback);
}

template <typename i_t, typename f_t>
const std::vector<internals::base_solution_callback_t*>
mip_solver_settings_t<i_t, f_t>::get_mip_callbacks() const
{
return mip_callbacks_;
}

template <typename i_t, typename f_t>
typename mip_solver_settings_t<i_t, f_t>::tolerances_t
mip_solver_settings_t<i_t, f_t>::get_tolerances() const noexcept
{
return tolerances;
}

// Explicit template instantiations for common types
#if MIP_INSTANTIATE_FLOAT
template class CUOPT_EXPORT mip_solver_settings_t<int, float>;
Expand Down
1 change: 1 addition & 0 deletions cpp/src/pdlp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(LP_CORE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/pdhg.cu
${CMAKE_CURRENT_SOURCE_DIR}/solver_solution.cu
${CMAKE_CURRENT_SOURCE_DIR}/solution_conversion.cu
${CMAKE_CURRENT_SOURCE_DIR}/solution_conversion_cpu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/saddle_point.cu
${CMAKE_CURRENT_SOURCE_DIR}/cusparse_view.cu
${CMAKE_CURRENT_SOURCE_DIR}/pdlp_warm_start_data.cu
Expand Down
Loading
Loading