@@ -38,7 +38,8 @@ void get_hessian_grad_logbarrier(MT const& A, MT const& A_trans, VT const& b,
38
38
39
39
b_Ax.noalias () = b - Ax;
40
40
NT *s_data = s.data ();
41
- for (int i = 0 ; i < m; i++) {
41
+ for (int i = 0 ; i < m; i++)
42
+ {
42
43
*s_data = NT (1 ) / b_Ax.coeff (i);
43
44
s_data++;
44
45
}
@@ -53,9 +54,12 @@ void get_hessian_grad_logbarrier(MT const& A, MT const& A_trans, VT const& b,
53
54
/*
54
55
This implementation computes the analytic center of a polytope given
55
56
as a set of linear inequalities P = {x | Ax <= b}. The analytic center
56
- is the optimal solution of the following optimization problem,
57
- \min - \sum \log(b_i - a_i^Tx), where a_i is the i-th row of A.
58
- The function implements the Newton method.
57
+ is the minimizer of the log barrier function i.e., the optimal solution
58
+ of the following optimization problem (Convex Optimization, Boyd and Vandenberghe, Section 8.5.3),
59
+
60
+ \min -\sum \log(b_i - a_i^Tx), where a_i is the i-th row of A.
61
+
62
+ The function solves the problem by using the Newton method.
59
63
60
64
Input: (i) Matrix A, vector b such that the polytope P = {x | Ax<=b}
61
65
(ii) The number of maximum iterations, max_iters
@@ -74,9 +78,10 @@ std::tuple<VT, bool> analytic_center_linear_ineq(MT const& A, VT const& b,
74
78
VT x;
75
79
bool feasibility_only = true , converged;
76
80
// Compute a feasible point
77
- std::tie (x, std::ignore, converged) = max_inscribed_ball (A, b, max_iters, 1e-08 , feasibility_only);
81
+ std::tie (x, std::ignore, converged) = max_inscribed_ball (A, b, max_iters, 1e-08 , feasibility_only);
78
82
VT Ax = A * x;
79
- if (!converged || (Ax.array () > b.array ()).any ()) {
83
+ if (!converged || (Ax.array () > b.array ()).any ())
84
+ {
80
85
std::runtime_error (" The computation of the analytic center failed." );
81
86
}
82
87
// Initialization
@@ -86,34 +91,38 @@ std::tuple<VT, bool> analytic_center_linear_ineq(MT const& A, VT const& b,
86
91
NT grad_err, rel_pos_err, rel_pos_err_temp, step;
87
92
unsigned int iter = 0 ;
88
93
converged = false ;
94
+ const NT tol_bnd = NT (0.01 );
89
95
90
96
get_hessian_grad_logbarrier<MT, VT, NT>(A, A_trans, b, x, Ax, H, grad, b_Ax);
91
97
92
98
do {
93
99
iter++;
94
100
// Compute the direction
95
- d.noalias () = - H.lu ().solve (grad);
101
+ d.noalias () = - H.llt ().solve (grad);
96
102
Ad.noalias () = A * d;
97
103
// Compute the step length
98
- step = std::min (NT (0.99 ) * get_max_step<VT, NT>(Ad, b_Ax), NT (1 ));
104
+ step = std::min (( NT (1 ) - tol_bnd ) * get_max_step<VT, NT>(Ad, b_Ax), NT (1 ));
99
105
step_d.noalias () = step*d;
100
106
x_prev = x;
101
107
x += step_d;
102
108
Ax.noalias () += step*Ad;
103
109
104
110
// Compute the max_i\{ |step*d_i| ./ |x_i| \}
105
111
rel_pos_err = std::numeric_limits<NT>::lowest ();
106
- for (int i = 0 ; i < n; i++) {
112
+ for (int i = 0 ; i < n; i++)
113
+ {
107
114
rel_pos_err_temp = std::abs (step_d.coeff (i) / x_prev.coeff (i));
108
- if (rel_pos_err_temp > rel_pos_err) {
115
+ if (rel_pos_err_temp > rel_pos_err)
116
+ {
109
117
rel_pos_err = rel_pos_err_temp;
110
- }
118
+ }
111
119
}
112
120
113
121
get_hessian_grad_logbarrier<MT, VT, NT>(A, A_trans, b, x, Ax, H, grad, b_Ax);
114
122
grad_err = grad.norm ();
115
123
116
- if (iter >= max_iters || grad_err <= grad_err_tol || rel_pos_err <= rel_pos_err_tol) {
124
+ if (iter >= max_iters || grad_err <= grad_err_tol || rel_pos_err <= rel_pos_err_tol)
125
+ {
117
126
converged = true ;
118
127
break ;
119
128
}
0 commit comments