Line data Source code
1 : /*
2 : * The MIT License (MIT)
3 : *
4 : * Copyright (c) 2017 Pantelis Sopasakis (https://alphaville.github.io),
5 : * Krina Menounou (https://www.linkedin.com/in/krinamenounou),
6 : * Panagiotis Patrinos (http://homes.esat.kuleuven.be/~ppatrino)
7 : * Copyright (c) 2012 Brendan O'Donoghue (bodonoghue85@gmail.com)
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a copy
10 : * of this software and associated documentation files (the "Software"), to deal
11 : * in the Software without restriction, including without limitation the rights
12 : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : * copies of the Software, and to permit persons to whom the Software is
14 : * furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included in all
17 : * copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : * SOFTWARE.
26 : *
27 : */
28 : #include "util.h"
29 : #include <float.h>
30 : #include <stdio.h>
31 :
32 : /* return milli-seconds */
33 : #if (defined NOTIMER)
34 :
35 : void scs_tic(ScsTimer *t) {
36 : }
37 :
38 : scs_float scs_toc_quiet(ScsTimer *t) {
39 : return NAN;
40 : }
41 :
42 : #elif(defined _WIN32 || _WIN64 || defined _WINDLL)
43 :
44 : void scs_tic(ScsTimer *t) {
45 : QueryPerformanceFrequency(&t->freq);
46 : QueryPerformanceCounter(&t->tic);
47 : }
48 :
49 : scs_float scs_toc_quiet(ScsTimer *t) {
50 : QueryPerformanceCounter(&t->toc);
51 : return (1e3 * (t->toc.QuadPart - t->tic.QuadPart) /
52 : (scs_float) t->freq.QuadPart);
53 : }
54 : #elif(defined __APPLE__)
55 :
56 : void scs_tic(ScsTimer *t) {
57 : /* read current clock cycles */
58 : t->tic = mach_absolute_time();
59 : }
60 :
61 : scs_float scs_toc_quiet(ScsTimer *t) {
62 : uint64_t duration; /* elapsed time in clock cycles*/
63 :
64 : t->toc = mach_absolute_time();
65 : duration = t->toc - t->tic;
66 :
67 : /*conversion from clock cycles to nanoseconds*/
68 : mach_timebase_info(&(t->tinfo));
69 : duration *= t->tinfo.numer;
70 : duration /= t->tinfo.denom;
71 :
72 : return (scs_float) duration / 1e6;
73 : }
74 : #else
75 :
76 129628 : void scs_tic(ScsTimer *t) {
77 129628 : clock_gettime(CLOCK_MONOTONIC, &t->tic);
78 129628 : }
79 :
80 160709 : scs_float scs_toc_quiet(ScsTimer *t) {
81 : struct timespec temp;
82 :
83 160709 : clock_gettime(CLOCK_MONOTONIC, &t->toc);
84 :
85 160709 : if ((t->toc.tv_nsec - t->tic.tv_nsec) < 0) {
86 151 : temp.tv_sec = t->toc.tv_sec - t->tic.tv_sec - 1;
87 151 : temp.tv_nsec = 1e9 + t->toc.tv_nsec - t->tic.tv_nsec;
88 : } else {
89 160558 : temp.tv_sec = t->toc.tv_sec - t->tic.tv_sec;
90 160558 : temp.tv_nsec = t->toc.tv_nsec - t->tic.tv_nsec;
91 : }
92 160709 : return (scs_float) temp.tv_sec * 1e3 + (scs_float) temp.tv_nsec / 1e6;
93 : }
94 : #endif
95 :
96 : /* LCOV_EXCL_START */
97 : scs_float scs_toc(ScsTimer *t) {
98 : scs_float time = scs_toc_quiet(t);
99 : scs_printf("time: %8.4f milli-seconds.\n", time);
100 : return time;
101 : }
102 :
103 : scs_float scs_strtoc(char *str, ScsTimer *t) {
104 : scs_float time = scs_toc_quiet(t);
105 : scs_printf("%s - time: %8.4f milli-seconds.\n", str, time);
106 : return time;
107 : }
108 :
109 : void scs_print_cone_data(const ScsCone *RESTRICT k) {
110 : scs_int i;
111 : scs_printf("num zeros = %i\n", (int) k->f);
112 : scs_printf("num LP = %i\n", (int) k->l);
113 : scs_printf("num SOCs = %i\n", (int) k->qsize);
114 : scs_printf("soc array:\n");
115 : for (i = 0; i < k->qsize; i++) {
116 : scs_printf("%i\n", (int) k->q[i]);
117 : }
118 : scs_printf("num SDCs = %i\n", (int) k->ssize);
119 : scs_printf("sdc array:\n");
120 : for (i = 0; i < k->ssize; i++) {
121 : scs_printf("%i\n", (int) k->s[i]);
122 : }
123 : scs_printf("num ep = %i\n", (int) k->ep);
124 : scs_printf("num ed = %i\n", (int) k->ed);
125 : scs_printf("num PCs = %i\n", (int) k->psize);
126 : scs_printf("pow array:\n");
127 : for (i = 0; i < k->psize; i++) {
128 : scs_printf("%4f\n", (double) k->p[i]);
129 : }
130 : }
131 :
132 : void scs_print_work(const ScsWork *w) {
133 : scs_int i, l = w->n + w->m;
134 : scs_printf("\n u_t is \n");
135 : for (i = 0; i < l; i++) {
136 : scs_printf("%f\n", w->u_t[i]);
137 : }
138 : scs_printf("\n u is \n");
139 : for (i = 0; i < l; i++) {
140 : scs_printf("%f\n", w->u[i]);
141 : }
142 : scs_printf("\n v is \n");
143 : for (i = 0; i < l; i++) {
144 : scs_printf("%f\n", w->v[i]);
145 : }
146 : }
147 :
148 : void scs_print_data(const ScsData *d) {
149 : scs_printf("m = %i\n", (int) d->m);
150 : scs_printf("n = %i\n", (int) d->n);
151 :
152 : scs_printf("max_iters = %i\n", (int) d->stgs->max_iters);
153 : scs_printf("verbose = %i\n", (int) d->stgs->verbose);
154 : scs_printf("normalize = %i\n", (int) d->stgs->normalize);
155 : scs_printf("warmStart = %i\n", (int) d->stgs->warm_start);
156 : scs_printf("eps = %4f\n", d->stgs->eps);
157 : scs_printf("alpha = %4f\n", d->stgs->alpha);
158 : scs_printf("rhoX = %4f\n", d->stgs->rho_x);
159 : scs_printf("cg_rate = %4f\n", d->stgs->cg_rate);
160 : scs_printf("scale = %4f\n", d->stgs->scale);
161 : }
162 :
163 : void scs_print_array(const scs_float *RESTRICT arr, scs_int n, const char *RESTRICT name) {
164 : scs_int i, j, k = 0;
165 : scs_int numOnOneLine = 1;
166 : const scs_int n_max = MAX(n, 1e5);
167 :
168 : scs_printf("\n");
169 : for (i = 0; i < n_max / numOnOneLine; ++i) {
170 : for (j = 0; j < numOnOneLine; ++j) {
171 : scs_printf("%s[%li] = %4f, ", name, (long) k, arr[(unsigned) k]);
172 : k++;
173 : }
174 : scs_printf("\n");
175 : }
176 : for (j = k; j < n_max; ++j) {
177 : scs_printf("%s[%li] = %4f, ", name, (long) j, arr[(unsigned) j]);
178 : }
179 : scs_printf("\n");
180 : }
181 :
182 : /* LCOV_EXCL_STOP */
183 :
184 45 : void scs_free_data(ScsData *RESTRICT data) {
185 45 : if (data != SCS_NULL) {
186 45 : if (data->b != SCS_NULL)
187 40 : scs_free(data->b);
188 45 : if (data->c != SCS_NULL)
189 40 : scs_free(data->c);
190 45 : if (data->stgs != SCS_NULL)
191 45 : scs_free(data->stgs);
192 45 : if (data->A != SCS_NULL) {
193 40 : scs_free_a_matrix(data->A);
194 : }
195 45 : scs_free(data);
196 : }
197 45 : }
198 :
199 40 : void scs_free_cone(ScsCone *RESTRICT cone) {
200 40 : if (cone != SCS_NULL) {
201 40 : if (cone->q != SCS_NULL)
202 34 : scs_free(cone->q);
203 40 : if (cone->s != SCS_NULL)
204 8 : scs_free(cone->s);
205 40 : if (cone->p != SCS_NULL)
206 5 : scs_free(cone->p);
207 40 : scs_free(cone);
208 : }
209 40 : }
210 :
211 40 : void scs_free_data_cone(ScsData *RESTRICT data, ScsCone *RESTRICT cone) {
212 40 : scs_free_data(data);
213 40 : scs_free_cone(cone);
214 40 : }
215 :
216 19 : void scs_free_sol(ScsSolution *sol) {
217 19 : if (sol != SCS_NULL) {
218 19 : if (sol->x != SCS_NULL) {
219 19 : scs_free(sol->x);
220 : }
221 19 : if (sol->y != SCS_NULL) {
222 19 : scs_free(sol->y);
223 : }
224 19 : if (sol->s != SCS_NULL) {
225 19 : scs_free(sol->s);
226 : }
227 19 : scs_free(sol);
228 : }
229 19 : }
230 :
231 18 : void scs_free_info(ScsInfo *RESTRICT info) {
232 18 : if (info != SCS_NULL) {
233 18 : if (info->progress_iter != SCS_NULL) {
234 3 : scs_free(info->progress_iter);
235 : }
236 18 : if (info->progress_relgap != SCS_NULL) {
237 3 : scs_free(info->progress_relgap);
238 : }
239 18 : if (info->progress_resdual != SCS_NULL) {
240 3 : scs_free(info->progress_resdual);
241 : }
242 18 : if (info->progress_respri != SCS_NULL) {
243 3 : scs_free(info->progress_respri);
244 : }
245 18 : if (info->progress_pcost != SCS_NULL) {
246 3 : scs_free(info->progress_pcost);
247 : }
248 18 : if (info->progress_dcost != SCS_NULL) {
249 3 : scs_free(info->progress_dcost);
250 : }
251 18 : if (info->progress_norm_fpr != SCS_NULL) {
252 3 : scs_free(info->progress_norm_fpr);
253 : }
254 18 : if (info->progress_time != SCS_NULL) {
255 3 : scs_free(info->progress_time);
256 : }
257 18 : if (info->progress_mode != SCS_NULL) {
258 3 : scs_free(info->progress_mode);
259 : }
260 18 : if (info->progress_ls != SCS_NULL) {
261 3 : scs_free(info->progress_ls);
262 : }
263 18 : scs_free(info);
264 : }
265 18 : }
266 :
267 : /* assumes d->stgs already allocated memory */
268 61 : void scs_set_default_settings(ScsData *RESTRICT d) {
269 61 : d->stgs->max_time_milliseconds = SCS_MAX_TIME_MILLISECONDS;
270 61 : d->stgs->max_iters = SCS_MAX_ITERS_DEFAULT; /* maximum iterations to take: 2500 */
271 61 : d->stgs->previous_max_iters = SCS_PMAXITER_DEFAULT; /* maximum iterations of previous invocation */
272 61 : d->stgs->eps = SCS_EPS_DEFAULT; /* convergence tolerance: 1e-3 */
273 61 : d->stgs->alpha = SCS_ALPHA_DEFAULT; /* relaxation parameter: 1.5 */
274 61 : d->stgs->rho_x = SCS_RHO_X_DEFAULT; /* parameter rho_x: 1e-3 */
275 61 : d->stgs->scale = SCS_SCALE_DEFAULT; /* if normalized, rescales by this factor: 1 */
276 61 : d->stgs->cg_rate = SCS_CG_RATE_DEFAULT; /* for indirect, tolerance goes down like (1/iter)^CG_RATE: 2 */
277 61 : d->stgs->verbose = SCS_VERBOSE_DEFAULT; /* int, 3 levels (0, 1, 2), write out progress: 1 */
278 61 : d->stgs->normalize = SCS_NORMALIZE_DEFAULT; /* boolean, heuristic data rescaling: 1 */
279 61 : d->stgs->warm_start = SCS_WARM_START_DEFAULT;
280 :
281 : /* -----------------------------
282 : * SuperSCS-specific parameters
283 : * ----------------------------- */
284 61 : d->stgs->beta = SCS_BETA_DEFAULT;
285 61 : d->stgs->c1 = SCS_C1_DEFAULT;
286 61 : d->stgs->c_bl = SCS_C_BL_DEFAULT;
287 61 : d->stgs->k0 = SCS_K0_DEFAULT;
288 61 : d->stgs->k1 = SCS_K1_DEFAULT;
289 61 : d->stgs->k2 = SCS_K2_DEFAULT;
290 61 : d->stgs->ls = SCS_LS_DEFAULT;
291 61 : d->stgs->sigma = SCS_SIGMA_DEFAULT;
292 61 : d->stgs->thetabar = SCS_THETABAR_DEFAULT;
293 61 : d->stgs->sse = SCS_SSE_DEFAULT;
294 61 : d->stgs->memory = SCS_MEMORY_DEFAULT;
295 61 : d->stgs->direction = SCS_DIRECTION_DEFAULT;
296 61 : d->stgs->do_super_scs = SCS_DO_SUPERSCS_DEFAULT; /* whether to run in SuperSCS mode (default: 1) */
297 61 : d->stgs->do_record_progress = SCS_DO_RECORD_PROGRESS_DEFAULT;
298 61 : d->stgs->do_override_streams = SCS_OVERRIDE_STREAMS_DEFAULT;
299 61 : d->stgs->output_stream = SCS_OUT_STREAM_DEFAULT;
300 61 : d->stgs->tRule = 1;
301 61 : d->stgs->broyden_init_scaling = SCS_BROYDEN_ISCS_SCALE_DEFAULT;
302 61 : }
303 :
304 3 : void scs_set_tolerance(ScsData * RESTRICT data, scs_float tolerance) {
305 6 : if (data == SCS_NULL || data->stgs == SCS_NULL) return;
306 3 : data->stgs->eps = MAX(tolerance, 10 * DBL_EPSILON);
307 : }
308 :
309 6 : void scs_set_memory(ScsData * RESTRICT data, scs_int memory) {
310 6 : if (data->stgs->direction == anderson_acceleration) {
311 4 : data->stgs->memory = MAX(2, MIN(data->m + data->n + 1, memory));
312 : } else {
313 2 : data->stgs->memory = MAX(2, memory);
314 : }
315 6 : }
316 :
317 2 : void scs_set_restarted_broyden_settings(ScsData * RESTRICT data, scs_int broyden_memory) {
318 4 : if (data == SCS_NULL || data->stgs == SCS_NULL) return;
319 2 : scs_set_default_settings(data);
320 2 : data->stgs->direction = restarted_broyden;
321 2 : scs_set_memory(data, broyden_memory);
322 2 : data->stgs->k0 = 0;
323 : }
324 :
325 2 : void scs_set_anderson_settings(ScsData * RESTRICT data, scs_int anderson_memory) {
326 4 : if (data == SCS_NULL || data->stgs == SCS_NULL) return;
327 2 : scs_set_default_settings(data);
328 2 : data->stgs->direction = anderson_acceleration;
329 2 : scs_set_memory(data, anderson_memory);
330 2 : data->stgs->k0 = 1;
331 : }
332 :
333 1537 : int scs_special_print(
334 : scs_int print_mode,
335 : FILE *RESTRICT __stream,
336 : const char *RESTRICT __format, ...) {
337 : int status;
338 : va_list args; /* variable-lenth args */
339 1537 : va_start(args, __format); /* The variable-lenth args start after __format */
340 :
341 1537 : if (print_mode == 0) {
342 : /* -----------------------------------------------------
343 : * The reason we do the following is because MATLAB
344 : * redefines printf as mexPrintf. If we use vprintf,
345 : * or any other function, such as fprintf, MATLAB will
346 : * not be able to show anything in the MATLAB console.
347 : * ----------------------------------------------------- */
348 : char message_buffer[4096];
349 : vsnprintf(message_buffer, 4096, __format, args);
350 0 : status = printf("%s", message_buffer);
351 : } else {
352 1537 : status = vfprintf(__stream, __format, args);
353 : }
354 1537 : va_end(args);
355 1537 : return status;
356 : }
|