Skip to content

Commit 0fe61d0

Browse files
authored
Merge branch 'main' into address_issues
2 parents cdc0796 + c36ae1d commit 0fe61d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1504
-343
lines changed

benchmarks/linear_programming/cuopt/run_pdlp.cu

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ static void parse_arguments(argparse::ArgumentParser& program)
7676
.choices("None", "Papilo", "PSLP", "Default");
7777

7878
program.add_argument("--solution-path").help("Path where solution file will be generated");
79+
80+
program.add_argument("--pdlp-precision")
81+
.help(
82+
"PDLP precision mode. default: native type, single: FP32 internally, "
83+
"double: FP64 explicitly, mixed: mixed-precision SpMV (FP32 matrix, FP64 vectors).")
84+
.default_value(std::string("default"))
85+
.choices("default", "single", "double", "mixed");
7986
}
8087

8188
static cuopt::linear_programming::presolver_t string_to_presolver(const std::string& presolver)
@@ -87,6 +94,15 @@ static cuopt::linear_programming::presolver_t string_to_presolver(const std::str
8794
return cuopt::linear_programming::presolver_t::Default;
8895
}
8996

97+
static cuopt::linear_programming::pdlp_precision_t string_to_pdlp_precision(
98+
const std::string& precision)
99+
{
100+
if (precision == "single") return cuopt::linear_programming::pdlp_precision_t::SinglePrecision;
101+
if (precision == "double") return cuopt::linear_programming::pdlp_precision_t::DoublePrecision;
102+
if (precision == "mixed") return cuopt::linear_programming::pdlp_precision_t::MixedPrecision;
103+
return cuopt::linear_programming::pdlp_precision_t::DefaultPrecision;
104+
}
105+
90106
static cuopt::linear_programming::pdlp_solver_mode_t string_to_pdlp_solver_mode(
91107
const std::string& mode)
92108
{
@@ -105,38 +121,24 @@ static cuopt::linear_programming::pdlp_solver_mode_t string_to_pdlp_solver_mode(
105121
static cuopt::linear_programming::pdlp_solver_settings_t<int, double> create_solver_settings(
106122
const argparse::ArgumentParser& program)
107123
{
108-
cuopt::linear_programming::pdlp_solver_settings_t<int, double> settings =
109-
cuopt::linear_programming::pdlp_solver_settings_t<int, double>{};
124+
cuopt::linear_programming::pdlp_solver_settings_t<int, double> settings{};
110125

111126
settings.time_limit = program.get<double>("--time-limit");
112127
settings.iteration_limit = program.get<int>("--iteration-limit");
113128
settings.set_optimality_tolerance(program.get<double>("--optimality-tolerance"));
114129
settings.pdlp_solver_mode =
115130
string_to_pdlp_solver_mode(program.get<std::string>("--pdlp-solver-mode"));
116131
settings.method = static_cast<cuopt::linear_programming::method_t>(program.get<int>("--method"));
117-
settings.crossover = program.get<int>("--crossover");
118-
settings.presolver = string_to_presolver(program.get<std::string>("--presolver"));
132+
settings.crossover = program.get<int>("--crossover");
133+
settings.presolver = string_to_presolver(program.get<std::string>("--presolver"));
134+
settings.pdlp_precision = string_to_pdlp_precision(program.get<std::string>("--pdlp-precision"));
119135

120136
return settings;
121137
}
122138

123-
int main(int argc, char* argv[])
139+
static int run_solver(const argparse::ArgumentParser& program, const raft::handle_t& handle_)
124140
{
125-
// Parse binary arguments
126-
argparse::ArgumentParser program("solve_LP");
127-
parse_arguments(program);
128-
129-
try {
130-
program.parse_args(argc, argv);
131-
} catch (const std::runtime_error& err) {
132-
std::cerr << err.what() << std::endl;
133-
std::cerr << program;
134-
return 1;
135-
}
136-
137-
// Initialize solver settings from binary arguments
138-
cuopt::linear_programming::pdlp_solver_settings_t<int, double> settings =
139-
create_solver_settings(program);
141+
auto settings = create_solver_settings(program);
140142

141143
bool use_pdlp_solver_mode = true;
142144
if (program.is_used("--pdlp-hyper-params-path")) {
@@ -145,13 +147,6 @@ int main(int argc, char* argv[])
145147
use_pdlp_solver_mode = false;
146148
}
147149

148-
// Setup up RMM memory pool
149-
auto memory_resource = make_pool();
150-
rmm::mr::set_current_device_resource(memory_resource.get());
151-
152-
// Initialize raft handle and running stream
153-
const raft::handle_t handle_{};
154-
155150
// Parse MPS file
156151
cuopt::mps_parser::mps_data_model_t<int, double> op_problem =
157152
cuopt::mps_parser::parse_mps<int, double>(program.get<std::string>("--path"));
@@ -168,3 +163,27 @@ int main(int argc, char* argv[])
168163

169164
return 0;
170165
}
166+
167+
int main(int argc, char* argv[])
168+
{
169+
// Parse binary arguments
170+
argparse::ArgumentParser program("solve_LP");
171+
parse_arguments(program);
172+
173+
try {
174+
program.parse_args(argc, argv);
175+
} catch (const std::runtime_error& err) {
176+
std::cerr << err.what() << std::endl;
177+
std::cerr << program;
178+
return 1;
179+
}
180+
181+
// Setup up RMM memory pool
182+
auto memory_resource = make_pool();
183+
rmm::mr::set_current_device_resource(memory_resource.get());
184+
185+
// Initialize raft handle and running stream
186+
const raft::handle_t handle_{};
187+
188+
return run_solver(program, handle_);
189+
}

cpp/cuopt_cli.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ inline auto make_async() { return std::make_shared<rmm::mr::cuda_async_memory_re
7777
inline cuopt::init_logger_t dummy_logger(
7878
const cuopt::linear_programming::solver_settings_t<int, double>& settings)
7979
{
80-
return cuopt::init_logger_t(settings.get_parameter<std::string>(CUOPT_LOG_FILE),
81-
settings.get_parameter<bool>(CUOPT_LOG_TO_CONSOLE));
80+
return cuopt::init_logger_t(settings.template get_parameter<std::string>(CUOPT_LOG_FILE),
81+
settings.template get_parameter<bool>(CUOPT_LOG_TO_CONSOLE));
8282
}
8383

8484
/**
@@ -287,6 +287,17 @@ int main(int argc, char* argv[])
287287
.implicit_value(true);
288288

289289
std::map<std::string, std::string> arg_name_to_param_name;
290+
291+
// Register --pdlp-precision with string-to-int mapping so that it flows
292+
// through the settings_strings map like other settings.
293+
program.add_argument("--pdlp-precision")
294+
.help(
295+
"PDLP precision mode. default: native type, single: FP32 internally, "
296+
"double: FP64 explicitly, mixed: mixed-precision SpMV (FP32 matrix, FP64 vectors).")
297+
.default_value(std::string("-1"))
298+
.choices("default", "single", "double", "mixed", "-1", "0", "1", "2");
299+
arg_name_to_param_name["--pdlp-precision"] = CUOPT_PDLP_PRECISION;
300+
290301
{
291302
// Add all solver settings as arguments
292303
cuopt::linear_programming::solver_settings_t<int, double> dummy_settings;
@@ -341,11 +352,20 @@ int main(int argc, char* argv[])
341352
return 1;
342353
}
343354

355+
// Map symbolic pdlp-precision names to integer values
356+
static const std::map<std::string, std::string> precision_name_to_value = {
357+
{"default", "-1"}, {"single", "0"}, {"double", "1"}, {"mixed", "2"}};
358+
344359
// Read everything as a string
345360
std::map<std::string, std::string> settings_strings;
346361
for (auto& [arg_name, param_name] : arg_name_to_param_name) {
347362
if (program.is_used(arg_name.c_str())) {
348-
settings_strings[param_name] = program.get<std::string>(arg_name.c_str());
363+
auto val = program.get<std::string>(arg_name.c_str());
364+
if (param_name == CUOPT_PDLP_PRECISION) {
365+
auto it = precision_name_to_value.find(val);
366+
if (it != precision_name_to_value.end()) { val = it->second; }
367+
}
368+
settings_strings[param_name] = val;
349369
}
350370
}
351371
// Get the values

cpp/include/cuopt/linear_programming/constants.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#define CUOPT_NUM_GPUS "num_gpus"
7575
#define CUOPT_USER_PROBLEM_FILE "user_problem_file"
7676
#define CUOPT_RANDOM_SEED "random_seed"
77+
#define CUOPT_PDLP_PRECISION "pdlp_precision"
7778

7879
/* @brief MIP determinism mode constants */
7980
#define CUOPT_MODE_OPPORTUNISTIC 0
@@ -125,6 +126,12 @@
125126
#define CUOPT_METHOD_DUAL_SIMPLEX 2
126127
#define CUOPT_METHOD_BARRIER 3
127128

129+
/* @brief PDLP precision mode constants */
130+
#define CUOPT_PDLP_DEFAULT_PRECISION -1
131+
#define CUOPT_PDLP_SINGLE_PRECISION 0
132+
#define CUOPT_PDLP_DOUBLE_PRECISION 1
133+
#define CUOPT_PDLP_MIXED_PRECISION 2
134+
128135
/* @brief File format constants for problem I/O */
129136
#define CUOPT_FILE_FORMAT_MPS 0
130137

cpp/include/cuopt/linear_programming/optimization_problem.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,14 @@ class optimization_problem_t : public optimization_problem_interface_t<i_t, f_t>
312312
// Conversion
313313
// ============================================================================
314314

315+
/**
316+
* @brief Convert this problem to a different floating-point precision.
317+
*
318+
* @tparam other_f_t Target floating-point type (e.g. float when this is double)
319+
*/
320+
template <typename other_f_t>
321+
optimization_problem_t<i_t, other_f_t> convert_to_other_prec(rmm::cuda_stream_view stream) const;
322+
315323
/**
316324
* @brief Returns nullptr since this is already a GPU problem.
317325
* @return nullptr

cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,21 @@ enum method_t : int {
6363
Barrier = CUOPT_METHOD_BARRIER
6464
};
6565

66+
/**
67+
* @brief Enum representing the PDLP precision modes.
68+
*
69+
* DefaultPrecision: Use the type of the problem (FP64 for double problems).
70+
* SinglePrecision: Run PDLP internally in FP32, converting inputs and outputs.
71+
* DoublePrecision: Explicitly run in FP64 (same as default for double problems).
72+
* MixedPrecision: Use mixed precision SpMV (FP32 matrix with FP64 vectors/compute).
73+
*/
74+
enum pdlp_precision_t : int {
75+
DefaultPrecision = CUOPT_PDLP_DEFAULT_PRECISION,
76+
SinglePrecision = CUOPT_PDLP_SINGLE_PRECISION,
77+
DoublePrecision = CUOPT_PDLP_DOUBLE_PRECISION,
78+
MixedPrecision = CUOPT_PDLP_MIXED_PRECISION
79+
};
80+
6681
template <typename i_t, typename f_t>
6782
class pdlp_solver_settings_t {
6883
public:
@@ -224,7 +239,7 @@ class pdlp_solver_settings_t {
224239
bool detect_infeasibility{false};
225240
bool strict_infeasibility{false};
226241
i_t iteration_limit{std::numeric_limits<i_t>::max()};
227-
double time_limit{std::numeric_limits<double>::infinity()};
242+
f_t time_limit{std::numeric_limits<f_t>::infinity()};
228243
pdlp_solver_mode_t pdlp_solver_mode{pdlp_solver_mode_t::Stable3};
229244
bool log_to_console{true};
230245
std::string log_file{""};
@@ -239,6 +254,7 @@ class pdlp_solver_settings_t {
239254
i_t ordering{-1};
240255
i_t barrier_dual_initial_point{-1};
241256
bool eliminate_dense_columns{true};
257+
pdlp_precision_t pdlp_precision{pdlp_precision_t::DefaultPrecision};
242258
bool save_best_primal_so_far{false};
243259
bool first_primal_feasible{false};
244260
presolver_t presolver{presolver_t::Default};

cpp/src/dual_simplex/sparse_matrix.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <dual_simplex/sparse_vector.hpp>
1111

1212
#include <dual_simplex/types.hpp>
13+
#include <mip_heuristics/mip_constants.hpp>
1314

1415
// #include <thrust/for_each.h>
1516
// #include <thrust/iterator/counting_iterator.h>
@@ -938,6 +939,12 @@ f_t sparse_dot(const std::vector<i_t>& xind,
938939
return dot;
939940
}
940941

942+
#if MIP_INSTANTIATE_FLOAT || PDLP_INSTANTIATE_FLOAT
943+
// Minimal float instantiation for LP usage
944+
template class csc_matrix_t<int, float>;
945+
template class csr_matrix_t<int, float>;
946+
#endif
947+
941948
#ifdef DUAL_SIMPLEX_INSTANTIATE_DOUBLE
942949
template class csc_matrix_t<int, double>;
943950

cpp/src/math_optimization/solution_writer.cu

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
#include <utilities/logger.hpp>
1010
#include "solution_writer.hpp"
1111

12+
#include <mip_heuristics/mip_constants.hpp>
13+
1214
#include <fstream>
1315

1416
namespace cuopt::linear_programming {
1517

18+
template <typename f_t>
1619
void solution_writer_t::write_solution_to_sol_file(const std::string& filename,
1720
const std::string& status,
18-
const double objective_value,
21+
const f_t objective_value,
1922
const std::vector<std::string>& variable_names,
20-
const std::vector<double>& variable_values)
23+
const std::vector<f_t>& variable_values)
2124
{
2225
raft::common::nvtx::range fun_scope("write final solution to .sol file");
2326
std::ofstream file(filename.data());
@@ -27,7 +30,7 @@ void solution_writer_t::write_solution_to_sol_file(const std::string& filename,
2730
return;
2831
}
2932

30-
file.precision(std::numeric_limits<double>::max_digits10 + 1);
33+
file.precision(std::numeric_limits<f_t>::max_digits10 + 1);
3134

3235
file << "# Status: " << status << std::endl;
3336

@@ -39,4 +42,22 @@ void solution_writer_t::write_solution_to_sol_file(const std::string& filename,
3942
}
4043
}
4144

45+
#if MIP_INSTANTIATE_FLOAT || PDLP_INSTANTIATE_FLOAT
46+
template void solution_writer_t::write_solution_to_sol_file<float>(
47+
const std::string& filename,
48+
const std::string& status,
49+
const float objective_value,
50+
const std::vector<std::string>& variable_names,
51+
const std::vector<float>& variable_values);
52+
#endif
53+
54+
#if MIP_INSTANTIATE_DOUBLE
55+
template void solution_writer_t::write_solution_to_sol_file<double>(
56+
const std::string& filename,
57+
const std::string& status,
58+
const double objective_value,
59+
const std::vector<std::string>& variable_names,
60+
const std::vector<double>& variable_values);
61+
#endif
62+
4263
} // namespace cuopt::linear_programming

cpp/src/math_optimization/solution_writer.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* clang-format off */
22
/*
3-
* SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
* SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66
/* clang-format on */
@@ -23,10 +23,11 @@ namespace cuopt::linear_programming {
2323
*/
2424
class solution_writer_t {
2525
public:
26+
template <typename f_t>
2627
static void write_solution_to_sol_file(const std::string& sol_file_path,
2728
const std::string& status,
28-
const double objective_value,
29+
const f_t objective_value,
2930
const std::vector<std::string>& variable_names,
30-
const std::vector<double>& variable_values);
31+
const std::vector<f_t>& variable_values);
3132
};
3233
} // namespace cuopt::linear_programming

0 commit comments

Comments
 (0)