1 module kkt; 2 3 nothrow @nogc extern(C): 4 5 import glob_opts; 6 import cs; 7 import types; // CSC matrix type 8 import constants; // for OSQP_NULL 9 10 version(EMBEDDED){} 11 else { 12 csc* form_KKT(const csc *P, 13 const csc *A, 14 c_int format, 15 c_float param1, 16 c_float *param2, 17 c_int *PtoKKT, 18 c_int *AtoKKT, 19 c_int **Pdiag_idx, 20 c_int *Pdiag_n, 21 c_int *param2toKKT) { 22 c_int nKKT; // Size, number of nonzeros and max number of nonzeros in KKT matrix 23 c_int nnzKKTmax; // Size, number of nonzeros and max number of nonzeros in KKT matrix 24 csc *KKT_trip; // KKT matrix in triplet format and CSC format 25 csc *KKT; // KKT matrix in triplet format and CSC format 26 c_int ptr, i, j; // Counters for elements (i,j) and index pointer 27 c_int zKKT = 0; // Counter for total number of elements in P and in 28 // KKT 29 c_int *KKT_TtoC; // Pointer to vector mapping from KKT in triplet form 30 // to CSC 31 32 // Get matrix dimensions 33 nKKT = P.m + A.m; 34 35 // Get maximum number of nonzero elements (only upper triangular part) 36 nnzKKTmax = P.p[P.n] + // Number of elements in P 37 P.m + // Number of elements in param1 * I 38 A.p[A.n] + // Number of nonzeros in A 39 A.m; // Number of elements in - diag(param2) 40 41 // Preallocate KKT matrix in triplet format 42 KKT_trip = csc_spalloc(nKKT, nKKT, nnzKKTmax, 1, 1); 43 44 if (!KKT_trip) return OSQP_NULL; // Failed to preallocate matrix 45 46 // Allocate vector of indices on the diagonal. Worst case it has m elements 47 if (Pdiag_idx != OSQP_NULL) { 48 (*Pdiag_idx) = cast(c_int*)c_malloc(P.m * c_int.sizeof); 49 *Pdiag_n = 0; // Set 0 diagonal elements to start 50 } 51 52 // Allocate Triplet matrices 53 // P + param1 I 54 for (j = 0; j < P.n; j++) { // cycle over columns 55 // No elements in column j => add diagonal element param1 56 if (P.p[j] == P.p[j + 1]) { 57 KKT_trip.i[zKKT] = j; 58 KKT_trip.p[zKKT] = j; 59 KKT_trip.x[zKKT] = param1; 60 zKKT++; 61 } 62 63 for (ptr = P.p[j]; ptr < P.p[j + 1]; ptr++) { // cycle over rows 64 // Get current row 65 i = P.i[ptr]; 66 67 // Add element of P 68 KKT_trip.i[zKKT] = i; 69 KKT_trip.p[zKKT] = j; 70 KKT_trip.x[zKKT] = P.x[ptr]; 71 72 if (PtoKKT != OSQP_NULL) PtoKKT[ptr] = zKKT; // Update index from P to 73 // KKTtrip 74 75 if (i == j) { // P has a diagonal element, 76 // add param1 77 KKT_trip.x[zKKT] += param1; 78 79 // If index vector pointer supplied . Store the index 80 if (Pdiag_idx != OSQP_NULL) { 81 (*Pdiag_idx)[*Pdiag_n] = ptr; 82 (*Pdiag_n)++; 83 } 84 } 85 zKKT++; 86 87 // Add diagonal param1 in case 88 if ((i < j) && // Diagonal element not reached 89 (ptr + 1 == P.p[j + 1])) { // last element of column j 90 // Add diagonal element param1 91 KKT_trip.i[zKKT] = j; 92 KKT_trip.p[zKKT] = j; 93 KKT_trip.x[zKKT] = param1; 94 zKKT++; 95 } 96 } 97 } 98 99 if (Pdiag_idx != OSQP_NULL) { 100 // Realloc Pdiag_idx so that it contains exactly *Pdiag_n diagonal elements 101 (*Pdiag_idx) = cast(c_int*)c_realloc((*Pdiag_idx), (*Pdiag_n) * c_int.sizeof); 102 } 103 104 105 // A' at top right 106 for (j = 0; j < A.n; j++) { // Cycle over columns of A 107 for (ptr = A.p[j]; ptr < A.p[j + 1]; ptr++) { 108 KKT_trip.p[zKKT] = P.m + A.i[ptr]; // Assign column index from 109 // row index of A 110 KKT_trip.i[zKKT] = j; // Assign row index from 111 // column index of A 112 KKT_trip.x[zKKT] = A.x[ptr]; // Assign A value element 113 114 if (AtoKKT != OSQP_NULL) AtoKKT[ptr] = zKKT; // Update index from A to 115 // KKTtrip 116 zKKT++; 117 } 118 } 119 120 // - diag(param2) at bottom right 121 for (j = 0; j < A.m; j++) { 122 KKT_trip.i[zKKT] = j + P.n; 123 KKT_trip.p[zKKT] = j + P.n; 124 KKT_trip.x[zKKT] = -param2[j]; 125 126 if (param2toKKT != OSQP_NULL) param2toKKT[j] = zKKT; // Update index from 127 // param2 to KKTtrip 128 zKKT++; 129 } 130 131 // Allocate number of nonzeros 132 KKT_trip.nz = zKKT; 133 134 // Convert triplet matrix to csc format 135 if (!PtoKKT && !AtoKKT && !param2toKKT) { 136 // If no index vectors passed, do not store KKT mapping from Trip to CSC/CSR 137 if (format == 0) KKT = triplet_to_csc(KKT_trip, OSQP_NULL); 138 else KKT = triplet_to_csr(KKT_trip, OSQP_NULL); 139 } 140 else { 141 // Allocate vector of indices from triplet to csc 142 KKT_TtoC = cast(c_int*)c_malloc((zKKT) * c_int.sizeof); 143 144 if (!KKT_TtoC) { 145 // Error in allocating KKT_TtoC vector 146 csc_spfree(KKT_trip); 147 c_free(*Pdiag_idx); 148 return OSQP_NULL; 149 } 150 151 // Store KKT mapping from Trip to CSC/CSR 152 if (format == 0) 153 KKT = triplet_to_csc(KKT_trip, KKT_TtoC); 154 else 155 KKT = triplet_to_csr(KKT_trip, KKT_TtoC); 156 157 // Update vectors of indices from P, A, param2 to KKT (now in CSC format) 158 if (PtoKKT != OSQP_NULL) { 159 for (i = 0; i < P.p[P.n]; i++) { 160 PtoKKT[i] = KKT_TtoC[PtoKKT[i]]; 161 } 162 } 163 164 if (AtoKKT != OSQP_NULL) { 165 for (i = 0; i < A.p[A.n]; i++) { 166 AtoKKT[i] = KKT_TtoC[AtoKKT[i]]; 167 } 168 } 169 170 if (param2toKKT != OSQP_NULL) { 171 for (i = 0; i < A.m; i++) { 172 param2toKKT[i] = KKT_TtoC[param2toKKT[i]]; 173 } 174 } 175 176 // Free mapping 177 c_free(KKT_TtoC); 178 } 179 180 // Clean matrix in triplet format and return result 181 csc_spfree(KKT_trip); 182 183 return KKT; 184 } 185 186 } /* ifndef EMBEDDED */ 187 188 189 version (EMBEDDED_1){} 190 else { 191 192 void update_KKT_P(csc *KKT, 193 const csc *P, 194 const c_int *PtoKKT, 195 const c_float param1, 196 const c_int *Pdiag_idx, 197 const c_int Pdiag_n) { 198 c_int i, j; // Iterations 199 200 // Update elements of KKT using P 201 for (i = 0; i < P.p[P.n]; i++) { 202 KKT.x[PtoKKT[i]] = P.x[i]; 203 } 204 205 // Update diagonal elements of KKT by adding sigma 206 for (i = 0; i < Pdiag_n; i++) { 207 j = Pdiag_idx[i]; // Extract index of the element on the 208 // diagonal 209 KKT.x[PtoKKT[j]] += param1; 210 } 211 } 212 213 void update_KKT_A(csc *KKT, const csc *A, const c_int *AtoKKT) { 214 c_int i; // Iterations 215 216 // Update elements of KKT using A 217 for (i = 0; i < A.p[A.n]; i++) { 218 KKT.x[AtoKKT[i]] = A.x[i]; 219 } 220 } 221 222 void update_KKT_param2(csc *KKT, const c_float *param2, 223 const c_int *param2toKKT, const c_int m) { 224 c_int i; // Iterations 225 226 // Update elements of KKT using param2 227 for (i = 0; i < m; i++) { 228 KKT.x[param2toKKT[i]] = -param2[i]; 229 } 230 } 231 232 } // EMBEDDED != 1