@@ -17,7 +17,7 @@ double objective_qp(double *nndef_ptr, /* A non-negative definite matrix *
17
17
int * nactive_ptr , /* Size of ever active set */
18
18
int nrow , /* how many rows in nndef */
19
19
double bound , /* Lagrange multipler for \ell_1 */
20
- double * theta ) /* current value */
20
+ double * theta_ptr ) /* current value */
21
21
{
22
22
int irow , icol ;
23
23
double value = 0 ;
@@ -28,20 +28,20 @@ double objective_qp(double *nndef_ptr, /* A non-negative definite matrix *
28
28
int active_row , active_col ;
29
29
int nactive = * nactive_ptr ;
30
30
31
- theta_row_ptr = theta ;
32
- theta_col_ptr = theta ;
31
+ theta_row_ptr = theta_ptr ;
32
+ theta_col_ptr = theta_ptr ;
33
33
34
34
for (irow = 0 ; irow < nactive ; irow ++ ) {
35
35
36
36
active_row_ptr = ((int * ) ever_active_ptr + irow );
37
37
active_row = * active_row_ptr - 1 ; // Ever-active is 1-based
38
- theta_row_ptr = ((double * ) theta + active_row );
38
+ theta_row_ptr = ((double * ) theta_ptr + active_row );
39
39
40
40
for (icol = 0 ; icol < nactive ; icol ++ ) {
41
41
42
42
active_col_ptr = ((int * ) ever_active_ptr + icol );
43
43
active_col = * active_col_ptr - 1 ; // Ever-active is 1-based
44
- theta_col_ptr = ((double * ) theta + active_col );
44
+ theta_col_ptr = ((double * ) theta_ptr + active_col );
45
45
46
46
nndef_ptr_tmp = ((double * ) nndef_ptr + nrow * active_col + active_row ); // Matrices are column-major order
47
47
@@ -90,7 +90,7 @@ int update_ever_active_qp(int coord,
90
90
return (0 );
91
91
}
92
92
93
- int check_KKT_qp (double * theta , /* current theta */
93
+ int check_KKT_qp (double * theta_ptr , /* current theta */
94
94
double * gradient_ptr , /* nndef times theta + linear_func */
95
95
int nrow , /* how many rows in nndef */
96
96
double bound , /* Lagrange multipler for \ell_1 */
@@ -99,22 +99,22 @@ int check_KKT_qp(double *theta, /* current theta */
99
99
// First check inactive
100
100
101
101
int irow ;
102
- double * theta_ptr , * gradient_ptr_tmp ;
102
+ double * theta_ptr_tmp , * gradient_ptr_tmp ;
103
103
double gradient ;
104
104
105
105
for (irow = 0 ; irow < nrow ; irow ++ ) {
106
- theta_ptr = ((double * ) theta + irow );
106
+ theta_ptr_tmp = ((double * ) theta_ptr + irow );
107
107
gradient_ptr_tmp = ((double * ) gradient_ptr + irow );
108
108
109
109
// Compute this coordinate of the gradient
110
110
111
111
gradient = * gradient_ptr_tmp ;
112
112
113
- if (* theta_ptr != 0 ) { // these coordinates of gradients should be equal to -bound
114
- if ((* theta_ptr > 0 ) && (fabs (gradient + bound ) > tol * bound )) {
113
+ if (* theta_ptr_tmp != 0 ) { // these coordinates of gradients should be equal to -bound
114
+ if ((* theta_ptr_tmp > 0 ) && (fabs (gradient + bound ) > tol * bound )) {
115
115
return (0 );
116
116
}
117
- else if ((* theta_ptr < 0 ) && (fabs (gradient - bound ) > tol * bound )) {
117
+ else if ((* theta_ptr_tmp < 0 ) && (fabs (gradient - bound ) > tol * bound )) {
118
118
return (0 );
119
119
}
120
120
}
@@ -128,6 +128,57 @@ int check_KKT_qp(double *theta, /* current theta */
128
128
return (1 );
129
129
}
130
130
131
+ int check_KKT_qp_active (int * ever_active_ptr , /* Ever active set: 0-based */
132
+ int * nactive_ptr , /* Size of ever active set */
133
+ double * theta_ptr , /* current theta */
134
+ double * gradient_ptr , /* nndef times theta + linear_func */
135
+ int nrow , /* how many rows in nndef */
136
+ double bound , /* Lagrange multipler for \ell_1 */
137
+ double tol ) /* precision for checking KKT conditions */
138
+ {
139
+ // First check inactive
140
+
141
+ int iactive ;
142
+ double * theta_ptr_tmp ;
143
+ double gradient ;
144
+ double * gradient_ptr_tmp ;
145
+ int nactive = * nactive_ptr ;
146
+ int active_feature ;
147
+ int * active_feature_ptr ;
148
+
149
+ for (iactive = 0 ; iactive < nactive ; iactive ++ ) {
150
+
151
+ active_feature_ptr = ((int * ) ever_active_ptr + iactive );
152
+ active_feature = * active_feature_ptr - 1 ; // Ever-active is 1-based
153
+ theta_ptr_tmp = ((double * ) theta_ptr + active_feature );
154
+
155
+ gradient_ptr_tmp = ((double * ) gradient_ptr + active_feature );
156
+
157
+ // Compute this coordinate of the gradient
158
+
159
+ gradient = * gradient_ptr_tmp ;
160
+
161
+ if (* theta_ptr_tmp != 0 ) { // these coordinates of gradients should be equal to -bound
162
+
163
+ if ((* theta_ptr_tmp > 0 ) && (fabs (gradient + bound ) > tol * bound )) {
164
+ return (0 );
165
+ }
166
+ else if ((* theta_ptr_tmp < 0 ) && (fabs (gradient - bound ) > tol * bound )) {
167
+ return (0 );
168
+ }
169
+
170
+ }
171
+ else {
172
+ if (fabs (gradient ) > (1. + tol ) * bound ) {
173
+ return (0 );
174
+ }
175
+ }
176
+ }
177
+
178
+ return (1 );
179
+ }
180
+
181
+
131
182
double update_one_coord_qp (double * nndef_ptr , /* A non-negative definite matrix */
132
183
double * linear_func_ptr , /* Linear term in objective */
133
184
double * nndef_diag_ptr , /* Diagonal of nndef */
@@ -136,7 +187,7 @@ double update_one_coord_qp(double *nndef_ptr, /* A non-negative defini
136
187
int * nactive_ptr , /* Size of ever active set */
137
188
int nrow , /* How many rows in nndef */
138
189
double bound , /* feasibility parameter */
139
- double * theta , /* current value */
190
+ double * theta_ptr , /* current value */
140
191
int coord , /* which coordinate to update: 0-based */
141
192
int is_active ) /* Is this coord in ever_active */
142
193
{
@@ -147,7 +198,7 @@ double update_one_coord_qp(double *nndef_ptr, /* A non-negative defini
147
198
double old_value ;
148
199
double * nndef_ptr_tmp ;
149
200
double * gradient_ptr_tmp ;
150
- double * theta_ptr ;
201
+ double * theta_ptr_tmp ;
151
202
int icol = 0 ;
152
203
153
204
double * quadratic_ptr = ((double * ) nndef_diag_ptr + coord );
@@ -156,8 +207,8 @@ double update_one_coord_qp(double *nndef_ptr, /* A non-negative defini
156
207
gradient_ptr_tmp = ((double * ) gradient_ptr + coord );
157
208
linear_term = * gradient_ptr_tmp ;
158
209
159
- theta_ptr = ((double * ) theta + coord );
160
- old_value = * theta_ptr ;
210
+ theta_ptr_tmp = ((double * ) theta_ptr + coord );
211
+ old_value = * theta_ptr_tmp ;
161
212
162
213
// The coord entry of gradient_ptr term has a diagonal term in it:
163
214
// nndef[coord, coord] * theta[coord]
@@ -200,8 +251,8 @@ double update_one_coord_qp(double *nndef_ptr, /* A non-negative defini
200
251
nndef_ptr_tmp += 1 ;
201
252
}
202
253
203
- theta_ptr = ((double * ) theta + coord );
204
- * theta_ptr = value ;
254
+ theta_ptr_tmp = ((double * ) theta_ptr + coord );
255
+ * theta_ptr_tmp = value ;
205
256
206
257
}
207
258
@@ -230,6 +281,8 @@ int solve_qp(double *nndef_ptr, /* A non-negative definite matrix */
230
281
int * active_ptr ;
231
282
232
283
int check_objective = 1 ;
284
+ int iter_active ;
285
+ int niter_active = 5 ;
233
286
234
287
double old_value , new_value ;
235
288
@@ -248,23 +301,38 @@ int solve_qp(double *nndef_ptr, /* A non-negative definite matrix */
248
301
249
302
for (iter = 0 ; iter < maxiter ; iter ++ ) {
250
303
251
- // Update the active variables first
252
-
253
- active_ptr = (int * ) ever_active_ptr ;
254
-
255
- for (iactive = 0 ; iactive < * nactive_ptr ; iactive ++ ) {
256
- update_one_coord_qp (nndef_ptr ,
257
- linear_func_ptr ,
258
- nndef_diag_ptr ,
259
- gradient_ptr ,
260
- ever_active_ptr ,
261
- nactive_ptr ,
262
- nrow ,
263
- bound ,
264
- theta ,
265
- * active_ptr - 1 , // Ever-active is 1-based
266
- 1 );
267
- active_ptr ++ ;
304
+ // Update the active variables first -- do this niter_active times
305
+
306
+ for (iter_active = 0 ; iter_active < niter_active ; iter_active ++ ) {
307
+
308
+ active_ptr = (int * ) ever_active_ptr ;
309
+ for (iactive = 0 ; iactive < * nactive_ptr ; iactive ++ ) {
310
+
311
+ update_one_coord_qp (nndef_ptr ,
312
+ linear_func_ptr ,
313
+ nndef_diag_ptr ,
314
+ gradient_ptr ,
315
+ ever_active_ptr ,
316
+ nactive_ptr ,
317
+ nrow ,
318
+ bound ,
319
+ theta ,
320
+ * active_ptr - 1 , // Ever-active is 1-based
321
+ 1 );
322
+ active_ptr ++ ;
323
+ }
324
+
325
+ // Check KKT of active subproblem
326
+
327
+ if (check_KKT_qp_active (ever_active_ptr ,
328
+ nactive_ptr ,
329
+ theta ,
330
+ gradient_ptr ,
331
+ nrow ,
332
+ bound ,
333
+ kkt_tol ) == 1 ) {
334
+ break ;
335
+ }
268
336
}
269
337
270
338
// Check KKT
0 commit comments