Skip to content

Commit e6dd7fd

Browse files
TolisChalApostolos Chalkis
and
Apostolos Chalkis
authored
Implement rounding method using the volumetric barrier (#313)
* generalize rounding loop * support sparse cholesky operator * complete sparse support in max_inscribed_ball * complete sparse support in preprocesing * add sparse tests * change main rounding function name * improve explaining comments * resolve PR comments * changing the dates in copyrights * use if constexpr instead of SNIFAE * update the examples to cpp17 * update to cpp17 order polytope example * fix templating in mat_computational_operators * fix templating errors and change header file to mat_computational_operators * first implementation of the volumetric barrier ellipsoid * add criterion for step_iter * restructure code that computes barriers' centers * remove unused comments * resolve PR comments * remove NT typename from max_step() --------- Co-authored-by: Apostolos Chalkis <[email protected]>
1 parent f1abc36 commit e6dd7fd

9 files changed

+307
-155
lines changed

include/preprocess/analytic_center_linear_ineq.h

Lines changed: 0 additions & 134 deletions
This file was deleted.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// VolEsti (volume computation and sampling library)
2+
3+
// Copyright (c) 2024 Vissarion Fisikopoulos
4+
// Copyright (c) 2024 Apostolos Chalkis
5+
// Copyright (c) 2024 Elias Tsigaridas
6+
7+
// Licensed under GNU LGPL.3, see LICENCE file
8+
9+
10+
#ifndef BARRIER_CENTER_ELLIPSOID_HPP
11+
#define BARRIER_CENTER_ELLIPSOID_HPP
12+
13+
#include <tuple>
14+
15+
#include "preprocess/max_inscribed_ball.hpp"
16+
#include "preprocess/feasible_point.hpp"
17+
#include "preprocess/rounding_util_functions.hpp"
18+
19+
/*
20+
This implementation computes the analytic or the volumetric center of a polytope given
21+
as a set of linear inequalities P = {x | Ax <= b}. The analytic center is the tminimizer
22+
of the log barrier function, i.e., the optimal solution
23+
of the following optimization problem (Convex Optimization, Boyd and Vandenberghe, Section 8.5.3),
24+
25+
\min -\sum \log(b_i - a_i^Tx), where a_i is the i-th row of A.
26+
27+
The volumetric center is the minimizer of the volumetric barrier function, i.e., the optimal
28+
solution of the following optimization problem,
29+
30+
\min logdet \nabla^2 f(x), where f(x) the log barrier function
31+
32+
The function solves the problems by using the Newton method.
33+
34+
Input: (i) Matrix A, vector b such that the polytope P = {x | Ax<=b}
35+
(ii) The number of maximum iterations, max_iters
36+
(iii) Tolerance parameter grad_err_tol to bound the L2-norm of the gradient
37+
(iv) Tolerance parameter rel_pos_err_tol to check the relative progress in each iteration
38+
39+
Output: (i) The Hessian of the barrier function
40+
(ii) The analytic/volumetric center of the polytope
41+
(iii) A boolean variable that declares convergence
42+
43+
Note: Using MT as to deal with both dense and sparse matrices, MT_dense will be the type of result matrix
44+
*/
45+
template <typename MT_dense, int BarrierType, typename NT, typename MT, typename VT>
46+
std::tuple<MT_dense, VT, bool> barrier_center_ellipsoid_linear_ineq(MT const& A, VT const& b, VT const& x0,
47+
unsigned int const max_iters = 500,
48+
NT const grad_err_tol = 1e-08,
49+
NT const rel_pos_err_tol = 1e-12)
50+
{
51+
// Initialization
52+
VT x = x0;
53+
VT Ax = A * x;
54+
const int n = A.cols(), m = A.rows();
55+
MT H(n, n), A_trans = A.transpose();
56+
VT grad(n), d(n), Ad(m), b_Ax(m), step_d(n), x_prev;
57+
NT grad_err, rel_pos_err, rel_pos_err_temp, step, obj_val, obj_val_prev;
58+
unsigned int iter = 0;
59+
bool converged = false;
60+
const NT tol_bnd = NT(0.01), tol_obj = NT(1e-06);
61+
62+
auto [step_iter, max_step_multiplier] = init_step<BarrierType, NT>();
63+
auto llt = initialize_chol<NT>(A_trans, A);
64+
get_barrier_hessian_grad<MT_dense, BarrierType>(A, A_trans, b, x, Ax, llt,
65+
H, grad, b_Ax, obj_val);
66+
do {
67+
iter++;
68+
// Compute the direction
69+
d.noalias() = - solve_vec<NT>(llt, H, grad);
70+
Ad.noalias() = A * d;
71+
// Compute the step length
72+
step = std::min(max_step_multiplier * get_max_step(Ad, b_Ax), step_iter);
73+
step_d.noalias() = step*d;
74+
x_prev = x;
75+
x += step_d;
76+
Ax.noalias() += step*Ad;
77+
78+
// Compute the max_i\{ |step*d_i| ./ |x_i| \}
79+
rel_pos_err = std::numeric_limits<NT>::lowest();
80+
for (int i = 0; i < n; i++)
81+
{
82+
rel_pos_err_temp = std::abs(step_d.coeff(i) / x_prev.coeff(i));
83+
if (rel_pos_err_temp > rel_pos_err)
84+
{
85+
rel_pos_err = rel_pos_err_temp;
86+
}
87+
}
88+
89+
obj_val_prev = obj_val;
90+
get_barrier_hessian_grad<MT_dense, BarrierType>(A, A_trans, b, x, Ax, llt,
91+
H, grad, b_Ax, obj_val);
92+
grad_err = grad.norm();
93+
94+
if (iter >= max_iters || grad_err <= grad_err_tol || rel_pos_err <= rel_pos_err_tol)
95+
{
96+
converged = true;
97+
break;
98+
}
99+
get_step_next_iteration<BarrierType>(obj_val_prev, obj_val, tol_obj, step_iter);
100+
} while (true);
101+
102+
return std::make_tuple(MT_dense(H), x, converged);
103+
}
104+
105+
template <typename MT_dense, int BarrierType, typename NT, typename MT, typename VT>
106+
std::tuple<MT_dense, VT, bool> barrier_center_ellipsoid_linear_ineq(MT const& A, VT const& b,
107+
unsigned int const max_iters = 500,
108+
NT const grad_err_tol = 1e-08,
109+
NT const rel_pos_err_tol = 1e-12)
110+
{
111+
VT x0 = compute_feasible_point(A, b);
112+
return barrier_center_ellipsoid_linear_ineq<MT_dense, BarrierType>(A, b, x0, max_iters, grad_err_tol, rel_pos_err_tol);
113+
}
114+
115+
#endif // BARRIER_CENTER_ELLIPSOID_HPP

include/preprocess/inscribed_ellipsoid_rounding.hpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,9 @@
1212
#define INSCRIBED_ELLIPSOID_ROUNDING_HPP
1313

1414
#include "preprocess/max_inscribed_ellipsoid.hpp"
15-
#include "preprocess/analytic_center_linear_ineq.h"
15+
#include "preprocess/barrier_center_ellipsoid.hpp"
1616
#include "preprocess/feasible_point.hpp"
1717

18-
enum EllipsoidType
19-
{
20-
MAX_ELLIPSOID = 1,
21-
LOG_BARRIER = 2
22-
};
2318

2419
template<typename MT, int ellipsoid_type, typename Custom_MT, typename VT, typename NT>
2520
inline static std::tuple<MT, VT, NT>
@@ -30,9 +25,10 @@ compute_inscribed_ellipsoid(Custom_MT A, VT b, VT const& x0,
3025
if constexpr (ellipsoid_type == EllipsoidType::MAX_ELLIPSOID)
3126
{
3227
return max_inscribed_ellipsoid<MT>(A, b, x0, maxiter, tol, reg);
33-
} else if constexpr (ellipsoid_type == EllipsoidType::LOG_BARRIER)
28+
} else if constexpr (ellipsoid_type == EllipsoidType::LOG_BARRIER ||
29+
ellipsoid_type == EllipsoidType::VOLUMETRIC_BARRIER)
3430
{
35-
return analytic_center_linear_ineq<MT, Custom_MT, VT, NT>(A, b, x0);
31+
return barrier_center_ellipsoid_linear_ineq<MT, ellipsoid_type, NT>(A, b, x0);
3632
} else
3733
{
3834
std::runtime_error("Unknown rounding method.");

include/preprocess/max_inscribed_ball.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#ifndef MAX_INSCRIBED_BALL_HPP
1212
#define MAX_INSCRIBED_BALL_HPP
1313

14-
#include "preprocess/mat_computational_operators.h"
14+
#include "preprocess/rounding_util_functions.hpp"
1515

1616
/*
1717
This implmentation computes the largest inscribed ball in a given convex polytope P.

include/preprocess/max_inscribed_ellipsoid.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
#include <utility>
1717
#include <Eigen/Eigen>
18-
#include "preprocess/mat_computational_operators.h"
18+
#include "preprocess/rounding_util_functions.hpp"
1919

2020

2121
/*

0 commit comments

Comments
 (0)