|
| 1 | +#include "glbopts.h" |
| 2 | +#include "linalg.h" |
| 3 | +#include "minunit.h" |
| 4 | +#include "problem_utils.h" |
| 5 | +#include "scs.h" |
| 6 | +#include "scs_matrix.h" |
| 7 | +#include "util.h" |
| 8 | + |
| 9 | +static const char *partial_warm_start(void) { |
| 10 | + ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); |
| 11 | + ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); |
| 12 | + ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); |
| 13 | + ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); |
| 14 | + ScsInfo info = {0}; |
| 15 | + scs_int exitflag; |
| 16 | + scs_int cold_iters; |
| 17 | + scs_int i; |
| 18 | + scs_float perr, derr; |
| 19 | + scs_int success; |
| 20 | + const char *fail; |
| 21 | + |
| 22 | + /* data (same as hs21_tiny_qp) */ |
| 23 | + scs_float Ax[] = {-10., -1., 1., -1.}; |
| 24 | + scs_int Ai[] = {1, 2, 1, 3}; |
| 25 | + scs_int Ap[] = {0, 2, 4}; |
| 26 | + |
| 27 | + scs_float Px[] = {0.02, 2.}; |
| 28 | + scs_int Pi[] = {0, 1}; |
| 29 | + scs_int Pp[] = {0, 1, 2}; |
| 30 | + |
| 31 | + scs_float b[] = {1., 0., 0., 0.}; |
| 32 | + scs_float c[] = {0., 0.}; |
| 33 | + |
| 34 | + scs_int m = 4; |
| 35 | + scs_int n = 2; |
| 36 | + |
| 37 | + scs_float bl[] = {10.0, 2.0, -50.0}; |
| 38 | + scs_float bu[] = {1e+20, 50.0, 50.0}; |
| 39 | + scs_int bsize = 4; |
| 40 | + |
| 41 | + scs_float opt = 0.04000000000000625; |
| 42 | + /* end data */ |
| 43 | + |
| 44 | + d->m = m; |
| 45 | + d->n = n; |
| 46 | + d->b = b; |
| 47 | + d->c = c; |
| 48 | + |
| 49 | + d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); |
| 50 | + d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); |
| 51 | + |
| 52 | + d->A->m = m; |
| 53 | + d->A->n = n; |
| 54 | + |
| 55 | + d->A->x = Ax; |
| 56 | + d->A->i = Ai; |
| 57 | + d->A->p = Ap; |
| 58 | + |
| 59 | + d->P->m = n; |
| 60 | + d->P->n = n; |
| 61 | + |
| 62 | + d->P->x = Px; |
| 63 | + d->P->i = Pi; |
| 64 | + d->P->p = Pp; |
| 65 | + |
| 66 | + k->bsize = bsize; |
| 67 | + k->bl = bl; |
| 68 | + k->bu = bu; |
| 69 | + |
| 70 | + scs_set_default_settings(stgs); |
| 71 | + stgs->eps_abs = 1e-9; |
| 72 | + stgs->eps_rel = 1e-9; |
| 73 | + stgs->eps_infeas = 0.; |
| 74 | + stgs->acceleration_lookback = 0; /* disable acceleration for consistent iters */ |
| 75 | + |
| 76 | + /* Step 1: Cold solve to get reference solution and iteration count */ |
| 77 | + exitflag = scs(d, k, stgs, sol, &info); |
| 78 | + |
| 79 | + perr = info.pobj - opt; |
| 80 | + derr = info.dobj - opt; |
| 81 | + |
| 82 | + success = ABS(perr) < 1e-3 && ABS(derr) < 1e-3 && exitflag == SCS_SOLVED; |
| 83 | + mu_assert("partial_warm_start: cold solve failed", success); |
| 84 | + fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); |
| 85 | + if (fail) { |
| 86 | + SCS(free_sol)(sol); |
| 87 | + scs_free(d->A); |
| 88 | + scs_free(d->P); |
| 89 | + scs_free(k); |
| 90 | + scs_free(stgs); |
| 91 | + scs_free(d); |
| 92 | + return fail; |
| 93 | + } |
| 94 | + |
| 95 | + cold_iters = info.iter; |
| 96 | + scs_printf("partial_warm_start: cold solve took %li iters\n", |
| 97 | + (long)cold_iters); |
| 98 | + |
| 99 | + /* Step 2: Partial warm start - keep x, set s and y to NaN */ |
| 100 | + for (i = 0; i < m; ++i) { |
| 101 | + sol->s[i] = NAN; |
| 102 | + sol->y[i] = NAN; |
| 103 | + } |
| 104 | + |
| 105 | + stgs->warm_start = 1; |
| 106 | + exitflag = scs(d, k, stgs, sol, &info); |
| 107 | + |
| 108 | + perr = info.pobj - opt; |
| 109 | + derr = info.dobj - opt; |
| 110 | + |
| 111 | + success = ABS(perr) < 1e-3 && ABS(derr) < 1e-3 && exitflag == SCS_SOLVED; |
| 112 | + mu_assert("partial_warm_start: partial warm start (x only) failed to solve", |
| 113 | + success); |
| 114 | + |
| 115 | + scs_printf("partial_warm_start: partial warm start (x only) took %li iters\n", |
| 116 | + (long)info.iter); |
| 117 | + mu_assert( |
| 118 | + "partial_warm_start: partial warm start should take fewer iters than " |
| 119 | + "cold start", |
| 120 | + info.iter < cold_iters); |
| 121 | + |
| 122 | + /* Step 3: All-NaN warm start - should still converge */ |
| 123 | + for (i = 0; i < n; ++i) { |
| 124 | + sol->x[i] = NAN; |
| 125 | + } |
| 126 | + for (i = 0; i < m; ++i) { |
| 127 | + sol->s[i] = NAN; |
| 128 | + sol->y[i] = NAN; |
| 129 | + } |
| 130 | + |
| 131 | + stgs->warm_start = 1; |
| 132 | + exitflag = scs(d, k, stgs, sol, &info); |
| 133 | + |
| 134 | + perr = info.pobj - opt; |
| 135 | + derr = info.dobj - opt; |
| 136 | + |
| 137 | + success = ABS(perr) < 1e-3 && ABS(derr) < 1e-3 && exitflag == SCS_SOLVED; |
| 138 | + mu_assert("partial_warm_start: all-NaN warm start failed to solve", success); |
| 139 | + |
| 140 | + scs_printf("partial_warm_start: all-NaN warm start took %li iters\n", |
| 141 | + (long)info.iter); |
| 142 | + |
| 143 | + SCS(free_sol)(sol); |
| 144 | + scs_free(d->A); |
| 145 | + scs_free(d->P); |
| 146 | + scs_free(k); |
| 147 | + scs_free(stgs); |
| 148 | + scs_free(d); |
| 149 | + return fail; |
| 150 | +} |
0 commit comments