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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions cpp/include/cuopt/linear_programming/mip/solver_solution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <cuopt/linear_programming/constants.h>
#include <cuopt/error.hpp>
#include <cuopt/linear_programming/mip/solver_stats.hpp>
#include <cuopt/linear_programming/utilities/internals.hpp>

#include <rmm/cuda_stream_view.hpp>
Expand Down Expand Up @@ -48,18 +49,16 @@ class mip_solution_t : public base_solution_t {
std::vector<std::string> var_names,
f_t objective,
f_t mip_gap,
f_t solution_bound,
double total_solve_time,
double presolve_time,
mip_termination_status_t termination_status,
f_t max_constraint_violation,
f_t max_int_violation,
f_t max_variable_bound_violation,
i_t num_nodes,
i_t num_simplex_iterations,
solver_stats_t<i_t, f_t> stats,
std::vector<rmm::device_uvector<f_t>> solution_pool = {});

mip_solution_t(mip_termination_status_t termination_status, rmm::cuda_stream_view stream_view);
mip_solution_t(mip_termination_status_t termination_status,
solver_stats_t<i_t, f_t> stats,
rmm::cuda_stream_view stream_view);
mip_solution_t(const cuopt::logic_error& error_status, rmm::cuda_stream_view stream_view);

bool is_mip() const override { return true; }
Expand Down Expand Up @@ -88,16 +87,12 @@ class mip_solution_t : public base_solution_t {
std::vector<std::string> var_names_;
f_t objective_;
f_t mip_gap_;
f_t solution_bound_;
double total_solve_time_;
double presolve_time_;
mip_termination_status_t termination_status_;
cuopt::logic_error error_status_;
f_t max_constraint_violation_;
f_t max_int_violation_;
f_t max_variable_bound_violation_;
i_t num_nodes_;
i_t num_simplex_iterations_;
solver_stats_t<i_t, f_t> stats_;
std::vector<rmm::device_uvector<f_t>> solution_pool_;
};

Expand Down
2 changes: 1 addition & 1 deletion cpp/src/linear_programming/cuopt_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ cuopt_int_t cuOptGetSolveTime(cuOptSolution solution, cuopt_float_t* solve_time_
optimization_problem_solution_t<cuopt_int_t, cuopt_float_t>* optimization_problem_solution =
static_cast<optimization_problem_solution_t<cuopt_int_t, cuopt_float_t>*>(
solution_and_stream_view->lp_solution_ptr);
*solve_time_ptr = (optimization_problem_solution->get_solve_time() / 1000.0);
*solve_time_ptr = (optimization_problem_solution->get_solve_time());
}
return CUOPT_SUCCESS;
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mip/diversity/diversity_manager.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
#include "recombiners/recombiner_stats.hpp"

#include <cuopt/linear_programming/mip/solver_settings.hpp>
#include <cuopt/linear_programming/mip/solver_stats.hpp>

#include <mip/local_search/local_search.cuh>
#include <mip/solution/solution.cuh>
#include <mip/solver.cuh>
#include <mip/solver_stats.cuh>
#include <utilities/timer.hpp>

namespace cuopt::linear_programming::detail {
Expand Down
7 changes: 2 additions & 5 deletions cpp/src/mip/solution/solution.cu
Original file line number Diff line number Diff line change
Expand Up @@ -598,18 +598,15 @@ mip_solution_t<i_t, f_t> solution_t<i_t, f_t>::get_solution(bool output_feasible
problem_ptr->var_names,
h_user_obj,
rel_mip_gap,
solution_bound,
total_solve_time,
presolve_time,
term_reason,
max_constraint_violation,
max_int_violation,
max_variable_bound_violation,
num_nodes,
num_simplex_iterations);
stats);
} else {
return mip_solution_t<i_t, f_t>{is_problem_fully_reduced ? mip_termination_status_t::Infeasible
: mip_termination_status_t::TimeLimit,
stats,
handle_ptr->get_stream()};
}
}
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mip/solution/solution.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@

#include <cuopt/linear_programming/mip/solver_settings.hpp>
#include <cuopt/linear_programming/mip/solver_solution.hpp>
#include <cuopt/linear_programming/mip/solver_stats.hpp>
#include <mip/diversity/weights.cuh>
#include <mip/problem/problem.cuh>
#include <mip/relaxed_lp/lp_state.cuh>
#include <mip/solver_stats.cuh>

#include <raft/util/cuda_dev_essentials.cuh>
#include <rmm/device_scalar.hpp>
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mip/solver.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
*/

#include <cuopt/linear_programming/mip/solver_settings.hpp>
#include <cuopt/linear_programming/mip/solver_stats.hpp>
#include <cuopt/linear_programming/pdlp/solver_solution.hpp>
#include <mip/problem/problem.cuh>
#include <mip/solver_context.cuh>
#include <mip/solver_stats.cuh>
#include <utilities/timer.hpp>
#pragma once

Expand Down
3 changes: 2 additions & 1 deletion cpp/src/mip/solver_context.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
* limitations under the License.
*/

#include <cuopt/linear_programming/mip/solver_stats.hpp>

#include <linear_programming/initial_scaling_strategy/initial_scaling.cuh>
#include <mip/problem/problem.cuh>
#include <mip/relaxed_lp/lp_state.cuh>
#include <mip/solver_stats.cuh>

#pragma once

Expand Down
32 changes: 9 additions & 23 deletions cpp/src/mip/solver_solution.cu
Original file line number Diff line number Diff line change
Expand Up @@ -32,49 +32,38 @@ mip_solution_t<i_t, f_t>::mip_solution_t(rmm::device_uvector<f_t> solution,
std::vector<std::string> var_names,
f_t objective,
f_t mip_gap,
f_t solution_bound,
double total_solve_time,
double presolve_time,
mip_termination_status_t termination_status,
f_t max_constraint_violation,
f_t max_int_violation,
f_t max_variable_bound_violation,
i_t num_nodes,
i_t num_simplex_iterations,
solver_stats_t<i_t, f_t> stats,
std::vector<rmm::device_uvector<f_t>> solution_pool)
: solution_(std::move(solution)),
var_names_(std::move(var_names)),
objective_(objective),
mip_gap_(mip_gap),
solution_bound_(solution_bound),
total_solve_time_(total_solve_time),
presolve_time_(presolve_time),
termination_status_(termination_status),
max_constraint_violation_(max_constraint_violation),
max_int_violation_(max_int_violation),
max_variable_bound_violation_(max_variable_bound_violation),
num_nodes_(num_nodes),
num_simplex_iterations_(num_simplex_iterations),
stats_(stats),
solution_pool_(std::move(solution_pool)),
error_status_(cuopt::logic_error("", cuopt::error_type_t::Success))
{
}

template <typename i_t, typename f_t>
mip_solution_t<i_t, f_t>::mip_solution_t(mip_termination_status_t termination_status,
solver_stats_t<i_t, f_t> stats,
rmm::cuda_stream_view stream_view)
: solution_(0, stream_view),
objective_(0),
mip_gap_(0),
solution_bound_(0),
total_solve_time_(0),
presolve_time_(0),
termination_status_(termination_status),
max_constraint_violation_(0),
max_int_violation_(0),
max_variable_bound_violation_(0),
num_nodes_(0),
num_simplex_iterations_(0),
stats_(stats),
error_status_(cuopt::logic_error("", cuopt::error_type_t::Success))
{
}
Expand All @@ -85,9 +74,6 @@ mip_solution_t<i_t, f_t>::mip_solution_t(const cuopt::logic_error& error_status,
: solution_(0, stream_view),
objective_(0),
mip_gap_(0),
solution_bound_(0),
total_solve_time_(0),
presolve_time_(0),
termination_status_(mip_termination_status_t::NoTermination),
max_constraint_violation_(0),
max_int_violation_(0),
Expand Down Expand Up @@ -129,19 +115,19 @@ f_t mip_solution_t<i_t, f_t>::get_mip_gap() const
template <typename i_t, typename f_t>
f_t mip_solution_t<i_t, f_t>::get_solution_bound() const
{
return solution_bound_;
return stats_.solution_bound;
}

template <typename i_t, typename f_t>
double mip_solution_t<i_t, f_t>::get_total_solve_time() const
{
return total_solve_time_;
return stats_.total_solve_time;
}

template <typename i_t, typename f_t>
double mip_solution_t<i_t, f_t>::get_presolve_time() const
{
return presolve_time_;
return stats_.presolve_time;
}

template <typename i_t, typename f_t>
Expand Down Expand Up @@ -194,13 +180,13 @@ f_t mip_solution_t<i_t, f_t>::get_max_variable_bound_violation() const
template <typename i_t, typename f_t>
i_t mip_solution_t<i_t, f_t>::get_num_nodes() const
{
return num_nodes_;
return stats_.num_nodes;
}

template <typename i_t, typename f_t>
i_t mip_solution_t<i_t, f_t>::get_num_simplex_iterations() const
{
return num_simplex_iterations_;
return stats_.num_simplex_iterations;
}

template <typename i_t, typename f_t>
Expand Down
5 changes: 3 additions & 2 deletions cpp/tests/linear_programming/c_api_tests/c_api_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ cuopt_int_t burglar_problem()
return status;
}

int solve_mps_file(const char* filename, double time_limit, double iteration_limit, int* termination_status_ptr)
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;
Expand All @@ -313,7 +313,7 @@ int solve_mps_file(const char* filename, double time_limit, double iteration_lim
printf("Error creating solver settings\n");
goto DONE;
}
status = cuOptSetIntegerParameter(settings, CUOPT_METHOD, CUOPT_METHOD_DUAL_SIMPLEX);
status = cuOptSetIntegerParameter(settings, CUOPT_METHOD, method);
if (status != CUOPT_SUCCESS) {
printf("Error setting method\n");
goto DONE;
Expand Down Expand Up @@ -345,6 +345,7 @@ int solve_mps_file(const char* filename, double time_limit, double iteration_lim
goto DONE;
}
status = cuOptGetSolveTime(solution, &time);
if (solve_time_ptr) *solve_time_ptr = time;
if (status != CUOPT_SUCCESS) {
printf("Error getting solve time\n");
goto DONE;
Expand Down
28 changes: 25 additions & 3 deletions cpp/tests/linear_programming/c_api_tests/c_api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,37 @@ TEST(c_api, afiro)
EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_OPTIMAL);
}

TEST(c_api, time_limit)
// Test both LP and MIP codepaths
class TimeLimitTestFixture : public ::testing::TestWithParam<std::tuple<std::string, double, int>> {
};
TEST_P(TimeLimitTestFixture, time_limit)
{
const std::string& rapidsDatasetRootDir = cuopt::test::get_rapids_dataset_root_dir();
std::string filename = rapidsDatasetRootDir + "/linear_programming/" + "afiro_original.mps";
std::string filename = rapidsDatasetRootDir + std::get<0>(GetParam());
double target_solve_time = std::get<1>(GetParam());
int method = std::get<2>(GetParam());
int termination_status;
EXPECT_EQ(solve_mps_file(filename.c_str(), 1e-6, CUOPT_INFINITY, &termination_status),
double solve_time = std::numeric_limits<double>::quiet_NaN();
EXPECT_EQ(solve_mps_file(filename.c_str(),
target_solve_time,
CUOPT_INFINITY,
&termination_status,
&solve_time,
method),
CUOPT_SUCCESS);
EXPECT_EQ(termination_status, CUOPT_TERIMINATION_STATUS_TIME_LIMIT);
EXPECT_NEAR(solve_time, target_solve_time, 0.1);
}
INSTANTIATE_TEST_SUITE_P(
c_api,
TimeLimitTestFixture,
::testing::Values(
std::make_tuple("/linear_programming/square41/square41.mps",
5,
CUOPT_METHOD_DUAL_SIMPLEX), // LP, Dual Simplex
std::make_tuple("/linear_programming/square41/square41.mps", 5, CUOPT_METHOD_PDLP), // LP, PDLP
std::make_tuple("/mip/enlight_hard.mps", 5, CUOPT_METHOD_DUAL_SIMPLEX) // MIP
));

TEST(c_api, iteration_limit)
{
Expand Down
9 changes: 8 additions & 1 deletion cpp/tests/linear_programming/c_api_tests/c_api_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ cuopt_int_t burglar_problem();
cuopt_int_t solve_mps_file(const char* filename,
double time_limit,
double iteration_limit,
cuopt_int_t* termination_status);
cuopt_int_t* termination_status,
#ifdef __cplusplus
cuopt_float_t* solve_time = 0,
cuopt_int_t method = CUOPT_METHOD_DUAL_SIMPLEX);
#else
cuopt_float_t* solve_time,
cuopt_int_t method);
#endif
cuopt_int_t test_missing_file();
cuopt_int_t test_infeasible_problem();
cuopt_int_t test_bad_parameter_name();
Expand Down
2 changes: 1 addition & 1 deletion cpp/tests/mip/bounds_standardization_test.cu
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
#include "mip_utils.cuh"

#include <cuopt/linear_programming/mip/solver_settings.hpp>
#include <cuopt/linear_programming/mip/solver_stats.hpp>
#include <linear_programming/pdlp.cuh>
#include <linear_programming/utilities/problem_checking.cuh>
#include <mip/presolve/trivial_presolve.cuh>
#include <mip/relaxed_lp/relaxed_lp.cuh>
#include <mip/solver_stats.cuh>
#include <mps_parser/parser.hpp>
#include <utilities/common_utils.hpp>
#include <utilities/error.hpp>
Expand Down
1 change: 1 addition & 0 deletions datasets/mip/download_miplib_test_dataset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ INSTANCES=(
"stein9inf"
"neos5"
"swath1"
"enlight_hard"
)

BASE_URL="https://miplib.zib.de/WebData/instances"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def test_time_limit_solver():
solution = solver.Solve(data_model_obj, settings)
assert solution.get_termination_status() == LPTerminationStatus.TimeLimit
# Check that around 200 ms has passed with some tolerance
assert solution.get_solve_time() <= (time_limit_seconds * 10) * 1000
assert solution.get_solve_time() <= (time_limit_seconds * 10)
# Not all 0
assert solution.get_primal_objective() != 0.0
assert np.any(solution.get_primal_solution())
Expand Down
Loading