Using the C interfaceFor the most flexible and best performing solver, use C directly. Once you have generated code online, do the following.
Complete exampleThis is a complete C file that uses a CVXGEN solver. It is similar to the testsolver.c file produced by CVXGEN. // Load and instantiate global namespaces with relevant data and working space. #include "solver.h" Vars vars; Params params; Workspace work; Settings settings; void load_data(Params params) { // In this function, load all problem instance data. params.A[i] = ...; ... } void use_solution(Vars vars) { // In this function, use the optimization result. ... = vars.x[i]; } int main(int argc, char **argv) { set_defaults(); // Set basic algorithm parameters. setup_indexing(); for (;;) { // Main control loop. load_data(params); // Solve our problem at high speed! num_iters = solve(); // Recommended: check work.converged == 1. use_solution(vars) } } Now we will look at the parts of this example in more detail. Allocating memoryYou need to allocate space for four structures, all defined in solver.h. No other space in memory is required or used. Thus, the exact memory usage for each solver may be found ahead of time. The recommended approach is to statically allocate these structures as global variables. They are then treated as namespaces in the CVXGEN code. In the example above, this is done with the lines Vars vars; Params params; Workspace work; Settings settings; In a future revision, these may be passed between functions to allow more flexibility. Contact me if you have thoughts about this. Compilers and librariesWe strongly recommend you use the latest possible version of gcc, for best performance. For some examples and architectures, version 4.3 can produce code three times faster than version 4.0, with version 4.4 another 15% faster. It is worth experimenting with compiler options as well; start with -Os. CVXGEN uses the stdio and math libraries by default. The only functions used from each of these are the printf and sqrt functions, respectively — and both are used in verbose mode only. To completely remove all library dependencies, add
#define ZERO_LIBRARY_MODE
to solver.h. This will disable verbose output of solver progress and other reporting, but will not affect core solver functionality. Setting parameters and retrieving variablesAll data in CVXGEN are stored in flat arrays, in column-major form with zero-based indices. (Thus, entries 0–3, say, are the first column of a matrix with 4 rows.) In particular, for a parameter matrix , entry is stored in params.A[(i-1) + (j-1)*m)]. For consistency, the same applies for vectors, and even scalars. Symmetric matrices are stored in exactly the same way, but only the diagonal entries are stored for diagonal matrices. Here are some examples. // Set all entries of a 5x3 matrix A. for (int i = 0; i < 5; i++) for (int j = 0; i < 3; i++) params.A[i+j*5] = ...; // Set the scalar parameter lambda. Note the 0 array index. params.lambda[0] = ...; // Variables are retrieved in the same way, from the vars structure. for (int i = 0; i < n; i++) printf(" %9.4f\n", vars.x[i]); Parameter checkingFor performance and embedding reasons, no checks will be performed on parameters of sizes, shapes or attributes. CVXGEN may do something useful if you violate your parameter specifications, but it's unlikely, and definitely not recommended or guaranteed. Indexed parameters or variablesIn your CVXGEN problem specification, you may have specified indexed parameters or variables, such as parameters
y[i] (3), i=1..3 end You can provide data for these parameters, in C, in two different ways. With the first, an underscore separates the index and the variable name. With the second, we use two indices to index into the parameter, and then into the parameter's data array. The latter is more convenient for use with loops. // Assign initial parameters, option 1. params.y_1[j] = ...; // Assign initial parameters, option 2. Equivalent. setup_indexing(); // call this once, at set up, before using option 2. params.y[1][j] = ...; Modifying solver settingsIf you want to modify solver behavior, you can change the settings. See more information about the settings. settings.verbose = 0; // disable output of solver progress. settings.max_iters = 10; // reduce the maximum iteration count, from 25. settings.eps = 0.1; // reduce the required objective tolerance, from 1e-6. settings.eps = 1e-2; // reduce the required residual tolerances, from 1e-4. // Solve with these settings. solve(); |