-
Notifications
You must be signed in to change notification settings - Fork 113
Fix non-trivial presolve not reporting Optimality #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4229b8e
90fdab6
3b2a537
f60fe00
8fc1969
c4b09a0
603788b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,8 +96,9 @@ solution_t<i_t, f_t> mip_solver_t<i_t, f_t>::run_solver() | |
| "preprocess_problem should be called before running the solver"); | ||
|
|
||
| if (context.problem_ptr->empty) { | ||
| CUOPT_LOG_INFO("Problem fully reduced at trivial presolve"); | ||
| CUOPT_LOG_INFO("Problem fully reduced in presolve"); | ||
| solution_t<i_t, f_t> sol(*context.problem_ptr); | ||
| sol.set_problem_fully_reduced(); | ||
| context.problem_ptr->post_process_solution(sol); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dumb question: is this where the solution is populated? Where does presolve store the information about the solution when the problem is fully reduced in presolve?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the case of fully presolved problems the solution is populated by post_process_solution() (which tracks the transformations made by presolve) and additional solving stats information is added when |
||
| return sol; | ||
| } | ||
|
|
@@ -106,15 +107,16 @@ solution_t<i_t, f_t> mip_solver_t<i_t, f_t>::run_solver() | |
| dm.timer = timer_; | ||
| bool presolve_success = dm.run_presolve(timer_.remaining_time()); | ||
| if (!presolve_success) { | ||
| CUOPT_LOG_INFO("Presolve is infeasible, returning infeasible solution!"); | ||
| CUOPT_LOG_INFO("Problem proven infeasible in presolve"); | ||
| solution_t<i_t, f_t> sol(*context.problem_ptr); | ||
| sol.set_problem_infeasible(); | ||
| sol.set_problem_fully_reduced(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we decide to keep infeasible, here it makes more sense to keep set_problem_infeasible |
||
| context.problem_ptr->post_process_solution(sol); | ||
| return sol; | ||
| } | ||
| if (context.problem_ptr->empty) { | ||
| CUOPT_LOG_INFO("Problem fully reduced at presolve"); | ||
| CUOPT_LOG_INFO("Problem full reduced in presolve"); | ||
| solution_t<i_t, f_t> sol(*context.problem_ptr); | ||
| sol.set_problem_fully_reduced(); | ||
| context.problem_ptr->post_process_solution(sol); | ||
| return sol; | ||
| } | ||
|
|
@@ -182,7 +184,7 @@ solution_t<i_t, f_t> mip_solver_t<i_t, f_t>::run_solver() | |
| context.stats.solution_bound = | ||
| context.problem_ptr->get_user_obj_from_solver_obj(branch_and_bound_solution.lower_bound); | ||
| } | ||
| if (bb_status == dual_simplex::mip_status_t::INFEASIBLE) { sol.set_problem_infeasible(); } | ||
| if (bb_status == dual_simplex::mip_status_t::INFEASIBLE) { sol.set_problem_fully_reduced(); } | ||
| context.stats.num_nodes = branch_and_bound_solution.nodes_explored; | ||
| context.stats.num_simplex_iterations = branch_and_bound_solution.simplex_iterations; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we remove the infeasible options? The problem can be infeasible right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to cover both the case of infeasibility and optimality after presolve with
set_problem_fully_reduced.get_solution()then determines, based on the status of the solution after post_process, which status to return (Optimal or Infeasible)This ended up making the code more concise so that's why I went with this :)
https://github.com/NVIDIA/cuopt/pull/26/files#diff-115aa63d798001b25f7e001080d8ff9136923b2509328d8ccd079131e4dbc2b8L589-R613