int main(int argc, char **argv) { FILE * fp; Cone * k; Data * d; Work * w; Sol * sol; Info info = { 0 }; scs_int i; if (openFile(argc, argv, 1, DEMO_PATH, &fp) < 0) return -1; k = scs_calloc(1, sizeof(Cone)); d = scs_calloc(1, sizeof(Data)); sol = scs_calloc(1, sizeof(Sol)); if (readInData(fp, d, k) == -1) { printf("Error reading in data, aborting.\n"); return -1; } fclose(fp); scs_printf("solve once using scs\n"); scs(d, k, sol, &info); if (TEST_WARM_START) { scs_printf("solve %i times with warm-start and (if applicable) factorization caching.\n", NUM_TRIALS); /* warm starts stored in Sol */ w = scs_init(d, k, &info); if (w) { for (i = 0; i < NUM_TRIALS; i++) { /* perturb b and c */ perturbVector(d->b, d->m); perturbVector(d->c, d->n); d->stgs->warm_start = 1; d->stgs->cg_rate = 4; scs_solve(w, d, k, sol, &info); d->stgs->warm_start = 0; d->stgs->cg_rate = 2; scs_solve(w, d, k, sol, &info); } } scs_printf("finished\n"); scs_finish(w); } freeData(d, k); freeSol(sol); return 0; }
/* C = compressed-column form of a triplet matrix T */ cs *SCS(cs_compress)(const cs *T) { scs_int m, n, nz, p, k, *Cp, *Ci, *w, *Ti, *Tj; scs_float *Cx, *Tx; cs *C; m = T->m; n = T->n; Ti = T->i; Tj = T->p; Tx = T->x; nz = T->nz; C = SCS(cs_spalloc)(m, n, nz, Tx != SCS_NULL, 0); /* allocate result */ w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */ if (!C || !w) { return (cs_done(C, w, SCS_NULL, 0)); } /* out of memory */ Cp = C->p; Ci = C->i; Cx = C->x; for (k = 0; k < nz; k++) w[Tj[k]]++; /* column counts */ SCS(cs_cumsum)(Cp, w, n); /* column pointers */ for (k = 0; k < nz; k++) { Ci[p = w[Tj[k]]++] = Ti[k]; /* A(i,j) is the pth entry in C */ if (Cx) { Cx[p] = Tx[k]; } } return (cs_done(C, w, SCS_NULL, 1)); /* success; free w and return C */ }
static int getConeFloatArr(char *key, scs_float **varr, scs_int *vsize, PyObject *cone) { /* get cone['key'] */ scs_int i, n = 0; scs_float *q = SCS_NULL; PyObject *obj = PyDict_GetItemString(cone, key); if (obj) { if (PyList_Check(obj)) { n = (scs_int)PyList_Size(obj); q = scs_calloc(n, sizeof(scs_float)); for (i = 0; i < n; ++i) { PyObject *qi = PyList_GetItem(obj, i); q[i] = (scs_float)PyFloat_AsDouble(qi); } } else if (PyInt_Check(obj) || PyLong_Check(obj) || PyFloat_Check(obj)) { n = 1; q = scs_malloc(sizeof(scs_float)); q[0] = (scs_float)PyFloat_AsDouble(obj); } else { return printErr(key); } if (PyErr_Occurred()) { /* potentially could have been triggered before */ return printErr(key); } } *vsize = n; *varr = q; return 0; }
Priv * initPriv(const AMatrix * A, const Settings * stgs) { Priv * p = scs_calloc(1, sizeof(Priv)); p->p = scs_malloc((A->n) * sizeof(scs_float)); p->r = scs_malloc((A->n) * sizeof(scs_float)); p->Gp = scs_malloc((A->n) * sizeof(scs_float)); p->tmp = scs_malloc((A->m) * sizeof(scs_float)); /* memory for A transpose */ p->At = scs_malloc(sizeof(AMatrix)); p->At->m = A->n; p->At->n = A->m; p->At->i = scs_malloc((A->p[A->n]) * sizeof(scs_int)); p->At->p = scs_malloc((A->m + 1) * sizeof(scs_int)); p->At->x = scs_malloc((A->p[A->n]) * sizeof(scs_float)); transpose(A, p); /* preconditioner memory */ p->z = scs_malloc((A->n) * sizeof(scs_float)); p->M = scs_malloc((A->n) * sizeof(scs_float)); getPreconditioner(A, stgs, p); totalSolveTime = 0; totCgIts = 0; if (!p->p || !p->r || !p->Gp || !p->tmp || !p->At || !p->At->i || !p->At->p || !p->At->x) { freePriv(p); return NULL; } return p; }
static Work * initWork(Data *d, Cone * k) { Work * w = scs_calloc(1, sizeof(Work)); idxint l = d->n + d->m + 1; if (d->VERBOSE) { printInitHeader(d, w, k); } if (!w) { scs_printf("ERROR: allocating work failure\n"); return NULL; } /* allocate workspace: */ w->u = scs_malloc(l * sizeof(pfloat)); w->v = scs_malloc(l * sizeof(pfloat)); w->u_t = scs_malloc(l * sizeof(pfloat)); w->u_prev = scs_malloc(l * sizeof(pfloat)); w->h = scs_malloc((l - 1) * sizeof(pfloat)); w->g = scs_malloc((l - 1) * sizeof(pfloat)); w->pr = scs_malloc(d->m * sizeof(pfloat)); w->dr = scs_malloc(d->n * sizeof(pfloat)); if (!w->u || !w->v || !w->u_t || !w->u_prev || !w->h || !w->g || !w->pr || !w->dr) { scs_printf("ERROR: work memory allocation failure\n"); scs_finish(d, w); return NULL; } if (d->NORMALIZE) { normalizeA(d, w, k); #ifdef EXTRAVERBOSE printArray(w->D, d->m, "D"); scs_printf("norm D = %4f\n", calcNorm(w->D, d->m)); printArray(w->E, d->n, "E"); scs_printf("norm E = %4f\n", calcNorm(w->E, d->n)); #endif } else { w->D = NULL; w->E = NULL; } if (initCone(k) < 0) { scs_printf("ERROR: initCone failure\n"); scs_finish(d, w); return NULL; } w->p = initPriv(d); if (!w->p) { scs_printf("ERROR: initPriv failure\n"); scs_finish(d, w); return NULL; } return w; }
cs *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values, scs_int triplet) { cs *A = (cs *)scs_calloc(1, sizeof(cs)); /* allocate the cs struct */ if (!A) { return (SCS_NULL); } /* out of memory */ A->m = m; /* define dimensions and nzmax */ A->n = n; A->nzmax = nzmax = MAX(nzmax, 1); A->nz = triplet ? 0 : -1; /* allocate triplet or comp.col */ A->p = (scs_int *)scs_malloc((triplet ? nzmax : n + 1) * sizeof(scs_int)); A->i = (scs_int *)scs_malloc(nzmax * sizeof(scs_int)); A->x = values ? (scs_float *)scs_malloc(nzmax * sizeof(scs_float)) : SCS_NULL; return ((!A->p || !A->i || (values && !A->x)) ? SCS(cs_spfree)(A) : A); }
/* gets warm starts from warm dict, doesn't destroy input warm start data */ static scs_int getWarmStart(char * key, scs_float ** x, scs_int l, PyObject * warm) { PyArrayObject *x0 = (PyArrayObject *) PyDict_GetItemString(warm, key); *x = scs_calloc(l, sizeof(scs_float)); if (x0) { if (!PyArray_ISFLOAT(x0) || PyArray_NDIM(x0) != 1 || PyArray_DIM(x0, 0) != l) { PySys_WriteStderr("Error parsing warm-start input\n"); return 0; } else { PyArrayObject * px0 = getContiguous(x0, getFloatType()); memcpy(*x, (scs_float *) PyArray_DATA(px0), l * sizeof(scs_float)); Py_DECREF(px0); return 1; } } return 0; }
cs *SCS(cs_symperm)(const cs *A, const scs_int *pinv, scs_int values) { scs_int i, j, p, q, i2, j2, n, *Ap, *Ai, *Cp, *Ci, *w; scs_float *Cx, *Ax; cs *C; n = A->n; Ap = A->p; Ai = A->i; Ax = A->x; C = SCS(cs_spalloc)(n, n, Ap[n], values && (Ax != SCS_NULL), 0); /* alloc result*/ w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */ if (!C || !w) { return (cs_done(C, w, SCS_NULL, 0)); } /* out of memory */ Cp = C->p; Ci = C->i; Cx = C->x; for (j = 0; j < n; j++) /* count entries in each column of C */ { j2 = pinv ? pinv[j] : j; /* column j of A is column j2 of C */ for (p = Ap[j]; p < Ap[j + 1]; p++) { i = Ai[p]; if (i > j) { continue; } /* skip lower triangular part of A */ i2 = pinv ? pinv[i] : i; /* row i of A is row i2 of C */ w[MAX(i2, j2)]++; /* column count of C */ } } SCS(cs_cumsum)(Cp, w, n); /* compute column pointers of C */ for (j = 0; j < n; j++) { j2 = pinv ? pinv[j] : j; /* column j of A is column j2 of C */ for (p = Ap[j]; p < Ap[j + 1]; p++) { i = Ai[p]; if (i > j) { continue; } /* skip lower triangular part of A*/ i2 = pinv ? pinv[i] : i; /* row i of A is row i2 of C */ Ci[q = w[MAX(i2, j2)]++] = MIN(i2, j2); if (Cx) { Cx[q] = Ax[p]; } } } return (cs_done(C, w, SCS_NULL, 1)); /* success; free workspace, return C */ }
Priv * initPriv(const AMatrix * A, const Settings * stgs) { Priv * p = scs_calloc(1, sizeof(Priv)); scs_int n_plus_m = A->n + A->m; p->P = scs_malloc(sizeof(scs_int) * n_plus_m); p->L = scs_malloc(sizeof(cs)); p->bp = scs_malloc(n_plus_m * sizeof(scs_float)); p->L->m = n_plus_m; p->L->n = n_plus_m; p->L->nz = -1; if (factorize(A, stgs, p) < 0) { freePriv(p); return NULL; } totalSolveTime = 0.0; return p; }
ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsSettings *stgs) { ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork)); scs_int n_plus_m = A->n + A->m; p->P = (scs_int *)scs_malloc(sizeof(scs_int) * n_plus_m); p->L = (cs *)scs_malloc(sizeof(cs)); p->bp = (scs_float *)scs_malloc(n_plus_m * sizeof(scs_float)); p->L->m = n_plus_m; p->L->n = n_plus_m; p->L->nz = -1; if (factorize(A, stgs, p) < 0) { SCS(free_lin_sys_work)(p); return SCS_NULL; } p->total_solve_time = 0.0; return p; }
static void transpose(const AMatrix * A, Priv * p) { scs_int * Ci = p->At->i; scs_int * Cp = p->At->p; scs_float * Cx = p->At->x; scs_int m = A->m; scs_int n = A->n; scs_int * Ap = A->p; scs_int * Ai = A->i; scs_float * Ax = A->x; scs_int i, j, q, *z, c1, c2; #if EXTRAVERBOSE > 0 timer transposeTimer; scs_printf("transposing A\n"); tic(&transposeTimer); #endif z = scs_calloc(m, sizeof(scs_int)); for (i = 0; i < Ap[n]; i++) z[Ai[i]]++; /* row counts */ cs_cumsum(Cp, z, m); /* row pointers */ for (j = 0; j < n; j++) { c1 = Ap[j]; c2 = Ap[j + 1]; for (i = c1; i < c2; i++) { q = z[Ai[i]]; Ci[q] = j; /* place A(i,j) as entry C(j,i) */ Cx[q] = Ax[i]; z[Ai[i]]++; } } scs_free(z); #if EXTRAVERBOSE > 0 scs_printf("finished transposing A, time: %1.2es\n", tocq(&transposeTimer) / 1e3); #endif }
SEXP scsr(SEXP data, SEXP cone, SEXP params) { scs_int len, num_protected = 0; SEXP ret, retnames, infor, xr, yr, sr; /* allocate memory */ Data *d = scs_malloc(sizeof(Data)); Cone *k = scs_malloc(sizeof(Cone)); Settings *stgs = scs_malloc(sizeof(Settings)); AMatrix *A = scs_malloc(sizeof(AMatrix)); Info *info = scs_calloc(1, sizeof(Info)); Sol *sol = scs_calloc(1, sizeof(Sol)); d->b = getFloatVectorFromList(data, "b", &len); d->c = getFloatVectorFromList(data, "c", &len); d->n = getIntFromListWithDefault(data, "n", 0); d->m = getIntFromListWithDefault(data, "m", 0); A->m = d->m; A->n = d->n; A->x = getFloatVectorFromList(data, "Ax", &len); A->i = getIntVectorFromList(data, "Ai", &len); A->p = getIntVectorFromList(data, "Ap", &len); d->A = A; stgs->max_iters = getIntFromListWithDefault(params, "max_iters", MAX_ITERS); stgs->normalize = getIntFromListWithDefault(params, "normalize", NORMALIZE); stgs->verbose = getIntFromListWithDefault(params, "verbose", VERBOSE); stgs->cg_rate = getFloatFromListWithDefault(params, "cg_rate", CG_RATE); stgs->scale = getFloatFromListWithDefault(params, "scale", SCALE); stgs->rho_x = getFloatFromListWithDefault(params, "rho_x", RHO_X); stgs->alpha = getFloatFromListWithDefault(params, "alpha", ALPHA); stgs->eps = getFloatFromListWithDefault(params, "eps", EPS); /* TODO add warm starting */ stgs->warm_start = getIntFromListWithDefault(params, "warm_start", WARM_START); d->stgs = stgs; k->f = getIntFromListWithDefault(cone, "f", 0); k->l = getIntFromListWithDefault(cone, "l", 0); k->ep = getIntFromListWithDefault(cone, "ep", 0); k->ed = getIntFromListWithDefault(cone, "ed", 0); k->q = getIntVectorFromList(cone, "q", &(k->qsize)); k->s = getIntVectorFromList(cone, "s", &(k->ssize)); k->p = getFloatVectorFromList(cone, "p", &(k->psize)); /* solve! */ scs(d, k, sol, info); infor = populateInfoR(info, &num_protected); PROTECT(ret = NEW_LIST(4)); num_protected++; PROTECT(retnames = NEW_CHARACTER(4)); num_protected++; SET_NAMES(ret, retnames); xr = floatVec2R(d->n, sol->x); num_protected++; yr = floatVec2R(d->m, sol->y); num_protected++; sr = floatVec2R(d->m, sol->s); num_protected++; SET_STRING_ELT(retnames, 0, mkChar("x")); SET_VECTOR_ELT(ret, 0, xr); SET_STRING_ELT(retnames, 1, mkChar("y")); SET_VECTOR_ELT(ret, 1, yr); SET_STRING_ELT(retnames, 2, mkChar("s")); SET_VECTOR_ELT(ret, 2, sr); SET_STRING_ELT(retnames, 3, mkChar("info")); SET_VECTOR_ELT(ret, 3, infor); /* free memory */ scs_free(info); scs_free(d); scs_free(k); scs_free(stgs); scs_free(A); freeSol(sol); UNPROTECT(num_protected); return ret; }
/* wrapper for calloc */ static void *cs_calloc(scs_int n, scs_int size) { return (scs_calloc(n, size)); }
static PyObject *csolve(PyObject *self, PyObject *args, PyObject *kwargs) { /* data structures for arguments */ PyArrayObject *Ax, *Ai, *Ap, *c, *b; PyObject *cone, *warm = SCS_NULL; PyObject *verbose = SCS_NULL; PyObject *normalize = SCS_NULL; /* get the typenum for the primitive scs_int and scs_float types */ int scs_intType = getIntType(); int scs_floatType = getFloatType(); struct ScsPyData ps = { SCS_NULL, SCS_NULL, SCS_NULL, SCS_NULL, SCS_NULL, }; /* scs data structures */ Data *d = scs_calloc(1, sizeof(Data)); Cone *k = scs_calloc(1, sizeof(Cone)); AMatrix *A; Sol sol = {0}; Info info; char *kwlist[] = {"shape", "Ax", "Ai", "Ap", "b", "c", "cone", "warm", "verbose", "normalize", "max_iters", "scale", "eps", "cg_rate", "alpha", "rho_x", SCS_NULL}; /* parse the arguments and ensure they are the correct type */ #ifdef DLONG #ifdef FLOAT char *argparse_string = "(ll)O!O!O!O!O!O!|O!O!O!lfffff"; char *outarg_string = "{s:l,s:l,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:s}"; #else char *argparse_string = "(ll)O!O!O!O!O!O!|O!O!O!lddddd"; char *outarg_string = "{s:l,s:l,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:s}"; #endif #else #ifdef FLOAT char *argparse_string = "(ii)O!O!O!O!O!O!|O!O!O!ifffff"; char *outarg_string = "{s:i,s:i,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:s}"; #else char *argparse_string = "(ii)O!O!O!O!O!O!|O!O!O!iddddd"; char *outarg_string = "{s:i,s:i,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:s}"; #endif #endif npy_intp veclen[1]; PyObject *x, *y, *s, *returnDict, *infoDict; d->stgs = scs_malloc(sizeof(Settings)); /* set defaults */ setDefaultSettings(d); if (!PyArg_ParseTupleAndKeywords( args, kwargs, argparse_string, kwlist, &(d->m), &(d->n), &PyArray_Type, &Ax, &PyArray_Type, &Ai, &PyArray_Type, &Ap, &PyArray_Type, &b, &PyArray_Type, &c, &PyDict_Type, &cone, &PyDict_Type, &warm, &PyBool_Type, &verbose, &PyBool_Type, &normalize, &(d->stgs->max_iters), &(d->stgs->scale), &(d->stgs->eps), &(d->stgs->cg_rate), &(d->stgs->alpha), &(d->stgs->rho_x))) { PySys_WriteStderr("error parsing inputs\n"); return SCS_NULL; } if (d->m < 0) { PyErr_SetString(PyExc_ValueError, "m must be a positive integer"); return SCS_NULL; } if (d->n < 0) { PyErr_SetString(PyExc_ValueError, "n must be a positive integer"); return SCS_NULL; } /* set A */ if (!PyArray_ISFLOAT(Ax) || PyArray_NDIM(Ax) != 1) { return finishWithErr(d, k, &ps, "Ax must be a numpy array of floats"); } if (!PyArray_ISINTEGER(Ai) || PyArray_NDIM(Ai) != 1) { return finishWithErr(d, k, &ps, "Ai must be a numpy array of ints"); } if (!PyArray_ISINTEGER(Ap) || PyArray_NDIM(Ap) != 1) { return finishWithErr(d, k, &ps, "Ap must be a numpy array of ints"); } ps.Ax = getContiguous(Ax, scs_floatType); ps.Ai = getContiguous(Ai, scs_intType); ps.Ap = getContiguous(Ap, scs_intType); A = scs_malloc(sizeof(AMatrix)); A->n = d->n; A->m = d->m; A->x = (scs_float *)PyArray_DATA(ps.Ax); A->i = (scs_int *)PyArray_DATA(ps.Ai); A->p = (scs_int *)PyArray_DATA(ps.Ap); d->A = A; /*d->Anz = d->Ap[d->n]; */ /*d->Anz = PyArray_DIM(Ai,0); */ /* set c */ if (!PyArray_ISFLOAT(c) || PyArray_NDIM(c) != 1) { return finishWithErr( d, k, &ps, "c must be a dense numpy array with one dimension"); } if (PyArray_DIM(c, 0) != d->n) { return finishWithErr(d, k, &ps, "c has incompatible dimension with A"); } ps.c = getContiguous(c, scs_floatType); d->c = (scs_float *)PyArray_DATA(ps.c); /* set b */ if (!PyArray_ISFLOAT(b) || PyArray_NDIM(b) != 1) { return finishWithErr( d, k, &ps, "b must be a dense numpy array with one dimension"); } if (PyArray_DIM(b, 0) != d->m) { return finishWithErr(d, k, &ps, "b has incompatible dimension with A"); } ps.b = getContiguous(b, scs_floatType); d->b = (scs_float *)PyArray_DATA(ps.b); if (getPosIntParam("f", &(k->f), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field f"); } if (getPosIntParam("l", &(k->l), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field l"); } if (getConeArrDim("q", &(k->q), &(k->qsize), cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field q"); } if (getConeArrDim("s", &(k->s), &(k->ssize), cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field s"); } if (getConeFloatArr("p", &(k->p), &(k->psize), cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field p"); } if (getPosIntParam("ep", &(k->ep), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field ep"); } if (getPosIntParam("ed", &(k->ed), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field ed"); } d->stgs->verbose = verbose ? (scs_int)PyObject_IsTrue(verbose) : VERBOSE; d->stgs->normalize = normalize ? (scs_int)PyObject_IsTrue(normalize) : NORMALIZE; if (d->stgs->max_iters < 0) { return finishWithErr(d, k, &ps, "max_iters must be positive"); } if (d->stgs->scale < 0) { return finishWithErr(d, k, &ps, "scale must be positive"); } if (d->stgs->eps < 0) { return finishWithErr(d, k, &ps, "eps must be positive"); } if (d->stgs->cg_rate < 0) { return finishWithErr(d, k, &ps, "cg_rate must be positive"); } if (d->stgs->alpha < 0) { return finishWithErr(d, k, &ps, "alpha must be positive"); } if (d->stgs->rho_x < 0) { return finishWithErr(d, k, &ps, "rho_x must be positive"); } /* parse warm start if set */ d->stgs->warm_start = WARM_START; if (warm) { d->stgs->warm_start = getWarmStart("x", &(sol.x), d->n, warm); d->stgs->warm_start |= getWarmStart("y", &(sol.y), d->m, warm); d->stgs->warm_start |= getWarmStart("s", &(sol.s), d->m, warm); } Py_BEGIN_ALLOW_THREADS /* Solve! */ scs(d, k, &sol, &info); Py_END_ALLOW_THREADS /* create output (all data is *deep copied*) */ /* x */ /* matrix *x; */ /* if(!(x = Matrix_New(n,1,DOUBLE))) */ /* return PyErr_NoMemory(); */ /* memcpy(MAT_BUFD(x), mywork->x, n*sizeof(scs_float)); */ veclen[0] = d->n; x = PyArray_SimpleNewFromData(1, veclen, scs_floatType, sol.x); PyArray_ENABLEFLAGS((PyArrayObject *)x, NPY_ARRAY_OWNDATA); /* y */ /* matrix *y; */ /* if(!(y = Matrix_New(p,1,DOUBLE))) */ /* return PyErr_NoMemory(); */ /* memcpy(MAT_BUFD(y), mywork->y, p*sizeof(scs_float)); */ veclen[0] = d->m; y = PyArray_SimpleNewFromData(1, veclen, scs_floatType, sol.y); PyArray_ENABLEFLAGS((PyArrayObject *)y, NPY_ARRAY_OWNDATA); /* s */ /* matrix *s; */ /* if(!(s = Matrix_New(m,1,DOUBLE))) */ /* return PyErr_NoMemory(); */ /* memcpy(MAT_BUFD(s), mywork->s, m*sizeof(scs_float)); */ veclen[0] = d->m; s = PyArray_SimpleNewFromData(1, veclen, scs_floatType, sol.s); PyArray_ENABLEFLAGS((PyArrayObject *)s, NPY_ARRAY_OWNDATA); infoDict = Py_BuildValue( outarg_string, "statusVal", (scs_int)info.statusVal, "iter", (scs_int)info.iter, "pobj", (scs_float)info.pobj, "dobj", (scs_float)info.dobj, "resPri", (scs_float)info.resPri, "resDual", (scs_float)info.resDual, "relGap", (scs_float)info.relGap, "resInfeas", (scs_float)info.resInfeas, "resUnbdd", (scs_float)info.resUnbdd, "solveTime", (scs_float)(info.solveTime), "setupTime", (scs_float)(info.setupTime), "status", info.status); returnDict = Py_BuildValue("{s:O,s:O,s:O,s:O}", "x", x, "y", y, "s", s, "info", infoDict); /* give up ownership to the return dictionary */ Py_DECREF(x); Py_DECREF(y); Py_DECREF(s); Py_DECREF(infoDict); /* no longer need pointers to arrays that held primitives */ freePyData(d, k, &ps); return returnDict; }
int main(int argc, char **argv) { scs_int n, m, col_nnz, nnz, i, q_total, q_num_rows, max_q; Cone * k; Data * d; Sol * sol, * opt_sol; Info info = { 0 }; scs_float p_f, p_l; int seed = 0; /* default parameters */ p_f = 0.1; p_l = 0.3; seed = time(SCS_NULL); switch (argc) { case 5: seed = atoi(argv[4]); /* no break */ case 4: p_f = atof(argv[2]); p_l = atof(argv[3]); /* no break */ case 2: n = atoi(argv[1]); break; default: scs_printf("usage:\t%s n p_f p_l s\n" "\tcreates an SOCP with n variables where p_f fraction of rows correspond\n" "\tto equality constraints, p_l fraction of rows correspond to LP constraints,\n" "\tand the remaining percentage of rows are involved in second-order\n" "\tcone constraints. the random number generator is seeded with s.\n" "\tnote that p_f + p_l should be less than or equal to 1, and that\n" "\tp_f should be less than .33, since that corresponds to as many equality\n" "\tconstraints as variables.\n", argv[0]); scs_printf("\nusage:\t%s n p_f p_l\n" "\tdefaults the seed to the system time\n", argv[0]); scs_printf("\nusage:\t%s n\n" "\tdefaults to using p_f = 0.1 and p_l = 0.3\n", argv[0]); return 0; } srand(seed); scs_printf("seed : %i\n", seed); k = scs_calloc(1, sizeof(Cone)); d = scs_calloc(1, sizeof(Data)); d->stgs = scs_calloc(1, sizeof(Settings)); sol = scs_calloc(1, sizeof(Sol)); opt_sol = scs_calloc(1, sizeof(Sol)); m = 3 * n; col_nnz = (int) ceil(sqrt(n)); nnz = n * col_nnz; max_q = (scs_int) ceil(3 * n / log(3 * n)); if (p_f + p_l > 1.0) { printf("error: p_f + p_l > 1.0!\n"); return 1; } k->f = (scs_int) floor(3 * n * p_f); k->l = (scs_int) floor(3 * n * p_l); k->qsize = 0; q_num_rows = 3 * n - k->f - k->l; k->q = scs_malloc(q_num_rows * sizeof(scs_int)); while (q_num_rows > max_q) { int size; size = (rand() % max_q) + 1; k->q[k->qsize] = size; k->qsize++; q_num_rows -= size; } if (q_num_rows > 0) { k->q[k->qsize] = q_num_rows; k->qsize++; } q_total = 0; for (i = 0; i < k->qsize; i++) { q_total += k->q[i]; } k->s = SCS_NULL; k->ssize = 0; k->ep = 0; k->ed = 0; scs_printf("\nA is %ld by %ld, with %ld nonzeros per column.\n", (long) m, (long) n, (long) col_nnz); scs_printf("A has %ld nonzeros (%f%% dense).\n", (long) nnz, 100 * (scs_float) col_nnz / m); scs_printf("Nonzeros of A take %f GB of storage.\n", ((scs_float) nnz * sizeof(scs_float)) / POWF(2, 30)); scs_printf("Row idxs of A take %f GB of storage.\n", ((scs_float) nnz * sizeof(scs_int)) / POWF(2, 30)); scs_printf("Col ptrs of A take %f GB of storage.\n\n", ((scs_float) n * sizeof(scs_int)) / POWF(2, 30)); printf("Cone information:\n"); printf("Zero cone rows: %ld\n", (long) k->f); printf("LP cone rows: %ld\n", (long) k->l); printf("Number of second-order cones: %ld, covering %ld rows, with sizes\n[", (long) k->qsize, (long) q_total); for (i = 0; i < k->qsize; i++) { printf("%ld, ", (long) k->q[i]); } printf("]\n"); printf("Number of rows covered is %ld out of %ld.\n\n", (long) (q_total + k->f + k->l), (long) m); /* set up SCS structures */ d->m = m; d->n = n; genRandomProbData(nnz, col_nnz, d, k, opt_sol); setDefaultSettings(d); scs_printf("true pri opt = %4f\n", innerProd(d->c, opt_sol->x, d->n)); scs_printf("true dua opt = %4f\n", -innerProd(d->b, opt_sol->y, d->m)); /* solve! */ scs(d, k, sol, &info); scs_printf("true pri opt = %4f\n", innerProd(d->c, opt_sol->x, d->n)); scs_printf("true dua opt = %4f\n", -innerProd(d->b, opt_sol->y, d->m)); if (sol->x) { scs_printf("scs pri obj= %4f\n", innerProd(d->c, sol->x, d->n)); } if (sol->y) { scs_printf("scs dua obj = %4f\n", -innerProd(d->b, sol->y, d->m)); } freeData(d, k); freeSol(sol); freeSol(opt_sol); return 0; }