1 module types;
2 
3 nothrow @nogc extern(C):
4 
5 import glob_opts;
6 import constants;
7 import qdldl_types; // for QDLDL_int and others
8 
9 
10 version(PRINTING){
11   import core.stdc.stdio;
12 } // ifdef PRINTING
13 
14 /******************
15 * Internal types *
16 ******************/
17 
18 /**
19  *  Matrix in compressed-column form.
20  *  The structure is used internally to store matrices in the triplet form as well,
21  *  but the API requires that the matrices are in the CSC format.
22  */
23 struct csc {
24   
25   c_int    nzmax; ///< maximum number of entries
26   c_int    m;     ///< number of rows
27   c_int    n;     ///< number of columns
28   c_int   *p;     ///< column pointers (size n+1); col indices (size nzmax) start from 0 when using triplet format (direct KKT matrix formation)
29   c_int   *i;     ///< row indices, size nzmax starting from 0
30   c_float *x;     ///< numerical values, size nzmax
31   c_int    nz;    ///< number of entries in triplet matrix, -1 for csc  
32 };
33 
34 /**
35  * Linear system solver structure (sublevel objects initialize it differently)
36  */
37 
38 //typedef struct linsys_solver LinSysSolver;
39 //alias linsys_solver = LinSysSolver;
40 alias LinSysSolver = linsys_solver;  // todo : check it
41 
42 /**
43  * OSQP Timer for statistics
44  */
45 
46 
47 /*********************************
48 * Timer Structs and Functions * *
49 *********************************/
50 
51 /*! \cond PRIVATE */
52 
53 version(PROFILING){
54 
55 // Windows
56 version(Windows){
57 
58   // Some R packages clash with elements
59   // of the windows.h header, so use a
60 version(R_LANG){
61 //#define NOGDI
62 enum bool NOGDI = true; // todo : test it
63 }
64 
65 //#   include <windows.h>
66 // import windows; // todo
67 
68 struct OSQPTimer {
69   ulong tic;
70   ulong toc;
71   ulong freq;
72 };
73 
74 } else version(OSX)
75 {
76     //#   include <mach/mach_time.h>
77     import core.time: mach_timebase_info_data_t;  // todo
78 
79     /* Use MAC OSX  mach_time for timing */
80     struct OSQPTimer {
81       ulong                  tic;
82       ulong                  toc;
83       mach_timebase_info_data_t tinfo;
84     };
85 }
86 else version(linux)
87 {
88 
89     /* Use POSIX clock_gettime() for timing on non-Windows machines */
90     import core.sys.posix.sys.time;
91 
92     struct OSQPTimer {
93       timespec tic;
94       timespec toc;
95     };
96   }
97 }/* END #ifdef PROFILING */
98 
99 /**
100  * Problem scaling matrices stored as vectors
101  */
102 struct OSQPScaling {
103   c_float  c;    ///< cost function scaling
104   c_float *D;    ///< primal variable scaling
105   c_float *E;    ///< dual variable scaling
106   c_float  cinv; ///< cost function rescaling
107   c_float *Dinv; ///< primal variable rescaling
108   c_float *Einv; ///< dual variable rescaling
109 };
110 
111 /**
112  * Solution structure
113  */
114 struct OSQPSolution{
115   c_float *x; ///< primal solution
116   c_float *y; ///< Lagrange multiplier associated to \f$l <= Ax <= u\f$
117 };
118 
119 
120 /**
121  * Solver return information
122  */
123 struct OSQPInfo{
124   c_int iter;          ///< number of iterations taken
125   char [32] status;    ///< status string, e.g. 'solved'
126   c_int status_val;    ///< status as c_int, defined in constants.h
127 
128 version(EMBEDDED){}
129 else {
130   c_int status_polish; ///< polish status: successful (1), unperformed (0), (-1) unsuccessful
131 } // ifndef EMBEDDED
132 
133   c_float obj_val;     ///< primal objective
134   c_float pri_res;     ///< norm of primal residual
135   c_float dua_res;     ///< norm of dual residual
136 
137 version(PROFILING){
138   c_float setup_time;  ///< time taken for setup phase (seconds)
139   c_float solve_time;  ///< time taken for solve phase (seconds)
140   c_float update_time; ///< time taken for update phase (seconds)
141   c_float polish_time; ///< time taken for polish phase (seconds)
142   c_float run_time;    ///< total time  (seconds)
143 } // ifdef PROFILING
144 
145 version(EMBEDDED_1){}
146 else { // if EMBEDDED != 1
147   c_int   rho_updates;  ///< number of rho updates
148   c_float rho_estimate; ///< best rho estimate so far from residuals
149 }
150 };
151 
152 version (EMBEDDED){}
153 else {
154 
155 /**
156  * Polish structure
157  */
158 struct OSQPPolish{
159   csc *Ared;          ///< active rows of A
160   ///<    Ared = vstack[Alow, Aupp]
161   c_int    n_low;     ///< number of lower-active rows
162   c_int    n_upp;     ///< number of upper-active rows
163   c_int   *A_to_Alow; ///< Maps indices in A to indices in Alow
164   c_int   *A_to_Aupp; ///< Maps indices in A to indices in Aupp
165   c_int   *Alow_to_A; ///< Maps indices in Alow to indices in A
166   c_int   *Aupp_to_A; ///< Maps indices in Aupp to indices in A
167   c_float *x;         ///< optimal x-solution obtained by polish
168   c_float *z;         ///< optimal z-solution obtained by polish
169   c_float *y;         ///< optimal y-solution obtained by polish
170   c_float  obj_val;   ///< objective value at polished solution
171   c_float  pri_res;   ///< primal residual at polished solution
172   c_float  dua_res;   ///< dual residual at polished solution
173 };
174 } // !version (EMBEDDED)
175 
176 
177 /**********************************
178 * Main structures and Data Types *
179 **********************************/
180 
181 /**
182  * Data structure
183  */
184 struct OSQPData{
185   c_int    n; ///< number of variables n
186   c_int    m; ///< number of constraints m
187   csc     *P; ///< the upper triangular part of the quadratic cost matrix P in csc format (size n x n).
188   csc     *A; ///< linear constraints matrix A in csc format (size m x n)
189   c_float *q; ///< dense array for linear part of cost function (size n)
190   c_float *l; ///< dense array for lower bound (size m)
191   c_float *u; ///< dense array for upper bound (size m)
192 };
193 
194 
195 /**
196  * Settings struct
197  */
198 struct OSQPSettings{
199   c_float rho;                    ///< ADMM step rho
200   c_float sigma;                  ///< ADMM step sigma
201   c_int   scaling;                ///< heuristic data scaling iterations; if 0, then disabled.
202 
203 version(EMBEDDED_1){}
204 else { // if EMBEDDED != 1
205 
206   c_int   adaptive_rho;           ///< boolean, is rho step size adaptive?
207   c_int   adaptive_rho_interval;  ///< number of iterations between rho adaptations; if 0, then it is automatic
208   c_float adaptive_rho_tolerance; ///< tolerance X for adapting rho. The new rho has to be X times larger or 1/X times smaller than the current one to trigger a new factorization.
209 version(PROFILING){
210   c_float adaptive_rho_fraction;  ///< interval for adapting rho (fraction of the setup time)
211 } // Profiling
212 }
213 
214   c_int                   max_iter;      ///< maximum number of iterations
215   c_float                 eps_abs;       ///< absolute convergence tolerance
216   c_float                 eps_rel;       ///< relative convergence tolerance
217   c_float                 eps_prim_inf;  ///< primal infeasibility tolerance
218   c_float                 eps_dual_inf;  ///< dual infeasibility tolerance
219   c_float                 alpha;         ///< relaxation parameter
220   linsys_solver_type      linsys_solver; ///< linear system solver to use
221 
222 version(EMBEDDED){}
223 else { // ifndef EMBEDDED
224   c_float delta;                         ///< regularization parameter for polishing
225   c_int   polish;                        ///< boolean, polish ADMM solution
226   c_int   polish_refine_iter;            ///< number of iterative refinement steps in polishing
227 
228   c_int verbose;                         ///< boolean, write out progress
229 } // ifndef EMBEDDED
230 
231   c_int scaled_termination;              ///< boolean, use scaled termination criteria
232   c_int check_termination;               ///< integer, check termination interval; if 0, then termination checking is disabled
233   c_int warm_start;                      ///< boolean, warm start
234 
235 version(PROFILING){
236   c_float time_limit;                    ///< maximum number of seconds allowed to solve the problem; if 0, then disabled
237 } // ifdef PROFILING
238 };
239 
240 
241 /**
242  * OSQP Workspace
243  */
244 struct OSQPWorkspace{
245   /// Problem data to work on (possibly scaled)
246   OSQPData *data;
247 
248   /// Linear System solver structure
249   LinSysSolver *linsys_solver;
250 
251 version(EMBEDDED){}
252 else { // ifndef EMBEDDED
253   /// Polish structure
254   OSQPPolish *pol;
255 } // ifndef EMBEDDED
256 
257   /**
258    * @name Vector used to store a vectorized rho parameter
259    * @{
260    */
261   c_float *rho_vec;     ///< vector of rho values
262   c_float *rho_inv_vec; ///< vector of inv rho values
263 
264   /** @} */
265 
266 version(EMBEDDED_1){}
267 else { // if EMBEDDED != 1
268   c_int *constr_type; ///< Type of constraints: loose (-1), equality (1), inequality (0)
269 } // if EMBEDDED != 1
270 
271   /**
272    * @name Iterates
273    * @{
274    */
275   c_float *x;        ///< Iterate x
276   c_float *y;        ///< Iterate y
277   c_float *z;        ///< Iterate z
278   c_float *xz_tilde; ///< Iterate xz_tilde
279 
280   c_float *x_prev;   ///< Previous x
281 
282   /**< NB: Used also as workspace vector for dual residual */
283   c_float *z_prev;   ///< Previous z
284 
285   /**< NB: Used also as workspace vector for primal residual */
286 
287   /**
288    * @name Primal and dual residuals workspace variables
289    *
290    * Needed for residuals computation, tolerances computation,
291    * approximate tolerances computation and adapting rho
292    * @{
293    */
294   c_float *Ax;  ///< scaled A * x
295   c_float *Px;  ///< scaled P * x
296   c_float *Aty; ///< scaled A * x
297 
298   /** @} */
299 
300   /**
301    * @name Primal infeasibility variables
302    * @{
303    */
304   c_float *delta_y;   ///< difference between consecutive dual iterates
305   c_float *Atdelta_y; ///< A' * delta_y
306 
307   /** @} */
308 
309   /**
310    * @name Dual infeasibility variables
311    * @{
312    */
313   c_float *delta_x;  ///< difference between consecutive primal iterates
314   c_float *Pdelta_x; ///< P * delta_x
315   c_float *Adelta_x; ///< A * delta_x
316 
317   /** @} */
318 
319   /**
320    * @name Temporary vectors used in scaling
321    * @{
322    */
323 
324   c_float *D_temp;   ///< temporary primal variable scaling vectors
325   c_float *D_temp_A; ///< temporary primal variable scaling vectors storing norms of A columns
326   c_float *E_temp;   ///< temporary constraints scaling vectors storing norms of A' columns
327 
328 
329   /** @} */
330 
331   OSQPSettings *settings; ///< problem settings
332   OSQPScaling  *scaling;  ///< scaling vectors
333   OSQPSolution *solution; ///< problem solution
334   OSQPInfo     *info;     ///< solver information
335 
336 version(PROFILING){
337   OSQPTimer *timer;       ///< timer object
338 
339   /// flag indicating whether the solve function has been run before
340   c_int first_run;
341 
342   /// flag indicating whether the update_time should be cleared
343   c_int clear_update_time;
344 
345   /// flag indicating that osqp_update_rho is called from osqp_solve function
346   c_int rho_update_from_solve;
347 } // ifdef PROFILING
348 
349 version(PRINTING){
350   c_int summary_printed; ///< Has last summary been printed? (true/false)
351 } // ifdef PRINTING
352 
353 };
354 
355 
356 /**
357  * Define linsys_solver prototype structure
358  *
359  * NB: The details are defined when the linear solver is initialized depending
360  *      on the choice
361  */
362 alias solve_t = c_int function(LinSysSolver* self, c_float* b);
363 alias update_matrices_t = c_int function(LinSysSolver* s, const csc* P, const csc* A);
364 alias update_rho_vec_t = c_int function(LinSysSolver* s, const c_float* rho_vec);
365 alias free_t = void function(LinSysSolver* self);
366 
367 struct linsys_solver {
368   linsys_solver_type type;                 ///< linear system solver type functions
369   //c_int (*solve)(LinSysSolver *self,
370   //               c_float      *b);              ///< solve linear system
371   solve_t solve;
372 
373 version(EMBEDDED){}
374 else { // ifndef EMBEDDED
375   //void (*free)(LinSysSolver *self);             ///< free linear system solver (only in desktop version)
376   free_t free; // todo
377 } // ifndef EMBEDDED
378 
379 version(EMBEDDED_1){}
380 else { // ifndef EMBEDDED
381   //c_int (*update_matrices)(LinSysSolver *s,
382   //                         const csc *P,            ///< update matrices P
383   //                         const csc *A);           //   and A in the solver
384   update_matrices_t update_matrices;
385 
386   //c_int (*update_rho_vec)(LinSysSolver  *s,
387   //                        const c_float *rho_vec);  ///< Update rho_vec
388   update_rho_vec_t update_rho_vec;
389 } // if EMBEDDED != 1
390 
391 version(EMBEDDED){}
392 else { // ifndef EMBEDDED
393   c_int nthreads; ///< number of threads active
394 } // ifndef EMBEDDED
395 };