diff --git a/cpp/include/cuopt/linear_programming/constants.h b/cpp/include/cuopt/linear_programming/constants.h index 4ee022484..33cd8bb6b 100644 --- a/cpp/include/cuopt/linear_programming/constants.h +++ b/cpp/include/cuopt/linear_programming/constants.h @@ -64,16 +64,16 @@ #define CUOPT_USER_PROBLEM_FILE "user_problem_file" /* @brief LP/MIP termination status constants */ -#define CUOPT_TERIMINATION_STATUS_NO_TERMINATION 0 -#define CUOPT_TERIMINATION_STATUS_OPTIMAL 1 -#define CUOPT_TERIMINATION_STATUS_INFEASIBLE 2 -#define CUOPT_TERIMINATION_STATUS_UNBOUNDED 3 -#define CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT 4 -#define CUOPT_TERIMINATION_STATUS_TIME_LIMIT 5 -#define CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR 6 -#define CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE 7 -#define CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND 8 -#define CUOPT_TERIMINATION_STATUS_CONCURRENT_LIMIT 9 +#define CUOPT_TERMINATION_STATUS_NO_TERMINATION 0 +#define CUOPT_TERMINATION_STATUS_OPTIMAL 1 +#define CUOPT_TERMINATION_STATUS_INFEASIBLE 2 +#define CUOPT_TERMINATION_STATUS_UNBOUNDED 3 +#define CUOPT_TERMINATION_STATUS_ITERATION_LIMIT 4 +#define CUOPT_TERMINATION_STATUS_TIME_LIMIT 5 +#define CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR 6 +#define CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE 7 +#define CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND 8 +#define CUOPT_TERMINATION_STATUS_CONCURRENT_LIMIT 9 /* @brief The objective sense constants */ #define CUOPT_MINIMIZE 1 @@ -107,6 +107,7 @@ #define CUOPT_METHOD_PDLP 1 #define CUOPT_METHOD_DUAL_SIMPLEX 2 #define CUOPT_METHOD_BARRIER 3 +#define CUOPT_METHOD_UNSET 4 /* @brief File format constants for problem I/O */ #define CUOPT_FILE_FORMAT_MPS 0 diff --git a/cpp/include/cuopt/linear_programming/mip/solver_solution.hpp b/cpp/include/cuopt/linear_programming/mip/solver_solution.hpp index 6ff8d324b..0d38d8050 100644 --- a/cpp/include/cuopt/linear_programming/mip/solver_solution.hpp +++ b/cpp/include/cuopt/linear_programming/mip/solver_solution.hpp @@ -1,6 +1,6 @@ /* clang-format off */ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* clang-format on */ @@ -24,12 +24,12 @@ namespace cuopt::linear_programming { enum class mip_termination_status_t : int8_t { - NoTermination = CUOPT_TERIMINATION_STATUS_NO_TERMINATION, - Optimal = CUOPT_TERIMINATION_STATUS_OPTIMAL, - FeasibleFound = CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND, - Infeasible = CUOPT_TERIMINATION_STATUS_INFEASIBLE, - Unbounded = CUOPT_TERIMINATION_STATUS_UNBOUNDED, - TimeLimit = CUOPT_TERIMINATION_STATUS_TIME_LIMIT, + NoTermination = CUOPT_TERMINATION_STATUS_NO_TERMINATION, + Optimal = CUOPT_TERMINATION_STATUS_OPTIMAL, + FeasibleFound = CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND, + Infeasible = CUOPT_TERMINATION_STATUS_INFEASIBLE, + Unbounded = CUOPT_TERMINATION_STATUS_UNBOUNDED, + TimeLimit = CUOPT_TERMINATION_STATUS_TIME_LIMIT, }; template diff --git a/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp b/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp index 3b94fee14..9667882b0 100644 --- a/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp +++ b/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp @@ -48,9 +48,11 @@ enum pdlp_solver_mode_t : int { * @brief Enum representing the different methods that can be used to solve the * linear programming problem. * - * Concurrent: Use both PDLP and DualSimplex in parallel. + * Concurrent: Use PDLP, Barrier and DualSimplex in parallel. * PDLP: Use the PDLP method. * DualSimplex: Use the dual simplex method. + * Barrier: Use the barrier method + * Unset: The value was not set. * * @note Default method is Concurrent. */ @@ -58,7 +60,8 @@ enum method_t : int { Concurrent = CUOPT_METHOD_CONCURRENT, PDLP = CUOPT_METHOD_PDLP, DualSimplex = CUOPT_METHOD_DUAL_SIMPLEX, - Barrier = CUOPT_METHOD_BARRIER + Barrier = CUOPT_METHOD_BARRIER, + Unset = CUOPT_METHOD_UNSET }; template diff --git a/cpp/include/cuopt/linear_programming/pdlp/solver_solution.hpp b/cpp/include/cuopt/linear_programming/pdlp/solver_solution.hpp index 45a47e740..c36e0a82e 100644 --- a/cpp/include/cuopt/linear_programming/pdlp/solver_solution.hpp +++ b/cpp/include/cuopt/linear_programming/pdlp/solver_solution.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -25,17 +26,27 @@ namespace cuopt::linear_programming { // Possible reasons for terminating enum class pdlp_termination_status_t : int8_t { - NoTermination = CUOPT_TERIMINATION_STATUS_NO_TERMINATION, - NumericalError = CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR, - Optimal = CUOPT_TERIMINATION_STATUS_OPTIMAL, - PrimalInfeasible = CUOPT_TERIMINATION_STATUS_INFEASIBLE, - DualInfeasible = CUOPT_TERIMINATION_STATUS_UNBOUNDED, - IterationLimit = CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT, - TimeLimit = CUOPT_TERIMINATION_STATUS_TIME_LIMIT, - PrimalFeasible = CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE, - ConcurrentLimit = CUOPT_TERIMINATION_STATUS_CONCURRENT_LIMIT + NoTermination = CUOPT_TERMINATION_STATUS_NO_TERMINATION, + NumericalError = CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR, + Optimal = CUOPT_TERMINATION_STATUS_OPTIMAL, + PrimalInfeasible = CUOPT_TERMINATION_STATUS_INFEASIBLE, + DualInfeasible = CUOPT_TERMINATION_STATUS_UNBOUNDED, + IterationLimit = CUOPT_TERMINATION_STATUS_ITERATION_LIMIT, + TimeLimit = CUOPT_TERMINATION_STATUS_TIME_LIMIT, + PrimalFeasible = CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE, + ConcurrentLimit = CUOPT_TERMINATION_STATUS_CONCURRENT_LIMIT }; +inline std::string method_to_string(method_t method) +{ + switch (method) { + case method_t::DualSimplex: return "Dual Simplex"; + case method_t::PDLP: return "PDLP"; + case method_t::Barrier: return "Barrier"; + default: return "Unset"; + } +} + /** * @brief A container of PDLP solver output * @tparam i_t Integer type. Currently only int is supported. @@ -88,8 +99,8 @@ class optimization_problem_solution_t : public base_solution_t { /** Solve time in seconds */ double solve_time{std::numeric_limits::signaling_NaN()}; - /** Whether the problem was solved by PDLP or Dual Simplex */ - bool solved_by_pdlp{false}; + /** Whether the problem was solved by PDLP, Barrier or Dual Simplex */ + method_t solved_by = method_t::Unset; }; /** diff --git a/cpp/include/cuopt/linear_programming/utilities/cython_solve.hpp b/cpp/include/cuopt/linear_programming/utilities/cython_solve.hpp index e1a75747d..0a1ecef21 100644 --- a/cpp/include/cuopt/linear_programming/utilities/cython_solve.hpp +++ b/cpp/include/cuopt/linear_programming/utilities/cython_solve.hpp @@ -1,6 +1,6 @@ /* clang-format off */ /* - * SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* clang-format on */ @@ -60,7 +60,7 @@ struct linear_programming_ret_t { double gap_; int nb_iterations_; double solve_time_; - bool solved_by_pdlp_; + linear_programming::method_t solved_by_; }; struct mip_ret_t { diff --git a/cpp/src/dual_simplex/basis_solves.cpp b/cpp/src/dual_simplex/basis_solves.cpp index f5cd54053..e11b7e735 100644 --- a/cpp/src/dual_simplex/basis_solves.cpp +++ b/cpp/src/dual_simplex/basis_solves.cpp @@ -362,7 +362,7 @@ i_t factorize_basis(const csc_matrix_t& A, SU, S_perm_inv); if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return -1; } if (Srank != Sdim) { @@ -581,7 +581,7 @@ i_t factorize_basis(const csc_matrix_t& A, } } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return -1; } if (verbose) { diff --git a/cpp/src/dual_simplex/branch_and_bound.cpp b/cpp/src/dual_simplex/branch_and_bound.cpp index acdc9888a..9cdeddbb5 100644 --- a/cpp/src/dual_simplex/branch_and_bound.cpp +++ b/cpp/src/dual_simplex/branch_and_bound.cpp @@ -1364,7 +1364,7 @@ lp_status_t branch_and_bound_t::solve_root_relaxation( root_status = lp_status_t::OPTIMAL; user_objective = root_crossover_soln_.user_objective; iter = root_crossover_soln_.iterations; - solver_name = "Barrier/PDLP and Crossover"; + solver_name = method_to_string(root_relax_solved_by); } else { root_status = root_status_future.get(); @@ -1381,13 +1381,13 @@ lp_status_t branch_and_bound_t::solve_root_relaxation( settings_.log.printf("\n"); if (root_status == lp_status_t::OPTIMAL) { - settings_.log.printf("Root relaxation solution found in %d iterations and %.2fs by %s\n", + settings_.log.printf("Root relaxation solution found in %d iterations and %.2fs with %s\n", iter, toc(start_time), solver_name.c_str()); settings_.log.printf("Root relaxation objective %+.8e\n", user_objective); } else { - settings_.log.printf("Root relaxation returned status: %s\n", + settings_.log.printf("Root relaxation returned: %s\n", lp_status_to_string(root_status).c_str()); } diff --git a/cpp/src/dual_simplex/branch_and_bound.hpp b/cpp/src/dual_simplex/branch_and_bound.hpp index 19621b889..7574f443d 100644 --- a/cpp/src/dual_simplex/branch_and_bound.hpp +++ b/cpp/src/dual_simplex/branch_and_bound.hpp @@ -7,6 +7,8 @@ #pragma once +#include + #include #include #include @@ -83,7 +85,8 @@ class branch_and_bound_t { const std::vector& reduced_costs, f_t objective, f_t user_objective, - i_t iterations) + i_t iterations, + method_t method) { if (!is_root_solution_set) { root_crossover_soln_.x = primal; @@ -93,6 +96,7 @@ class branch_and_bound_t { root_crossover_soln_.objective = objective; root_crossover_soln_.user_objective = user_objective; root_crossover_soln_.iterations = iterations; + root_relax_solved_by = method; root_crossover_solution_set_.store(true, std::memory_order_release); } } @@ -166,6 +170,7 @@ class branch_and_bound_t { f_t root_objective_; lp_solution_t root_relax_soln_; lp_solution_t root_crossover_soln_; + method_t root_relax_solved_by; std::vector edge_norms_; std::atomic root_crossover_solution_set_{false}; bool enable_concurrent_lp_root_solve_{false}; diff --git a/cpp/src/dual_simplex/crossover.cpp b/cpp/src/dual_simplex/crossover.cpp index 8ee3fb0ce..3a53ccb22 100644 --- a/cpp/src/dual_simplex/crossover.cpp +++ b/cpp/src/dual_simplex/crossover.cpp @@ -534,7 +534,7 @@ i_t dual_push(const lp_problem_t& lp, return -1; } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return -2; } } @@ -832,7 +832,7 @@ i_t primal_push(const lp_problem_t& lp, return -1; } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return -2; } } @@ -1163,7 +1163,7 @@ crossover_status_t crossover(const lp_problem_t& lp, return crossover_status_t::TIME_LIMIT; } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return crossover_status_t::CONCURRENT_LIMIT; } @@ -1250,7 +1250,7 @@ crossover_status_t crossover(const lp_problem_t& lp, return crossover_status_t::TIME_LIMIT; } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return crossover_status_t::CONCURRENT_LIMIT; } primal_infeas = primal_infeasibility(lp, settings, vstatus, solution.x); @@ -1386,7 +1386,7 @@ crossover_status_t crossover(const lp_problem_t& lp, return crossover_status_t::TIME_LIMIT; } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return crossover_status_t::CONCURRENT_LIMIT; } solution.iterations += iter; diff --git a/cpp/src/dual_simplex/pseudo_costs.cpp b/cpp/src/dual_simplex/pseudo_costs.cpp index f56f3be4b..a62e235f5 100644 --- a/cpp/src/dual_simplex/pseudo_costs.cpp +++ b/cpp/src/dual_simplex/pseudo_costs.cpp @@ -279,7 +279,7 @@ void strong_branching(const user_problem_t& original_problem, } settings.log.printf( - "Batch PDLP strong branching took %.2f seconds. Solved %d/%d with max %d iterations\n", + "Strong branching took %.2f seconds with Batch PDLP. Solved %d/%d with max %d iterations\n", duration.count(), amount_done, fractional.size() * 2, @@ -351,7 +351,7 @@ void strong_branching(const user_problem_t& original_problem, } std::chrono::steady_clock::time_point end_timea = std::chrono::steady_clock::now(); std::chrono::duration duration = end_timea - start_timea; - settings.log.printf("Dual Simplex Strong branching took %.2f seconds\n", duration.count()); + settings.log.printf("Strong branching took %.2f seconds with Dual Simplex\n", duration.count()); } pc.update_pseudo_costs_from_strong_branching(fractional, root_soln); diff --git a/cpp/src/dual_simplex/right_looking_lu.cpp b/cpp/src/dual_simplex/right_looking_lu.cpp index a63c1181f..e15a83271 100644 --- a/cpp/src/dual_simplex/right_looking_lu.cpp +++ b/cpp/src/dual_simplex/right_looking_lu.cpp @@ -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 */ @@ -1114,7 +1114,7 @@ i_t right_looking_lu_row_permutation_only(const csc_matrix_t& A, } if (settings.concurrent_halt != nullptr && *settings.concurrent_halt == 1) { - settings.log.printf("Concurrent halt\n"); + if (!settings.inside_mip) { settings.log.printf("Concurrent halt\n"); } return -2; } } diff --git a/cpp/src/linear_programming/pdlp.cu b/cpp/src/linear_programming/pdlp.cu index 8a05f1b2a..ddee8b124 100644 --- a/cpp/src/linear_programming/pdlp.cu +++ b/cpp/src/linear_programming/pdlp.cu @@ -764,10 +764,13 @@ pdlp_solver_t::check_batch_termination(const timer_t& timer) batch_solution_to_return_ .get_additional_termination_informations()[climber_strategies_[i].original_index] .total_number_of_attempted_steps = pdhg_solver_.get_total_pdhg_iterations(); - batch_solution_to_return_ - .get_additional_termination_informations()[climber_strategies_[i].original_index] - .solved_by_pdlp = (current_termination_strategy_.get_termination_status(i) != - pdlp_termination_status_t::ConcurrentLimit); + + if (current_termination_strategy_.get_termination_status(i) != + pdlp_termination_status_t::ConcurrentLimit) { + batch_solution_to_return_ + .get_additional_termination_informations()[climber_strategies_[i].original_index] + .solved_by = method_t::PDLP; + } } current_termination_strategy_.fill_gpu_terms_stats(total_pdlp_iterations_); RAFT_CUDA_TRY(cudaStreamSynchronize(stream_view_)); @@ -832,10 +835,13 @@ pdlp_solver_t::check_batch_termination(const timer_t& timer) batch_solution_to_return_ .get_additional_termination_informations()[climber_strategies_[i].original_index] .total_number_of_attempted_steps = pdhg_solver_.get_total_pdhg_iterations(); - batch_solution_to_return_ - .get_additional_termination_informations()[climber_strategies_[i].original_index] - .solved_by_pdlp = (current_termination_strategy_.get_termination_status(i) != - pdlp_termination_status_t::ConcurrentLimit); + + if (current_termination_strategy_.get_termination_status(i) != + pdlp_termination_status_t::ConcurrentLimit) { + batch_solution_to_return_ + .get_additional_termination_informations()[climber_strategies_[i].original_index] + .solved_by = method_t::PDLP; + } } } if (to_remove.size() > 0) { diff --git a/cpp/src/linear_programming/solve.cu b/cpp/src/linear_programming/solve.cu index db15eed82..34a60ceda 100644 --- a/cpp/src/linear_programming/solve.cu +++ b/cpp/src/linear_programming/solve.cu @@ -315,7 +315,7 @@ optimization_problem_solution_t convert_dual_simplex_sol( f_t duration, f_t norm_user_objective, f_t norm_rhs, - i_t method) + method_t method) { auto to_termination_status = [](dual_simplex::lp_status_t status) { switch (status) { @@ -344,7 +344,7 @@ optimization_problem_solution_t convert_dual_simplex_sol( std::vector< typename optimization_problem_solution_t::additional_termination_information_t> info(1); - info[0].solved_by_pdlp = false; + info[0].solved_by = method; info[0].primal_objective = solution.user_objective; info[0].dual_objective = solution.user_objective; info[0].gap = 0.0; @@ -375,7 +375,7 @@ optimization_problem_solution_t convert_dual_simplex_sol( termination_status != pdlp_termination_status_t::TimeLimit && termination_status != pdlp_termination_status_t::ConcurrentLimit) { CUOPT_LOG_INFO("%s Solve status %s", - method == 0 ? "Dual Simplex" : "Barrier", + method == method_t::DualSimplex ? "Dual Simplex" : "Barrier", sol.get_termination_status_string().c_str()); } @@ -447,7 +447,7 @@ optimization_problem_solution_t run_barrier( std::get<2>(sol_dual_simplex), std::get<3>(sol_dual_simplex), std::get<4>(sol_dual_simplex), - 1); + method_t::Barrier); } template @@ -522,7 +522,7 @@ optimization_problem_solution_t run_dual_simplex( std::get<2>(sol_dual_simplex), std::get<3>(sol_dual_simplex), std::get<4>(sol_dual_simplex), - 0); + method_t::DualSimplex); } template @@ -989,7 +989,7 @@ optimization_problem_solution_t run_concurrent( std::get<2>(*sol_dual_simplex_ptr), std::get<3>(*sol_dual_simplex_ptr), std::get<4>(*sol_dual_simplex_ptr), - 0) + method_t::DualSimplex) : optimization_problem_solution_t{pdlp_termination_status_t::ConcurrentLimit, problem.handle_ptr->get_stream()}; @@ -1000,7 +1000,7 @@ optimization_problem_solution_t run_concurrent( std::get<2>(*sol_barrier_ptr), std::get<3>(*sol_barrier_ptr), std::get<4>(*sol_barrier_ptr), - 1); + method_t::Barrier); f_t end_time = timer.elapsed_time(); CUOPT_LOG_CONDITIONAL_INFO(!settings.inside_mip, diff --git a/cpp/src/linear_programming/solver_solution.cu b/cpp/src/linear_programming/solver_solution.cu index ff6234024..adb4a9506 100644 --- a/cpp/src/linear_programming/solver_solution.cu +++ b/cpp/src/linear_programming/solver_solution.cu @@ -168,12 +168,12 @@ void optimization_problem_solution_t::write_additional_termination_sta myfile << "\t\"Additional termination information\" : { " << std::endl; myfile << "\t\"Number of steps taken\" : " << termination_stats.number_of_steps_taken << "," << std::endl; - if (termination_stats.solved_by_pdlp) { + if (termination_stats.solved_by == method_t::PDLP) { myfile << "\t\"Total number of attempted steps\" : " << termination_stats.total_number_of_attempted_steps << "," << std::endl; } myfile << "\t\"Total solve time\" : " << termination_stats.solve_time; - if (termination_stats.solved_by_pdlp) { + if (termination_stats.solved_by == method_t::PDLP) { myfile << "," << std::endl; myfile << "\t\t\"Convergence measures\" : { " << std::endl; myfile << "\t\t\t\"Absolute primal residual\" : " << termination_stats.l2_primal_residual << "," diff --git a/cpp/src/linear_programming/termination_strategy/termination_strategy.cu b/cpp/src/linear_programming/termination_strategy/termination_strategy.cu index 1041bd98a..a0200d159 100644 --- a/cpp/src/linear_programming/termination_strategy/termination_strategy.cu +++ b/cpp/src/linear_programming/termination_strategy/termination_strategy.cu @@ -596,8 +596,10 @@ pdlp_termination_strategy_t::fill_return_problem_solution( &infeasibility_information_view.dual_ray_linear_objective[i], 1, stream_view_); - term_stats_vector[i].solved_by_pdlp = - (termination_status[i] != pdlp_termination_status_t::ConcurrentLimit); + + if (termination_status[i] != pdlp_termination_status_t::ConcurrentLimit) { + term_stats_vector[i].solved_by = lp_solver_type_t::PDLP; + } } RAFT_CUDA_TRY(cudaStreamSynchronize(stream_view_)); diff --git a/cpp/src/linear_programming/utilities/cython_solve.cu b/cpp/src/linear_programming/utilities/cython_solve.cu index f49e2057b..2260795af 100644 --- a/cpp/src/linear_programming/utilities/cython_solve.cu +++ b/cpp/src/linear_programming/utilities/cython_solve.cu @@ -182,7 +182,7 @@ linear_programming_ret_t call_solve_lp( solution.get_additional_termination_information().gap, solution.get_additional_termination_information().number_of_steps_taken, solution.get_additional_termination_information().solve_time, - solution.get_additional_termination_information().solved_by_pdlp}; + solution.get_additional_termination_information().solved_by}; return lp_ret; } diff --git a/cpp/src/mip/diversity/diversity_manager.cu b/cpp/src/mip/diversity/diversity_manager.cu index cf2180801..b362aa061 100644 --- a/cpp/src/mip/diversity/diversity_manager.cu +++ b/cpp/src/mip/diversity/diversity_manager.cu @@ -438,9 +438,10 @@ solution_t diversity_manager_t::run_solver() auto user_obj = lp_result.get_objective_value(); auto solver_obj = problem_ptr->get_solver_obj_from_user_obj(user_obj); auto iterations = lp_result.get_additional_termination_information().number_of_steps_taken; + auto method = lp_result.get_additional_termination_information().solved_by; // Set for the B&B (param4 expects solver space, param5 expects user space) problem_ptr->set_root_relaxation_solution_callback( - host_primal, host_dual, host_reduced_costs, solver_obj, user_obj, iterations); + host_primal, host_dual, host_reduced_costs, solver_obj, user_obj, iterations, method); } // in case the pdlp returned var boudns that are out of bounds diff --git a/cpp/src/mip/problem/problem.cuh b/cpp/src/mip/problem/problem.cuh index 6cbd5e5a5..cc8e60b92 100644 --- a/cpp/src/mip/problem/problem.cuh +++ b/cpp/src/mip/problem/problem.cuh @@ -18,6 +18,7 @@ #include #include +#include #include #include "host_helper.cuh" #include "problem_fixing.cuh" @@ -229,8 +230,13 @@ class problem_t { rmm::device_uvector integer_fixed_variable_map; std::function&)> branch_and_bound_callback; - std::function&, const std::vector&, const std::vector&, f_t, f_t, i_t)> + std::function&, + const std::vector&, + const std::vector&, + f_t, + f_t, + i_t, + method_t)> set_root_relaxation_solution_callback; typename mip_solver_settings_t::tolerances_t tolerances{}; diff --git a/cpp/src/mip/solver.cu b/cpp/src/mip/solver.cu index b88d39eaa..febf5b106 100644 --- a/cpp/src/mip/solver.cu +++ b/cpp/src/mip/solver.cu @@ -238,7 +238,8 @@ solution_t mip_solver_t::run_solver() std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, - std::placeholders::_6); + std::placeholders::_6, + std::placeholders::_7); // Fork a thread for branch and bound // std::async and std::future allow us to get the return value of bb::solve() diff --git a/cpp/tests/linear_programming/c_api_tests/c_api_test.c b/cpp/tests/linear_programming/c_api_tests/c_api_test.c index 799a42914..b62abde13 100644 --- a/cpp/tests/linear_programming/c_api_tests/c_api_test.c +++ b/cpp/tests/linear_programming/c_api_tests/c_api_test.c @@ -18,7 +18,6 @@ #error "This file must be compiled as C code" #endif - int check_problem(cuOptOptimizationProblem problem, cuopt_int_t num_constraints, cuopt_int_t num_variables, @@ -38,47 +37,36 @@ int check_problem(cuOptOptimizationProblem problem, const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: - return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: - return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: - return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: - return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: - return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: - return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: - return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: - return "Feasible found"; + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; } return "Unknown"; } +int test_int_size() { return cuOptGetIntSize(); } -int test_int_size() { - return cuOptGetIntSize(); -} +int test_float_size() { return cuOptGetFloatSize(); } -int test_float_size() { - return cuOptGetFloatSize(); -} - -cuopt_int_t test_missing_file() { +cuopt_int_t test_missing_file() +{ cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; - cuopt_int_t status = cuOptReadProblem("missing_file.mps", &problem); + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; + cuopt_int_t status = cuOptReadProblem("missing_file.mps", &problem); cuOptDestroyProblem(&problem); cuOptDestroySolverSettings(&settings); cuOptDestroySolution(&solution); return status; } -cuopt_int_t test_bad_parameter_name() { +cuopt_int_t test_bad_parameter_name() +{ cuOptSolverSettings settings = NULL; cuopt_int_t status; cuopt_int_t value; @@ -332,7 +320,7 @@ cuopt_int_t burglar_problem() cuopt_int_t row_offsets[] = {0, NUM_ITEMS}; cuopt_int_t column_indices[NUM_ITEMS]; - cuopt_float_t rhs[] = {max_weight}; + cuopt_float_t rhs[] = {max_weight}; char constraint_sense[] = {CUOPT_LESS_THAN}; cuopt_float_t lower_bounds[NUM_ITEMS]; cuopt_float_t upper_bounds[NUM_ITEMS]; @@ -428,9 +416,9 @@ cuopt_int_t burglar_problem() printf("Error getting termination status\n"); goto DONE; } - if (termination_status != CUOPT_TERIMINATION_STATUS_OPTIMAL) { + if (termination_status != CUOPT_TERMINATION_STATUS_OPTIMAL) { printf("Error: expected termination status to be %d, but got %d\n", - CUOPT_TERIMINATION_STATUS_OPTIMAL, + CUOPT_TERMINATION_STATUS_OPTIMAL, termination_status); status = -1; goto DONE; @@ -453,11 +441,16 @@ cuopt_int_t burglar_problem() return status; } -int solve_mps_file(const char* filename, double time_limit, double iteration_limit, int* termination_status_ptr, double* solve_time_ptr, int method) +int solve_mps_file(const char* filename, + double time_limit, + double iteration_limit, + int* termination_status_ptr, + double* solve_time_ptr, + int method) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; cuopt_int_t status; cuopt_int_t is_mip; cuopt_int_t termination_status = -1; @@ -500,9 +493,10 @@ int solve_mps_file(const char* filename, double time_limit, double iteration_lim } status = cuOptSolve(problem, settings, &solution); if (status != CUOPT_SUCCESS) { - #define ERROR_BUFFER_SIZE 1024 +#define ERROR_BUFFER_SIZE 1024 char error_string[ERROR_BUFFER_SIZE]; - cuopt_int_t error_string_status = cuOptGetErrorString(solution, error_string, ERROR_BUFFER_SIZE); + cuopt_int_t error_string_status = + cuOptGetErrorString(solution, error_string, ERROR_BUFFER_SIZE); if (error_string_status != CUOPT_SUCCESS) { printf("Error getting error string\n"); goto DONE; @@ -572,14 +566,14 @@ int check_problem(cuOptOptimizationProblem problem, char* check_variable_types; cuopt_int_t status; check_objective_coefficients = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); - check_row_offsets = (cuopt_int_t*)malloc((num_constraints + 1) * sizeof(cuopt_int_t)); - check_column_indices = (cuopt_int_t*)malloc(nnz * sizeof(cuopt_int_t)); - check_values = (cuopt_float_t*)malloc(nnz * sizeof(cuopt_float_t)); - check_constraint_sense = (char*)malloc(num_constraints * sizeof(char)); - check_rhs = (cuopt_float_t*)malloc(num_constraints * sizeof(cuopt_float_t)); - check_var_lower_bounds = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); - check_var_upper_bounds = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); - check_variable_types = (char*)malloc(num_variables * sizeof(char)); + check_row_offsets = (cuopt_int_t*)malloc((num_constraints + 1) * sizeof(cuopt_int_t)); + check_column_indices = (cuopt_int_t*)malloc(nnz * sizeof(cuopt_int_t)); + check_values = (cuopt_float_t*)malloc(nnz * sizeof(cuopt_float_t)); + check_constraint_sense = (char*)malloc(num_constraints * sizeof(char)); + check_rhs = (cuopt_float_t*)malloc(num_constraints * sizeof(cuopt_float_t)); + check_var_lower_bounds = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); + check_var_upper_bounds = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); + check_variable_types = (char*)malloc(num_variables * sizeof(char)); status = cuOptGetNumConstraints(problem, &check_num_constraints); if (status != CUOPT_SUCCESS) { @@ -637,7 +631,9 @@ int check_problem(cuOptOptimizationProblem problem, goto DONE; } if (check_objective_offset != objective_offset) { - printf("Error: expected objective offset to be %f, but got %f\n", objective_offset, check_objective_offset); + printf("Error: expected objective offset to be %f, but got %f\n", + objective_offset, + check_objective_offset); status = -1; goto DONE; } @@ -791,9 +787,8 @@ int check_problem(cuOptOptimizationProblem problem, cuopt_int_t test_infeasible_problem() { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; - + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; /* Solve the following problem minimize 0 @@ -812,21 +807,28 @@ cuopt_int_t test_infeasible_problem() 0 1 2 3 */ - cuopt_int_t num_variables = 4; + cuopt_int_t num_variables = 4; cuopt_int_t num_constraints = 9; - cuopt_int_t nnz = 17; - cuopt_int_t row_offsets[] = {0, 2, 4, 6, 7, 9, 10, 12, 15, 17}; + cuopt_int_t nnz = 17; + cuopt_int_t row_offsets[] = {0, 2, 4, 6, 7, 9, 10, 12, 15, 17}; // clang-format off // row1, row2, row3, row4, row5,row6, row7, row8, row9 cuopt_int_t column_indices[] = {0, 1, 0, 1, 0, 1, 3, 2, 3, 2, 0, 3, 0, 1, 2, 1, 2}; cuopt_float_t values[] = {-0.5, 1.0, 2.0, -1.0, 3.0, 1.0, 1.0, 3.0, -1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0}; // clang-format on - cuopt_float_t rhs[] = {0.5, 3.0, 6.0, 2.0, 2.0, 5.0, 10.0, 14.0, 1.0}; - char constraint_sense[] = {CUOPT_GREATER_THAN, CUOPT_GREATER_THAN, - CUOPT_LESS_THAN, CUOPT_LESS_THAN, CUOPT_LESS_THAN, - CUOPT_GREATER_THAN, CUOPT_LESS_THAN, CUOPT_LESS_THAN, CUOPT_GREATER_THAN}; + cuopt_float_t rhs[] = {0.5, 3.0, 6.0, 2.0, 2.0, 5.0, 10.0, 14.0, 1.0}; + char constraint_sense[] = {CUOPT_GREATER_THAN, + CUOPT_GREATER_THAN, + CUOPT_LESS_THAN, + CUOPT_LESS_THAN, + CUOPT_LESS_THAN, + CUOPT_GREATER_THAN, + CUOPT_LESS_THAN, + CUOPT_LESS_THAN, + CUOPT_GREATER_THAN}; cuopt_float_t var_lower_bounds[] = {0.0, 0.0, 0.0, 0.0}; - cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY}; + cuopt_float_t var_upper_bounds[] = { + CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY}; char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS, CUOPT_CONTINUOUS, CUOPT_CONTINUOUS}; cuopt_float_t objective_coefficients[] = {0.0, 0.0, 0.0, 0.0}; @@ -835,19 +837,19 @@ cuopt_int_t test_infeasible_problem() cuopt_float_t objective_value; cuopt_int_t status = cuOptCreateProblem(num_constraints, - num_variables, - CUOPT_MINIMIZE, - 0.0, - objective_coefficients, - row_offsets, - column_indices, - values, - constraint_sense, - rhs, - var_lower_bounds, - var_upper_bounds, - variable_types, - &problem); + num_variables, + CUOPT_MINIMIZE, + 0.0, + objective_coefficients, + row_offsets, + column_indices, + values, + constraint_sense, + rhs, + var_lower_bounds, + var_upper_bounds, + variable_types, + &problem); if (status != CUOPT_SUCCESS) { printf("Error creating problem\n"); goto DONE; @@ -898,9 +900,9 @@ cuopt_int_t test_infeasible_problem() printf("Error getting termination status\n"); goto DONE; } - if (termination_status != CUOPT_TERIMINATION_STATUS_INFEASIBLE) { + if (termination_status != CUOPT_TERMINATION_STATUS_INFEASIBLE) { printf("Error: expected termination status to be %d, but got %d\n", - CUOPT_TERIMINATION_STATUS_INFEASIBLE, + CUOPT_TERMINATION_STATUS_INFEASIBLE, termination_status); status = -1; goto DONE; @@ -923,12 +925,11 @@ cuopt_int_t test_infeasible_problem() return status; } - -cuopt_int_t test_ranged_problem(cuopt_int_t *termination_status_ptr, cuopt_float_t *objective_ptr) +cuopt_int_t test_ranged_problem(cuopt_int_t* termination_status_ptr, cuopt_float_t* objective_ptr) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; // maximize obj: 5 * x + 8 * y; // subject to c1: 2*x + 3*y <= 12; @@ -937,22 +938,22 @@ cuopt_int_t test_ranged_problem(cuopt_int_t *termination_status_ptr, cuopt_float // subject to x_limit: 0 <= x <= 10; // subject to y_limit: 0 <= y <= 10; - cuopt_int_t num_variables = 2; - cuopt_int_t num_constraints = 3; - cuopt_int_t nnz = 6; - cuopt_int_t objective_sense = CUOPT_MAXIMIZE; - cuopt_float_t objective_offset = 0.0; - cuopt_float_t objective_coefficients[] = {5.0, 8.0}; - cuopt_int_t row_offsets[] = {0, 2, 4, 6}; - cuopt_int_t column_indices[] = {0, 1, 0, 1, 0, 1}; - cuopt_float_t values[] = {2.0, 3.0, 3.0, 1.0, 1.0, 2.0}; - cuopt_float_t constraint_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY, 2.0}; - cuopt_float_t constraint_upper_bounds[] = {12.0, 6.0, 8.0}; + cuopt_int_t num_variables = 2; + cuopt_int_t num_constraints = 3; + cuopt_int_t nnz = 6; + cuopt_int_t objective_sense = CUOPT_MAXIMIZE; + cuopt_float_t objective_offset = 0.0; + cuopt_float_t objective_coefficients[] = {5.0, 8.0}; + cuopt_int_t row_offsets[] = {0, 2, 4, 6}; + cuopt_int_t column_indices[] = {0, 1, 0, 1, 0, 1}; + cuopt_float_t values[] = {2.0, 3.0, 3.0, 1.0, 1.0, 2.0}; + cuopt_float_t constraint_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY, 2.0}; + cuopt_float_t constraint_upper_bounds[] = {12.0, 6.0, 8.0}; cuopt_float_t constraint_lower_bounds_check[] = {1.0, 1.0, 1.0}; cuopt_float_t constraint_upper_bounds_check[] = {1.0, 1.0, 1.0}; - cuopt_float_t variable_lower_bounds[] = {0.0, 0.0}; - cuopt_float_t variable_upper_bounds[] = {10.0, 10.0}; - char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS}; + cuopt_float_t variable_lower_bounds[] = {0.0, 0.0}; + cuopt_float_t variable_upper_bounds[] = {10.0, 10.0}; + char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS}; cuopt_int_t status; status = cuOptCreateRangedProblem(num_constraints, @@ -989,13 +990,17 @@ cuopt_int_t test_ranged_problem(cuopt_int_t *termination_status_ptr, cuopt_float for (cuopt_int_t i = 0; i < num_constraints; i++) { if (constraint_lower_bounds_check[i] != constraint_lower_bounds[i]) { printf("Error: expected constraint lower bound %d to be %f, but got %f\n", - i, constraint_lower_bounds[i], constraint_lower_bounds_check[i]); + i, + constraint_lower_bounds[i], + constraint_lower_bounds_check[i]); status = -1; goto DONE; } if (constraint_upper_bounds_check[i] != constraint_upper_bounds[i]) { printf("Error: expected constraint upper bound %d to be %f, but got %f\n", - i, constraint_upper_bounds[i], constraint_upper_bounds_check[i]); + i, + constraint_upper_bounds[i], + constraint_upper_bounds_check[i]); status = -1; goto DONE; } @@ -1043,8 +1048,8 @@ cuopt_int_t test_ranged_problem(cuopt_int_t *termination_status_ptr, cuopt_float cuopt_int_t test_invalid_bounds(cuopt_int_t test_mip) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; /* Test the invalid bounds scenario: maximize 2*x @@ -1059,17 +1064,17 @@ cuopt_int_t test_invalid_bounds(cuopt_int_t test_mip) - Result: 1.0 <= x <= 0.0 (INVALID!) */ - cuopt_int_t num_variables = 1; + cuopt_int_t num_variables = 1; cuopt_int_t num_constraints = 2; - cuopt_int_t nnz = 2; + cuopt_int_t nnz = 2; // CSR format constraint matrix // From the constraints: // x >= 0.2 // x <= 0.5 - cuopt_int_t row_offsets[] = {0, 1, 2}; + cuopt_int_t row_offsets[] = {0, 1, 2}; cuopt_int_t column_indices[] = {0, 0}; - cuopt_float_t values[] = {1.0, 1.0}; + cuopt_float_t values[] = {1.0, 1.0}; // Objective coefficients // From the objective function: maximize 2*x @@ -1101,19 +1106,19 @@ cuopt_int_t test_invalid_bounds(cuopt_int_t test_mip) // Create the problem status = cuOptCreateRangedProblem(num_constraints, - num_variables, - CUOPT_MAXIMIZE, // maximize - 0.0, // objective offset - objective_coefficients, - row_offsets, - column_indices, - values, - constraint_lower_bounds, - constraint_upper_bounds, - var_lower_bounds, - var_upper_bounds, - variable_types, - &problem); + num_variables, + CUOPT_MAXIMIZE, // maximize + 0.0, // objective offset + objective_coefficients, + row_offsets, + column_indices, + values, + constraint_lower_bounds, + constraint_upper_bounds, + var_lower_bounds, + var_upper_bounds, + variable_types, + &problem); printf("cuOptCreateRangedProblem returned: %d\n", status); @@ -1151,14 +1156,13 @@ cuopt_int_t test_invalid_bounds(cuopt_int_t test_mip) printf("Error getting termination status: %d\n", status); goto DONE; } - if (termination_status != CUOPT_TERIMINATION_STATUS_INFEASIBLE) { + if (termination_status != CUOPT_TERMINATION_STATUS_INFEASIBLE) { printf("Error: expected termination status to be %d, but got %d\n", - CUOPT_TERIMINATION_STATUS_INFEASIBLE, + CUOPT_TERMINATION_STATUS_INFEASIBLE, termination_status); status = CUOPT_VALIDATION_ERROR; goto DONE; - } - else { + } else { printf("✓ Problem found infeasible as expected\n"); status = CUOPT_SUCCESS; goto DONE; @@ -1173,13 +1177,15 @@ cuopt_int_t test_invalid_bounds(cuopt_int_t test_mip) // Print results printf("\nResults:\n"); printf("--------\n"); - printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status); + printf("Termination status: %s (%d)\n", + termination_status_to_string(termination_status), + termination_status); printf("Solve time: %f seconds\n", time); printf("Objective value: %f\n", objective_value); // Get and print solution variables cuopt_float_t* solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); - status = cuOptGetPrimalSolution(solution, solution_values); + status = cuOptGetPrimalSolution(solution, solution_values); if (status != CUOPT_SUCCESS) { printf("Error getting solution values: %d\n", status); free(solution_values); @@ -1200,11 +1206,12 @@ cuopt_int_t test_invalid_bounds(cuopt_int_t test_mip) return status; } -cuopt_int_t test_quadratic_problem(cuopt_int_t* termination_status_ptr, cuopt_float_t* objective_ptr) +cuopt_int_t test_quadratic_problem(cuopt_int_t* termination_status_ptr, + cuopt_float_t* objective_ptr) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; // minimize x1^2 + 4*x2^2 - 8*x1 - 16*x2 // subject to x1 + x2 >= 5 @@ -1213,22 +1220,22 @@ cuopt_int_t test_quadratic_problem(cuopt_int_t* termination_status_ptr, cuopt_fl // x1 <= 10 // x2 <= 10 - cuopt_int_t num_variables = 2; - cuopt_int_t num_constraints = 1; - cuopt_int_t objective_sense = CUOPT_MINIMIZE; - cuopt_float_t objective_offset = 0.0; + cuopt_int_t num_variables = 2; + cuopt_int_t num_constraints = 1; + cuopt_int_t objective_sense = CUOPT_MINIMIZE; + cuopt_float_t objective_offset = 0.0; cuopt_float_t objective_coefficients[] = {-8.0, -16.0}; - cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2}; - cuopt_int_t quadratic_objective_matrix_column_indices[] = {0, 1}; + cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2}; + cuopt_int_t quadratic_objective_matrix_column_indices[] = {0, 1}; cuopt_float_t quadratic_objective_matrix_coefficent_values[] = {1.0, 4.0}; - cuopt_int_t row_offsets[] = {0, 2}; + cuopt_int_t row_offsets[] = {0, 2}; cuopt_int_t column_indices[] = {0, 1}; - cuopt_float_t values[] = {1.0, 1.0}; + cuopt_float_t values[] = {1.0, 1.0}; cuopt_float_t constraint_bounds[] = {5.0}; - char constraint_sense[] = {'G'}; + char constraint_sense[] = {'G'}; cuopt_float_t var_lower_bounds[] = {3.0, 0.0}; cuopt_float_t var_upper_bounds[] = {10.0, 10.0}; @@ -1281,20 +1288,20 @@ cuopt_int_t test_quadratic_problem(cuopt_int_t* termination_status_ptr, cuopt_fl goto DONE; } - DONE: -cuOptDestroyProblem(&problem); -cuOptDestroySolverSettings(&settings); -cuOptDestroySolution(&solution); + cuOptDestroyProblem(&problem); + cuOptDestroySolverSettings(&settings); + cuOptDestroySolution(&solution); -return status; + return status; } -cuopt_int_t test_quadratic_ranged_problem(cuopt_int_t* termination_status_ptr, cuopt_float_t* objective_ptr) +cuopt_int_t test_quadratic_ranged_problem(cuopt_int_t* termination_status_ptr, + cuopt_float_t* objective_ptr) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; // minimize x1^2 + 4*x2^2 - 8*x1 - 16*x2 // subject to x1 + x2 >= 5 @@ -1302,18 +1309,18 @@ cuopt_int_t test_quadratic_ranged_problem(cuopt_int_t* termination_status_ptr, c // x2 >= 0 // x1 <= 10 // x2 <= 10 - cuopt_int_t num_variables = 2; - cuopt_int_t num_constraints = 1; - cuopt_int_t objective_sense = CUOPT_MINIMIZE; - cuopt_float_t objective_offset = 0.0; - cuopt_float_t objective_coefficients[] = {-8.0, -16.0}; - cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2}; - cuopt_int_t quadratic_objective_matrix_column_indices[] = {0, 1}; + cuopt_int_t num_variables = 2; + cuopt_int_t num_constraints = 1; + cuopt_int_t objective_sense = CUOPT_MINIMIZE; + cuopt_float_t objective_offset = 0.0; + cuopt_float_t objective_coefficients[] = {-8.0, -16.0}; + cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2}; + cuopt_int_t quadratic_objective_matrix_column_indices[] = {0, 1}; cuopt_float_t quadratic_objective_matrix_coefficent_values[] = {1.0, 4.0}; - cuopt_int_t row_offsets[] = {0, 2}; + cuopt_int_t row_offsets[] = {0, 2}; cuopt_int_t column_indices[] = {0, 1}; - cuopt_float_t values[] = {1.0, 1.0}; + cuopt_float_t values[] = {1.0, 1.0}; cuopt_float_t constraint_lower_bounds[] = {5.0}; cuopt_float_t constraint_upper_bounds[] = {100.0}; @@ -1324,21 +1331,21 @@ cuopt_int_t test_quadratic_ranged_problem(cuopt_int_t* termination_status_ptr, c cuopt_int_t status; status = cuOptCreateQuadraticRangedProblem(num_constraints, - num_variables, - objective_sense, - objective_offset, - objective_coefficients, - quadratic_objective_matrix_row_offsets, - quadratic_objective_matrix_column_indices, - quadratic_objective_matrix_coefficent_values, - row_offsets, - column_indices, - values, - constraint_lower_bounds, - constraint_upper_bounds, - var_lower_bounds, - var_upper_bounds, - &problem); + num_variables, + objective_sense, + objective_offset, + objective_coefficients, + quadratic_objective_matrix_row_offsets, + quadratic_objective_matrix_column_indices, + quadratic_objective_matrix_coefficent_values, + row_offsets, + column_indices, + values, + constraint_lower_bounds, + constraint_upper_bounds, + var_lower_bounds, + var_upper_bounds, + &problem); if (status != CUOPT_SUCCESS) { printf("Error creating problem: %d\n", status); @@ -1370,19 +1377,19 @@ cuopt_int_t test_quadratic_ranged_problem(cuopt_int_t* termination_status_ptr, c } DONE: -cuOptDestroyProblem(&problem); -cuOptDestroySolverSettings(&settings); -cuOptDestroySolution(&solution); + cuOptDestroyProblem(&problem); + cuOptDestroySolverSettings(&settings); + cuOptDestroySolution(&solution); -return status; + return status; } cuopt_int_t test_write_problem(const char* input_filename, const char* output_filename) { - cuOptOptimizationProblem problem = NULL; + cuOptOptimizationProblem problem = NULL; cuOptOptimizationProblem problem_read = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; cuopt_int_t status; cuopt_int_t termination_status; cuopt_float_t objective_value; @@ -1442,7 +1449,7 @@ cuopt_int_t test_write_problem(const char* input_filename, const char* output_fi printf("Termination status: %d, Objective: %f\n", termination_status, objective_value); - if (termination_status != CUOPT_TERIMINATION_STATUS_OPTIMAL) { + if (termination_status != CUOPT_TERMINATION_STATUS_OPTIMAL) { printf("Expected optimal status\n"); status = -1; goto DONE; diff --git a/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp b/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp index 273924ec0..b0ac32dcd 100644 --- a/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp +++ b/cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp @@ -29,7 +29,7 @@ TEST(c_api, afiro) int termination_status; EXPECT_EQ(solve_mps_file(filename.c_str(), 60, CUOPT_INFINITY, &termination_status), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ(termination_status, CUOPT_TERMINATION_STATUS_OPTIMAL); } // Test both LP and MIP codepaths @@ -50,7 +50,7 @@ TEST_P(TimeLimitTestFixture, time_limit) &solve_time, method), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_TIME_LIMIT); + EXPECT_EQ(termination_status, CUOPT_TERMINATION_STATUS_TIME_LIMIT); // Dual simplex is spending some time for factorizing the basis, and this computation does not // check for time limit @@ -74,7 +74,7 @@ TEST(c_api, iteration_limit) std::string filename = rapidsDatasetRootDir + "/linear_programming/" + "afiro_original.mps"; int termination_status; EXPECT_EQ(solve_mps_file(filename.c_str(), 60, 1, &termination_status), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT); + EXPECT_EQ(termination_status, CUOPT_TERMINATION_STATUS_ITERATION_LIMIT); } TEST(c_api, solve_time_bb_preemption) @@ -85,7 +85,7 @@ TEST(c_api, solve_time_bb_preemption) double solve_time = std::numeric_limits::quiet_NaN(); EXPECT_EQ(solve_mps_file(filename.c_str(), 5, CUOPT_INFINITY, &termination_status, &solve_time), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ(termination_status, CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_GT(solve_time, 0); // solve time should not be equal to 0, even on very simple instances // solved by B&B before the diversity solver has time to run } @@ -107,7 +107,7 @@ TEST(c_api, test_ranged_problem) cuopt_int_t termination_status; cuopt_float_t objective; EXPECT_EQ(test_ranged_problem(&termination_status, &objective), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ(termination_status, CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_NEAR(objective, 32.0, 1e-3); } @@ -124,7 +124,7 @@ TEST(c_api, test_quadratic_problem) cuopt_int_t termination_status; cuopt_float_t objective; EXPECT_EQ(test_quadratic_problem(&termination_status, &objective), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ(termination_status, CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_NEAR(objective, -32.0, 1e-3); } @@ -133,7 +133,7 @@ TEST(c_api, test_quadratic_ranged_problem) cuopt_int_t termination_status; cuopt_float_t objective; EXPECT_EQ(test_quadratic_ranged_problem(&termination_status, &objective), CUOPT_SUCCESS); - EXPECT_EQ(termination_status, (int)CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ(termination_status, (int)CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_NEAR(objective, -32.0, 1e-3); } diff --git a/cpp/tests/linear_programming/pdlp_test.cu b/cpp/tests/linear_programming/pdlp_test.cu index 994fa89fe..199e1067f 100644 --- a/cpp/tests/linear_programming/pdlp_test.cu +++ b/cpp/tests/linear_programming/pdlp_test.cu @@ -68,7 +68,7 @@ TEST(pdlp_class, run_double) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information().primal_objective)); } @@ -94,7 +94,7 @@ TEST(pdlp_class, run_double_very_low_accuracy) settings.method = cuopt::linear_programming::method_t::PDLP; optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information().primal_objective)); } @@ -116,7 +116,7 @@ TEST(pdlp_class, run_double_initial_solution) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information().primal_objective)); } @@ -138,7 +138,7 @@ TEST(pdlp_class, run_iteration_limit) settings.method = cuopt::linear_programming::method_t::PDLP; optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_ITERATION_LIMIT); // By default we would return all 0, we now return what we currently have so not all 0 EXPECT_FALSE(thrust::all_of(handle_.get_thrust_policy(), solution.get_primal_solution().begin(), @@ -164,7 +164,7 @@ TEST(pdlp_class, run_time_limit) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_TIME_LIMIT); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_TIME_LIMIT); // By default we would return all 0, we now return what we currently have so not all 0 EXPECT_FALSE(thrust::all_of(handle_.get_thrust_policy(), solution.get_primal_solution().begin(), @@ -219,7 +219,7 @@ TEST(pdlp_class, run_sub_mittleman) solve_lp(&handle_, op_problem, settings); printf( "running %s mode %d presolve? %d\n", name.c_str(), (int)solver_mode, settings.presolve); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( expected_objective_value, solution.get_additional_termination_information().primal_objective)); @@ -911,7 +911,7 @@ TEST(pdlp_class, dual_postsolve_size) solver_settings.dual_postsolve = true; optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_EQ(solution.get_dual_solution().size(), op_problem.get_n_constraints()); } @@ -919,7 +919,7 @@ TEST(pdlp_class, dual_postsolve_size) solver_settings.dual_postsolve = false; optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_EQ(solution.get_dual_solution().size(), 0); } } @@ -956,7 +956,7 @@ TEST(pdlp_class, run_empty_matrix_pdlp) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR); } // Should run thanks to Dual Simplex @@ -973,8 +973,8 @@ TEST(pdlp_class, run_empty_matrix_dual_simplex) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); - EXPECT_FALSE(solution.get_additional_termination_information().solved_by_pdlp); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); + EXPECT_EQ(solution.get_additional_termination_information().solved_by, method_t::DualSimplex); } TEST(pdlp_class, test_max) @@ -991,7 +991,7 @@ TEST(pdlp_class, test_max) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_NEAR( solution.get_additional_termination_information().primal_objective, 17.0, factor_tolerance); } @@ -1009,7 +1009,7 @@ TEST(pdlp_class, test_max_with_offset) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_NEAR( solution.get_additional_termination_information().primal_objective, 0.0, factor_tolerance); } @@ -1026,7 +1026,7 @@ TEST(pdlp_class, test_lp_no_constraints) optimization_problem_solution_t solution = solve_lp(&handle_, op_problem, solver_settings); - EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_NEAR( solution.get_additional_termination_information().primal_objective, 1.0, factor_tolerance); } @@ -1067,7 +1067,7 @@ TEST(pdlp_class, simple_batch_afiro) // All should be optimal with the right objective for (size_t i = 0; i < batch_size; ++i) { - EXPECT_EQ((int)solution.get_termination_status(i), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(i), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information(i).primal_objective)); } @@ -1158,10 +1158,10 @@ TEST(pdlp_class, simple_batch_different_bounds) // Both should be optimal // Climber #0 should have same objective as ref and #1 as the usual - EXPECT_EQ((int)solution2.get_termination_status(0), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution2.get_termination_status(0), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( new_primal, solution2.get_additional_termination_information(0).primal_objective)); - EXPECT_EQ((int)solution2.get_termination_status(1), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution2.get_termination_status(1), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution2.get_additional_termination_information(1).primal_objective)); @@ -1230,7 +1230,7 @@ TEST(pdlp_class, more_complex_batch_different_bounds) // All should be optimal for (size_t i = 0; i < batch_size; ++i) - EXPECT_EQ((int)solution3.get_termination_status(i), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution3.get_termination_status(i), CUOPT_TERMINATION_STATUS_OPTIMAL); // Climber #0 #2 #4 should have the same primal objective which is the unmodified one EXPECT_FALSE(is_incorrect_objective( @@ -1459,7 +1459,7 @@ TEST(pdlp_class, big_batch_afiro) // All should be optimal with for (size_t i = 0; i < batch_size; ++i) { - EXPECT_EQ((int)solution.get_termination_status(i), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(i), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information(i).primal_objective)); } @@ -1542,8 +1542,8 @@ TEST(pdlp_class, DISABLED_simple_batch_optimal_and_infeasible) solve_lp(&handle_, op_problem, solver_settings); // First should be primal infeasible and the second optimal with the correct - EXPECT_EQ((int)solution.get_termination_status(0), CUOPT_TERIMINATION_STATUS_INFEASIBLE); - EXPECT_EQ((int)solution.get_termination_status(1), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(0), CUOPT_TERMINATION_STATUS_INFEASIBLE); + EXPECT_EQ((int)solution.get_termination_status(1), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information(1).primal_objective)); } @@ -1579,13 +1579,13 @@ TEST(pdlp_class, DISABLED_larger_batch_optimal_and_infeasible) solve_lp(&handle_, op_problem, solver_settings); // #1 and #3 should be infeasible - EXPECT_EQ((int)solution.get_termination_status(1), CUOPT_TERIMINATION_STATUS_INFEASIBLE); - EXPECT_EQ((int)solution.get_termination_status(3), CUOPT_TERIMINATION_STATUS_INFEASIBLE); + EXPECT_EQ((int)solution.get_termination_status(1), CUOPT_TERMINATION_STATUS_INFEASIBLE); + EXPECT_EQ((int)solution.get_termination_status(3), CUOPT_TERMINATION_STATUS_INFEASIBLE); // Rest should be feasible with the correct primal objective - EXPECT_EQ((int)solution.get_termination_status(0), CUOPT_TERIMINATION_STATUS_OPTIMAL); - EXPECT_EQ((int)solution.get_termination_status(2), CUOPT_TERIMINATION_STATUS_OPTIMAL); - EXPECT_EQ((int)solution.get_termination_status(4), CUOPT_TERIMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(0), CUOPT_TERMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(2), CUOPT_TERMINATION_STATUS_OPTIMAL); + EXPECT_EQ((int)solution.get_termination_status(4), CUOPT_TERMINATION_STATUS_OPTIMAL); EXPECT_FALSE(is_incorrect_objective( afiro_primal_objective, solution.get_additional_termination_information(0).primal_objective)); diff --git a/cpp/tests/mip/bounds_standardization_test.cu b/cpp/tests/mip/bounds_standardization_test.cu index 0c8b6739b..769d52f5c 100644 --- a/cpp/tests/mip/bounds_standardization_test.cu +++ b/cpp/tests/mip/bounds_standardization_test.cu @@ -67,7 +67,7 @@ void test_bounds_standardization_test(std::string test_instance) // run the problem through pdlp auto result_1 = detail::get_relaxed_lp_solution(standardized_problem, solution_1, lp_settings); solution_1.compute_feasibility(); - bool sol_1_feasible = (int)result_1.get_termination_status() == CUOPT_TERIMINATION_STATUS_OPTIMAL; + bool sol_1_feasible = (int)result_1.get_termination_status() == CUOPT_TERMINATION_STATUS_OPTIMAL; // the problem might not be feasible in terms of per constraint residual // only consider the pdlp results EXPECT_TRUE(sol_1_feasible); diff --git a/cpp/tests/mip/elim_var_remap_test.cu b/cpp/tests/mip/elim_var_remap_test.cu index 6e1ea02ca..97b330f0c 100644 --- a/cpp/tests/mip/elim_var_remap_test.cu +++ b/cpp/tests/mip/elim_var_remap_test.cu @@ -152,8 +152,8 @@ void test_elim_var_solution(std::string test_instance) auto result_1 = detail::get_relaxed_lp_solution(standardized_problem, solution_1, lp_settings); solution_1.compute_feasibility(); // the solution might not be feasible per row as we are getting the result of pdlp - bool sol_1_feasible = (int)result_1.get_termination_status() == CUOPT_TERIMINATION_STATUS_OPTIMAL; - EXPECT_EQ((int)result_1.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + bool sol_1_feasible = (int)result_1.get_termination_status() == CUOPT_TERMINATION_STATUS_OPTIMAL; + EXPECT_EQ((int)result_1.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); standardized_problem.post_process_solution(solution_1); solution_1.problem_ptr = &original_problem; auto opt_sol_1 = solution_1.get_solution(sol_1_feasible, solver_stats_t{}); @@ -181,8 +181,8 @@ void test_elim_var_solution(std::string test_instance) // run the problem through pdlp auto result_2 = detail::get_relaxed_lp_solution(sub_problem, solution_2, lp_settings_2); solution_2.compute_feasibility(); - bool sol_2_feasible = (int)result_2.get_termination_status() == CUOPT_TERIMINATION_STATUS_OPTIMAL; - EXPECT_EQ((int)result_2.get_termination_status(), CUOPT_TERIMINATION_STATUS_OPTIMAL); + bool sol_2_feasible = (int)result_2.get_termination_status() == CUOPT_TERMINATION_STATUS_OPTIMAL; + EXPECT_EQ((int)result_2.get_termination_status(), CUOPT_TERMINATION_STATUS_OPTIMAL); sub_problem.post_process_solution(solution_2); solution_2.problem_ptr = &original_problem; auto opt_sol_2 = solution_2.get_solution(sol_2_feasible, solver_stats_t{}); diff --git a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/milp_mps_example.c b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/milp_mps_example.c index fe59f2fc4..7f0da3404 100644 --- a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/milp_mps_example.c +++ b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/milp_mps_example.c @@ -1,5 +1,5 @@ /* - * 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 */ /* @@ -13,32 +13,23 @@ const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: - return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: - return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: - return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: - return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: - return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: - return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: - return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: - return "Feasible found"; - default: - return "Unknown"; + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; + default: return "Unknown"; } } cuopt_int_t solve_mps_file(const char* filename) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; cuopt_int_t status; cuopt_float_t time; cuopt_int_t termination_status; @@ -106,13 +97,15 @@ cuopt_int_t solve_mps_file(const char* filename) printf("\nResults:\n"); printf("--------\n"); printf("Number of variables: %d\n", num_variables); - printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status); + printf("Termination status: %s (%d)\n", + termination_status_to_string(termination_status), + termination_status); printf("Solve time: %f seconds\n", time); printf("Objective value: %f\n", objective_value); // Get and print solution variables solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); - status = cuOptGetPrimalSolution(solution, solution_values); + status = cuOptGetPrimalSolution(solution, solution_values); if (status != CUOPT_SUCCESS) { printf("Error getting solution values: %d\n", status); goto DONE; @@ -132,7 +125,8 @@ cuopt_int_t solve_mps_file(const char* filename) return status; } -int main(int argc, char* argv[]) { +int main(int argc, char* argv[]) +{ if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; diff --git a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/mps_file_example.c b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/mps_file_example.c index 6fb3a4fc5..a45f0cf3e 100644 --- a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/mps_file_example.c +++ b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/mps_file_example.c @@ -1,5 +1,5 @@ /* - * 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 */ /* @@ -36,32 +36,23 @@ const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: - return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: - return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: - return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: - return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: - return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: - return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: - return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: - return "Feasible found"; - default: - return "Unknown"; + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; + default: return "Unknown"; } } cuopt_int_t solve_mps_file(const char* filename) { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; cuopt_int_t status; cuopt_float_t time; cuopt_int_t termination_status; @@ -129,13 +120,15 @@ cuopt_int_t solve_mps_file(const char* filename) printf("\nResults:\n"); printf("--------\n"); printf("Number of variables: %d\n", num_variables); - printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status); + printf("Termination status: %s (%d)\n", + termination_status_to_string(termination_status), + termination_status); printf("Solve time: %f seconds\n", time); printf("Objective value: %f\n", objective_value); // Get and print solution variables solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t)); - status = cuOptGetPrimalSolution(solution, solution_values); + status = cuOptGetPrimalSolution(solution, solution_values); if (status != CUOPT_SUCCESS) { printf("Error getting solution values: %d\n", status); goto DONE; @@ -158,7 +151,8 @@ cuopt_int_t solve_mps_file(const char* filename) return status; } -int main(int argc, char* argv[]) { +int main(int argc, char* argv[]) +{ if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; diff --git a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_lp_example.c b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_lp_example.c index bd613af9b..419217b15 100644 --- a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_lp_example.c +++ b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_lp_example.c @@ -1,5 +1,5 @@ /* - * 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 */ /* @@ -37,24 +37,15 @@ const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: - return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: - return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: - return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: - return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: - return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: - return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: - return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: - return "Feasible found"; - default: - return "Unknown"; + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; + default: return "Unknown"; } } @@ -62,8 +53,8 @@ const char* termination_status_to_string(cuopt_int_t termination_status) cuopt_int_t test_simple_lp() { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; /* Solve the following LP: minimize -0.2*x1 + 0.1*x2 @@ -73,18 +64,18 @@ cuopt_int_t test_simple_lp() x1, x2 >= 0 */ - cuopt_int_t num_variables = 2; + cuopt_int_t num_variables = 2; cuopt_int_t num_constraints = 2; - cuopt_int_t nnz = 4; + cuopt_int_t nnz = 4; // CSR format constraint matrix // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr // From the constraints: // 3.0*x1 + 4.0*x2 <= 5.4 // 2.7*x1 + 10.1*x2 <= 4.9 - cuopt_int_t row_offsets[] = {0, 2, 4}; + cuopt_int_t row_offsets[] = {0, 2, 4}; cuopt_int_t column_indices[] = {0, 1, 0, 1}; - cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1}; + cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1}; // Objective coefficients // From the objective function: minimize -0.2*x1 + 0.1*x2 @@ -119,19 +110,19 @@ cuopt_int_t test_simple_lp() // Create the problem status = cuOptCreateRangedProblem(num_constraints, - num_variables, - CUOPT_MINIMIZE, - 0.0, // objective offset - objective_coefficients, - row_offsets, - column_indices, - values, - constraint_lower_bounds, - constraint_upper_bounds, - var_lower_bounds, - var_upper_bounds, - variable_types, - &problem); + num_variables, + CUOPT_MINIMIZE, + 0.0, // objective offset + objective_coefficients, + row_offsets, + column_indices, + values, + constraint_lower_bounds, + constraint_upper_bounds, + var_lower_bounds, + var_upper_bounds, + variable_types, + &problem); if (status != CUOPT_SUCCESS) { printf("Error creating problem: %d\n", status); goto DONE; @@ -180,7 +171,9 @@ cuopt_int_t test_simple_lp() // Print results printf("\nResults:\n"); printf("--------\n"); - printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status); + printf("Termination status: %s (%d)\n", + termination_status_to_string(termination_status), + termination_status); printf("Solve time: %f seconds\n", time); printf("Objective value: %f\n", objective_value); @@ -211,7 +204,8 @@ cuopt_int_t test_simple_lp() return status; } -int main() { +int main() +{ // Run the test cuopt_int_t status = test_simple_lp(); diff --git a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_milp_example.c b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_milp_example.c index 61dba362c..34d9c013e 100644 --- a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_milp_example.c +++ b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_milp_example.c @@ -1,5 +1,5 @@ /* - * 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 */ /* @@ -15,24 +15,15 @@ const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: - return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: - return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: - return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: - return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: - return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: - return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: - return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: - return "Feasible found"; - default: - return "Unknown"; + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; + default: return "Unknown"; } } @@ -40,8 +31,8 @@ const char* termination_status_to_string(cuopt_int_t termination_status) cuopt_int_t test_simple_milp() { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; /* Solve the following MILP: minimize -0.2*x1 + 0.1*x2 @@ -53,18 +44,18 @@ cuopt_int_t test_simple_milp() x2 is continuous */ - cuopt_int_t num_variables = 2; + cuopt_int_t num_variables = 2; cuopt_int_t num_constraints = 2; - cuopt_int_t nnz = 4; + cuopt_int_t nnz = 4; // CSR format constraint matrix // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr // From the constraints: // 3.0*x1 + 4.0*x2 <= 5.4 // 2.7*x1 + 10.1*x2 <= 4.9 - cuopt_int_t row_offsets[] = {0, 2, 4}; + cuopt_int_t row_offsets[] = {0, 2, 4}; cuopt_int_t column_indices[] = {0, 1, 0, 1}; - cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1}; + cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1}; // Objective coefficients // From the objective function: minimize -0.2*x1 + 0.1*x2 @@ -99,19 +90,19 @@ cuopt_int_t test_simple_milp() // Create the problem status = cuOptCreateRangedProblem(num_constraints, - num_variables, - CUOPT_MINIMIZE, - 0.0, // objective offset - objective_coefficients, - row_offsets, - column_indices, - values, - constraint_lower_bounds, - constraint_upper_bounds, - var_lower_bounds, - var_upper_bounds, - variable_types, - &problem); + num_variables, + CUOPT_MINIMIZE, + 0.0, // objective offset + objective_coefficients, + row_offsets, + column_indices, + values, + constraint_lower_bounds, + constraint_upper_bounds, + var_lower_bounds, + var_upper_bounds, + variable_types, + &problem); if (status != CUOPT_SUCCESS) { printf("Error creating problem: %d\n", status); goto DONE; @@ -160,7 +151,9 @@ cuopt_int_t test_simple_milp() // Print results printf("\nResults:\n"); printf("--------\n"); - printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status); + printf("Termination status: %s (%d)\n", + termination_status_to_string(termination_status), + termination_status); printf("Solve time: %f seconds\n", time); printf("Objective value: %f\n", objective_value); @@ -191,7 +184,8 @@ cuopt_int_t test_simple_milp() return status; } -int main() { +int main() +{ // Run the test cuopt_int_t status = test_simple_milp(); diff --git a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_qp_example.c b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_qp_example.c index c88890115..8610c2c41 100644 --- a/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_qp_example.c +++ b/docs/cuopt/source/cuopt-c/lp-qp-milp/examples/simple_qp_example.c @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights + * reserved. SPDX-License-Identifier: Apache-2.0 */ /* * Simple QP C API Example @@ -30,24 +30,15 @@ const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: - return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: - return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: - return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: - return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: - return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: - return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: - return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: - return "Feasible found"; - default: - return "Unknown"; + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; + default: return "Unknown"; } } @@ -55,8 +46,8 @@ const char* termination_status_to_string(cuopt_int_t termination_status) cuopt_int_t test_simple_qp() { cuOptOptimizationProblem problem = NULL; - cuOptSolverSettings settings = NULL; - cuOptSolution solution = NULL; + cuOptSolverSettings settings = NULL; + cuOptSolution solution = NULL; /* Solve the following QP: minimize x^2 + y^2 @@ -65,15 +56,15 @@ cuopt_int_t test_simple_qp() x, y >= 0 */ - cuopt_int_t num_variables = 2; + cuopt_int_t num_variables = 2; cuopt_int_t num_constraints = 1; - cuopt_int_t nnz = 2; + cuopt_int_t nnz = 2; // CSR format constraint matrix // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr - cuopt_int_t row_offsets[] = {0, 2}; + cuopt_int_t row_offsets[] = {0, 2}; cuopt_int_t column_indices[] = {0, 1}; - cuopt_float_t values[] = {1.0, 1.0}; + cuopt_float_t values[] = {1.0, 1.0}; // Objective coefficients // From the objective function: minimize x^2 + y^2 @@ -85,16 +76,15 @@ cuopt_int_t test_simple_qp() // From the objective function: minimize x^2 + y^2 // 1 is the coefficient of the quadratic term on x^2 // 1 is the coefficient of the quadratic term on y^2 - cuopt_float_t quadratic_objective_matrix_values[] = {1.0, 1.0}; - cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2}; + cuopt_float_t quadratic_objective_matrix_values[] = {1.0, 1.0}; + cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2}; cuopt_int_t quadratic_objective_matrix_column_indices[] = {0, 1}; // Constraint bounds // From the constraints: // x + y >= 1 cuopt_float_t constraint_rhs[] = {1.0}; - char constraint_sense[] = { CUOPT_GREATER_THAN }; - + char constraint_sense[] = {CUOPT_GREATER_THAN}; // Variable bounds // From the constraints: @@ -172,7 +162,9 @@ cuopt_int_t test_simple_qp() // Print results printf("\nResults:\n"); printf("--------\n"); - printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status); + printf("Termination status: %s (%d)\n", + termination_status_to_string(termination_status), + termination_status); printf("Solve time: %f seconds\n", time); printf("Objective value: %f\n", objective_value); @@ -203,7 +195,8 @@ cuopt_int_t test_simple_qp() return status; } -int main() { +int main() +{ // Run the test cuopt_int_t status = test_simple_qp(); diff --git a/docs/cuopt/source/cuopt-c/lp-qp-milp/lp-qp-milp-c-api.rst b/docs/cuopt/source/cuopt-c/lp-qp-milp/lp-qp-milp-c-api.rst index 43d15eca6..f8d884ec8 100644 --- a/docs/cuopt/source/cuopt-c/lp-qp-milp/lp-qp-milp-c-api.rst +++ b/docs/cuopt/source/cuopt-c/lp-qp-milp/lp-qp-milp-c-api.rst @@ -253,13 +253,13 @@ Termination Status Constants These constants define the termination status received from the :c:func:`cuOptGetTerminationStatus` function. .. LP/MIP termination status constants -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_NO_TERMINATION -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_OPTIMAL -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_INFEASIBLE -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_UNBOUNDED -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_TIME_LIMIT -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND -.. doxygendefine:: CUOPT_TERIMINATION_STATUS_CONCURRENT_LIMIT +.. doxygendefine:: CUOPT_TERMINATION_STATUS_NO_TERMINATION +.. doxygendefine:: CUOPT_TERMINATION_STATUS_OPTIMAL +.. doxygendefine:: CUOPT_TERMINATION_STATUS_INFEASIBLE +.. doxygendefine:: CUOPT_TERMINATION_STATUS_UNBOUNDED +.. doxygendefine:: CUOPT_TERMINATION_STATUS_ITERATION_LIMIT +.. doxygendefine:: CUOPT_TERMINATION_STATUS_TIME_LIMIT +.. doxygendefine:: CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR +.. doxygendefine:: CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE +.. doxygendefine:: CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND +.. doxygendefine:: CUOPT_TERMINATION_STATUS_CONCURRENT_LIMIT diff --git a/python/cuopt/cuopt/linear_programming/solution/solution.py b/python/cuopt/cuopt/linear_programming/solution/solution.py index 849c907d0..7983e2fa8 100644 --- a/python/cuopt/cuopt/linear_programming/solution/solution.py +++ b/python/cuopt/cuopt/linear_programming/solution/solution.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 from cuopt.linear_programming.solver.solver_wrapper import ( @@ -116,8 +116,8 @@ class Solution: Time used for pre-solve solve_time: Float64 Solve time in seconds - solved_by_pdlp: bool - Whether the problem was solved by PDLP or Dual Simplex + solved_by: int + Whether the problem was solved by Dual Simplex(1), PDLP(2) or Barrier(3) """ def __init__( @@ -154,7 +154,7 @@ def __init__( dual_objective=0.0, gap=0.0, nb_iterations=0, - solved_by_pdlp=None, + solved_by=None, mip_gap=0.0, solution_bound=0.0, presolve_time=0.0, @@ -193,7 +193,7 @@ def __init__( self.primal_objective = primal_objective self.dual_objective = dual_objective self.solve_time = solve_time - self.solved_by_pdlp = solved_by_pdlp + self.solved_by = solved_by self.vars = vars self.lp_stats = { "primal_residual": primal_residual, @@ -289,11 +289,11 @@ def get_solve_time(self): """ return self.solve_time - def get_solved_by_pdlp(self): + def get_solved_by(self): """ - Returns whether the problem was solved by PDLP or Dual Simplex + Returns whether the problem was solved by Dual Simplex(1), PDLP(2) or Barrier(3) """ - return self.solved_by_pdlp + return self.solved_by def get_vars(self): """ diff --git a/python/cuopt/cuopt/linear_programming/solver/solver.pxd b/python/cuopt/cuopt/linear_programming/solver/solver.pxd index 6688e5166..70dbf9fb1 100644 --- a/python/cuopt/cuopt/linear_programming/solver/solver.pxd +++ b/python/cuopt/cuopt/linear_programming/solver/solver.pxd @@ -153,7 +153,7 @@ cdef extern from "cuopt/linear_programming/utilities/cython_solve.hpp" namespace double gap_ int nb_iterations_ double solve_time_ - bool solved_by_pdlp_ + int solved_by_ cdef cppclass mip_ret_t: unique_ptr[device_buffer] solution_ diff --git a/python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx b/python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx index 8c1c8fdc3..2dd56c601 100644 --- a/python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx +++ b/python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx @@ -366,7 +366,7 @@ cdef create_solution(unique_ptr[solver_ret_t] sol_ret_ptr, gap = sol_ret.lp_ret.gap_ nb_iterations = sol_ret.lp_ret.nb_iterations_ solve_time = sol_ret.lp_ret.solve_time_ - solved_by_pdlp = sol_ret.lp_ret.solved_by_pdlp_ + solved_by = sol_ret.lp_ret.solved_by_ # In BatchSolve, we don't get the warm start data if not is_batch: @@ -469,7 +469,7 @@ cdef create_solution(unique_ptr[solver_ret_t] sol_ret_ptr, dual_objective, gap, nb_iterations, - solved_by_pdlp, + solved_by, ) return Solution( problem_category=ProblemCategory(sol_ret.problem_type), @@ -487,7 +487,7 @@ cdef create_solution(unique_ptr[solver_ret_t] sol_ret_ptr, dual_objective=dual_objective, gap=gap, nb_iterations=nb_iterations, - solved_by_pdlp=solved_by_pdlp, + solved_by=solved_by, ) diff --git a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py index 09f3c42f4..f53c9c620 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 import os @@ -75,7 +75,7 @@ def test_solver(): assert solution.get_primal_objective() == pytest.approx(0.0) assert solution.get_dual_objective() == pytest.approx(0.0) assert solution.get_lp_stats()["gap"] == pytest.approx(0.0) - assert solution.get_solved_by_pdlp() + assert solution.get_solved_by() == 2 # PDLP def test_parser_and_solver(): @@ -585,7 +585,7 @@ def test_dual_simplex(): assert solution.get_termination_status() == LPTerminationStatus.Optimal assert solution.get_primal_objective() == pytest.approx(-464.7531) - assert not solution.get_solved_by_pdlp() + assert solution.get_solved_by() == 1 # DualSimplex def test_barrier(): diff --git a/python/cuopt_self_hosted/cuopt_sh_client/cuopt_self_host_client.py b/python/cuopt_self_hosted/cuopt_sh_client/cuopt_self_host_client.py index 066e81b02..8a4156c59 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/cuopt_self_host_client.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/cuopt_self_host_client.py @@ -200,7 +200,7 @@ def create_solution_obj(solver_response): nb_iterations=sol["lp_statistics"]["nb_iterations"], primal_objective=sol["primal_objective"], dual_objective=sol["dual_objective"], - solved_by_pdlp=sol["solved_by_pdlp"], + solved_by=sol["solved_by"], ) return status, solution_obj diff --git a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solution.py b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solution.py index aa169abed..2d72a6e38 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solution.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solution.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 @@ -66,8 +66,8 @@ class ThinClientSolution: Time used for pre-solve solve_time: Float64 Solve time in seconds - solved_by_pdlp: bool - Whether the problem was solved by PDLP or Dual Simplex + solved_by: int + Whether the problem was solved by Dual Simplex(1), PDLP(2) or Barrier(3) """ def __init__( @@ -87,7 +87,7 @@ def __init__( dual_objective=0.0, gap=0.0, nb_iterations=0, - solved_by_pdlp=None, + solved_by=None, mip_gap=0.0, solution_bound=0.0, presolve_time=0.0, @@ -107,7 +107,7 @@ def __init__( self.primal_objective = primal_objective self.dual_objective = dual_objective self.solve_time = solve_time - self.solved_by_pdlp = solved_by_pdlp + self.solved_by = solved_by self.vars = vars self.lp_stats = { "primal_residual": primal_residual, @@ -191,11 +191,11 @@ def get_solve_time(self): """ return self.solve_time - def get_solved_by_pdlp(self): + def get_solved_by(self): """ - Returns whether the problem was solved by PDLP or Dual Simplex + Returns whether the problem was solved by Dual Simplex(1), PDLP(2) or Barrier(3) """ - return self.solved_by_pdlp + return self.solved_by def get_vars(self): """ diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py index 198b115d4..767b8bd83 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py @@ -695,7 +695,7 @@ class SolutionData(StrictModel): default=None, description=("Returns the engine solve time in seconds"), ) - solved_by_pdlp: bool = Field( + solved_by: bool = Field( default=None, description=( "Returns whether problem was solved by PDLP or Dual Simplex" diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py b/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py index 5b49e25d7..83d90946f 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py @@ -529,7 +529,7 @@ def create_solution(sol): sol.get_dual_objective ) solution["solver_time"] = sol.get_solve_time() - solution["solved_by_pdlp"] = sol.get_solved_by_pdlp() + solution["solved_by"] = sol.get_solved_by() solution["vars"] = sol.get_vars() solution["lp_statistics"] = {} if lp_stats is None else lp_stats solution["reduced_cost"] = reduced_cost