-
Notifications
You must be signed in to change notification settings - Fork 222
Add more strategies of init point computation in barrier #1577
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
base: main
Are you sure you want to change the base?
Changes from all commits
278d02a
8e29f92
d39ddef
8489cd4
d6b9166
4f5e8fd
ba78c89
ffc457c
225421f
a5af18e
40789ae
e2d0e59
a65e20a
864257c
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 |
|---|---|---|
|
|
@@ -97,6 +97,34 @@ bool validate_barrier_cone_layout(const lp_problem_t<i_t, f_t>& problem, | |
| return true; | ||
| } | ||
|
|
||
| // Push entries into interior of nonnegative orthant and SOC. | ||
|
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. SOC -> second-order cone |
||
| template <typename i_t, typename f_t> | ||
| static void ensure_initial_point_interior(dense_vector_t<i_t, f_t>& values, | ||
| f_t epsilon_adjust, | ||
| const std::vector<i_t>& linear_mask, | ||
| i_t linear_end, | ||
| const std::vector<i_t>& cone_dims) | ||
| { | ||
| // Linear shift | ||
| std::vector<i_t> linear_only_mask(values.size(), 0); | ||
| std::copy(linear_mask.begin(), linear_mask.begin() + linear_end, linear_only_mask.begin()); | ||
| values.ensure_positive(epsilon_adjust, linear_only_mask); | ||
|
|
||
| // Cone shift | ||
| i_t off = 0; | ||
|
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. off -> offset |
||
| for (i_t q_k : cone_dims) { | ||
| const i_t base = linear_end + off; | ||
| f_t tail_sq = 0.0; | ||
| for (i_t j = 1; j < q_k; ++j) { | ||
| const f_t t = values[base + j]; | ||
| tail_sq += t * t; | ||
| } | ||
| const f_t tail_norm = std::sqrt(tail_sq); | ||
| if (values[base] <= tail_norm + epsilon_adjust) { values[base] = tail_norm + epsilon_adjust; } | ||
| off += q_k; | ||
| } | ||
| } | ||
|
|
||
| // -1 automatic: enable for cones, disable otherwise; 0 off; 1 on | ||
| template <typename i_t, typename f_t> | ||
| bool should_use_adaptive_regularization(const simplex_solver_settings_t<i_t, f_t>& settings, | ||
|
|
@@ -2182,41 +2210,54 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data) | |
| const bool use_augmented = data.use_augmented; | ||
| const bool has_direct_free_linear = data.n_direct_free_linear > 0; | ||
|
|
||
| // SOCP: data-dependent initial point following SeDuMi (Sturm, 1999). | ||
| // mu = sqrt((1 + ||b||_inf) * (1 + ||c||_inf)) | ||
| // primal and dual: x = mu * e_K, z = mu * e_K | ||
| const barrier_dual_initial_point_t input_strategy = settings.barrier_dual_initial_point; | ||
|
|
||
| const barrier_dual_initial_point_t init_strategy = | ||
| (data.has_cones() && input_strategy == barrier_dual_initial_point_t::Automatic) | ||
| ? barrier_dual_initial_point_t::SedumiMu | ||
| : input_strategy; | ||
|
|
||
| // SedumiMu: Sturm/SeDuMi-style mu-based primal+dual initial point. | ||
| // mu = sqrt((1 + ||b||_inf) * (1 + ||c||_inf)); x = z = mu * e_K. | ||
| // where e_K is the identity of the symmetric cone: | ||
| // LP block: e = 1, SOC block: e = (sqrt(2), 0, ..., 0) | ||
| if (data.has_cones()) { | ||
| const i_t cs = data.cone_start(); | ||
| const f_t norm_b = vector_norm_inf<i_t, f_t>(lp.rhs); | ||
| const f_t norm_c = vector_norm_inf<i_t, f_t>(lp.objective); | ||
| const f_t mu = std::sqrt((1.0 + norm_b) * (1.0 + norm_c)); | ||
| const f_t sqrt2 = std::sqrt(2.0); | ||
| const f_t x_soc = mu * sqrt2; | ||
| const f_t z_soc = mu * sqrt2; | ||
| // Linear orthant | ||
| for (i_t j = 0; j < cs; ++j) { | ||
| // Full primal+dual point; no factorization/solve (main loop factorizes later). | ||
| if (init_strategy == barrier_dual_initial_point_t::SedumiMu) { | ||
| const f_t norm_b = vector_norm_inf<i_t, f_t>(lp.rhs); | ||
| const f_t norm_c = vector_norm_inf<i_t, f_t>(lp.objective); | ||
| const f_t mu = std::sqrt((1.0 + norm_b) * (1.0 + norm_c)); | ||
| const f_t sqrt2 = std::sqrt(2.0); | ||
| const i_t linear_end = data.linear_xz_size(lp.num_cols); | ||
|
|
||
| // Linear orthant: x = z = mu * e, with e = 1 | ||
| for (i_t j = 0; j < linear_end; ++j) { | ||
| data.x[j] = mu; | ||
| data.z[j] = mu; | ||
| } | ||
| if (has_direct_free_linear) { | ||
| for (i_t j : presolve_info.direct_free_variables) { | ||
| if (j < cs) { data.z[j] = 0.0; } | ||
| if (j < linear_end) { data.z[j] = 0.0; } | ||
| } | ||
| } | ||
| // SOC blocks | ||
| i_t off = 0; | ||
| for (size_t k = 0; k < lp.second_order_cone_dims.size(); k++) { | ||
| i_t q_k = lp.second_order_cone_dims[k]; | ||
| data.x[cs + off] = x_soc; | ||
| data.z[cs + off] = z_soc; | ||
| for (i_t j = 1; j < q_k; ++j) { | ||
| data.x[cs + off + j] = 0.0; | ||
| data.z[cs + off + j] = 0.0; | ||
|
|
||
| // SOC blocks: x = z = mu * e, with e = (sqrt(2), 0, ..., 0) | ||
|
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. SOC -> second-order cone |
||
| if (data.has_cones()) { | ||
| const i_t cs = data.cone_start(); | ||
|
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. cs -> cone_start |
||
| const f_t x_soc = mu * sqrt2; | ||
| const f_t z_soc = mu * sqrt2; | ||
| i_t off = 0; | ||
|
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. off -> offset |
||
| for (size_t k = 0; k < lp.second_order_cone_dims.size(); k++) { | ||
| i_t q_k = lp.second_order_cone_dims[k]; | ||
| data.x[cs + off] = x_soc; | ||
| data.z[cs + off] = z_soc; | ||
| for (i_t j = 1; j < q_k; ++j) { | ||
| data.x[cs + off + j] = 0.0; | ||
| data.z[cs + off + j] = 0.0; | ||
| } | ||
| off += q_k; | ||
| } | ||
| off += q_k; | ||
| } | ||
|
|
||
| data.y.set_scalar(0.0); | ||
| if (data.n_upper_bounds > 0) { | ||
| data.w.set_scalar(mu); | ||
|
|
@@ -2359,9 +2400,18 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data) | |
| #endif | ||
| } | ||
|
|
||
| float64_t epsilon_adjust = 10.0; | ||
| const f_t epsilon_adjust = settings.barrier_initial_point_safeguard; | ||
| // Push entries into interior of nonnegative orthant and SOC. | ||
|
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. SOC -> second-order cone |
||
| const bool has_soc = data.has_cones(); | ||
| const i_t linear_end = has_soc ? data.cone_start() : lp.num_cols; | ||
| auto ensure_interior = [&](dense_vector_t<i_t, f_t>& values, | ||
|
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. Please don't create a lambda for this. Just call |
||
| const std::vector<i_t>& linear_mask) { | ||
| ensure_initial_point_interior( | ||
| values, epsilon_adjust, linear_mask, linear_end, lp.second_order_cone_dims); | ||
| }; | ||
|
|
||
| if (settings.barrier_dual_initial_point == -1 || settings.barrier_dual_initial_point == 0) { | ||
| if (init_strategy == barrier_dual_initial_point_t::Automatic || | ||
| init_strategy == barrier_dual_initial_point_t::LustigMarstenShanno) { | ||
| // Use the dual starting point suggested by the paper | ||
| // On Implementing Mehrotra’s Predictor–Corrector Interior-Point Method for Linear Programming | ||
| // Irvin J. Lustig, Roy E. Marsten, and David F. Shanno | ||
|
|
@@ -2430,7 +2480,6 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data) | |
| data.v.multiply_scalar(-1.0); | ||
|
|
||
| data.v.ensure_positive(epsilon_adjust); | ||
| data.z.ensure_positive(epsilon_adjust, nonnegative_z); | ||
| } else { | ||
| // First compute rhs = A*Dinv*c | ||
| dense_vector_t<i_t, f_t> rhs(lp.num_rows); | ||
|
|
@@ -2454,7 +2503,6 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data) | |
| data.gather_upper_bounds(data.z, data.v); | ||
| data.v.multiply_scalar(-1.0); | ||
| data.v.ensure_positive(epsilon_adjust); | ||
| data.z.ensure_positive(epsilon_adjust, nonnegative_z); | ||
| } | ||
|
|
||
| // Verify A'*y + z - E*v - Q*x = c | ||
|
|
@@ -2472,6 +2520,7 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data) | |
| settings.log.printf("||A^T y + z - E*v - Q*x - c ||: %e\n", | ||
| vector_norm2<i_t, f_t>(init_dual_residual)); | ||
| #endif | ||
|
|
||
| // Make sure (w, x, v, z) > 0. Skip free variables being handled directly. | ||
| data.w.ensure_positive(epsilon_adjust); | ||
| std::vector<i_t> nonnegative_variables(data.x.size(), 1); | ||
|
|
@@ -2480,7 +2529,8 @@ int barrier_solver_t<i_t, f_t>::initial_point(iteration_data_t<i_t, f_t>& data) | |
| nonnegative_variables[j] = 0; | ||
| } | ||
| } | ||
| data.x.ensure_positive(epsilon_adjust, nonnegative_variables); | ||
| ensure_interior(data.z, nonnegative_z); | ||
| ensure_interior(data.x, nonnegative_variables); | ||
| // Direct free variables: reduced cost z = 0 (no complementarity condition). | ||
| if (has_direct_free_linear) { | ||
| for (i_t j : presolve_info.direct_free_variables) { | ||
|
|
||
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 think this comment applies to another parameter.
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.
Oh whoops. This is for the safeguard not the dual initial point. My mistake. Please ignore.