/* 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; }
static PyObject *csolve(PyObject* self, PyObject *args, PyObject *kwargs) { /* Expects a function call * sol = csolve((m,n,p),c,Gx,Gi,Gp,h,dims,Ax,Ai,Ap,b,verbose) * where * * the triple (m,n,p) corresponds to: * `m`: the rows of G * `n`: the cols of G and A, must agree with the length of c * `p`: the rows of A * `c` is a Numpy array of doubles * "G" is a sparse matrix in column compressed storage. "Gx" are the values, * "Gi" are the rows, and "Gp" are the column pointers. * `Gx` is a Numpy array of doubles * `Gi` is a Numpy array of ints * `Gp` is a Numpy array of ints * `h` is a Numpy array * `dims` is a dictionary with * `dims['l']` an integer specifying the dimension of positive orthant cone * `dims['q']` an *list* specifying dimensions of second-order cones * * "A" is an optional sparse matrix in column compressed storage. "Ax" are * the values, "Ai" are the rows, and "Ap" are the column pointers. * `Ax` is a Numpy array of doubles * `Ai` is a Numpy array of ints * `Ap` is a Numpy array of ints * `b` is an optional argument, which is a Numpy array of doubles * `verbose` is an optional bool signaling whether to print info * * This call will solve the problem * * minimize c'*x * subject to A*x = b * h - G*x \in K * * The code returns a Python dictionary with five keys, 'x', 'y', 'info', 's', * and 'z'. These correspond to the following: * * `x`: primal variables * `y`: dual variables for equality constraints * `s`: slacks for Gx + s <= h, s \in K * `z`: dual variables for inequality constraints s \in K * `info`: another dictionary with the following fields: * exitflag: 0=OPTIMAL, 1=PRIMAL INFEASIBLE, 2=DUAL INFEASIBLE, -1=MAXIT REACHED * infostring: gives information about the status of solution * pcost: value of primal objective * dcost: value of dual objective * pres: primal residual on inequalities and equalities * dres: dual residual * pinf: primal infeasibility measure * dinf: dual infeasibility measure * pinfres: NaN * dinfres: 3.9666e+15 * gap: duality gap * relgap: relative duality gap * r0: ??? * numerr: numerical error? * iter: number of iterations * timing: dictionary with timing information */ /* data structures for arguments */ //matrix *c, *h, *b = NULL; //spmatrix *G, *A = NULL; PyArrayObject *Gx, *Gi, *Gp, *c, *h; PyArrayObject *Ax = NULL; PyArrayObject *Ai = NULL; PyArrayObject *Ap = NULL; PyArrayObject *b = NULL; PyObject *dims, *verbose = NULL; idxint n; // number or variables idxint m; // number of conic variables idxint p = 0; // number of equality constraints idxint ncones = 0; // number of cones idxint numConicVariables = 0; /* ECOS data structures */ idxint l = 0; idxint *q = NULL; pfloat *Gpr = NULL; idxint *Gjc = NULL; idxint *Gir = NULL; pfloat *Apr = NULL; idxint *Ajc = NULL; idxint *Air = NULL; pfloat *cpr = NULL; pfloat *hpr = NULL; pfloat *bpr = NULL; pwork* mywork; idxint i; static char *kwlist[] = {"shape", "c", "Gx", "Gi", "Gp", "h", "dims", "Ax", "Ai", "Ap", "b", "verbose", NULL}; // parse the arguments and ensure they are the correct type #ifdef DLONG static char *argparse_string = "(lll)O!O!O!O!O!O!|O!O!O!O!O!"; #else static char *argparse_string = "(iii)O!O!O!O!O!O!|O!O!O!O!O!"; #endif if( !PyArg_ParseTupleAndKeywords(args, kwargs, argparse_string, kwlist, &m, &n, &p, &PyArray_Type, &c, &PyArray_Type, &Gx, &PyArray_Type, &Gi, &PyArray_Type, &Gp, &PyArray_Type, &h, &PyDict_Type, &dims, &PyArray_Type, &Ax, &PyArray_Type, &Ai, &PyArray_Type, &Ap, &PyArray_Type, &b, &PyBool_Type, &verbose) ) { return NULL; } if (m < 0) { PyErr_SetString(PyExc_ValueError, "m must be a positive integer"); return NULL; } if (n < 0) { PyErr_SetString(PyExc_ValueError, "n must be a positive integer"); return NULL; } if (p < 0) { PyErr_SetString(PyExc_ValueError, "p must be a positive integer"); return NULL; } /* get the typenum for the primitive int and double types */ int intType = getIntType(); int doubleType = getDoubleType(); /* set G */ if( !PyArray_ISFLOAT(Gx) || PyArray_NDIM(Gx) != 1) { PyErr_SetString(PyExc_TypeError, "Gx must be a numpy array of floats"); return NULL; } if( !PyArray_ISINTEGER(Gi) || PyArray_NDIM(Gi) != 1) { PyErr_SetString(PyExc_TypeError, "Gi must be a numpy array of ints"); return NULL; } if( !PyArray_ISINTEGER(Gp) || PyArray_NDIM(Gp) != 1) { PyErr_SetString(PyExc_TypeError, "Gp must be a numpy array of ints"); return NULL; } PyArrayObject *Gx_arr = getContiguous(Gx, doubleType); PyArrayObject *Gi_arr = getContiguous(Gi, intType); PyArrayObject *Gp_arr = getContiguous(Gp, intType); Gpr = (pfloat *) PyArray_DATA(Gx_arr); Gir = (idxint *) PyArray_DATA(Gi_arr); Gjc = (idxint *) PyArray_DATA(Gp_arr); /* set c */ if (!PyArray_ISFLOAT(c) || PyArray_NDIM(c) != 1) { PyErr_SetString(PyExc_TypeError, "c must be a dense numpy array with one dimension"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); return NULL; } if (PyArray_DIM(c,0) != n){ PyErr_SetString(PyExc_ValueError, "c has incompatible dimension with G"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); return NULL; } PyArrayObject *c_arr = getContiguous(c, doubleType); cpr = (pfloat *) PyArray_DATA(c_arr); /* set h */ if (!PyArray_ISFLOAT(h) || PyArray_NDIM(h) != 1) { PyErr_SetString(PyExc_TypeError, "h must be a dense numpy array with one dimension"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); return NULL; } if (PyArray_DIM(h,0) != m){ PyErr_SetString(PyExc_ValueError, "h has incompatible dimension with G"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); return NULL; } PyArrayObject *h_arr = getContiguous(h, doubleType); hpr = (pfloat *) PyArray_DATA(h_arr); /* get dims['l'] */ PyObject *linearObj = PyDict_GetItemString(dims, "l"); if(linearObj) { if(PyInt_Check(linearObj) && ((l = (idxint) PyInt_AsLong(linearObj)) >= 0)) { numConicVariables += l; } else { PyErr_SetString(PyExc_TypeError, "dims['l'] ought to be a nonnegative integer"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } } /* get dims['q'] */ PyObject *socObj = PyDict_GetItemString(dims, "q"); if(socObj) { if (PyList_Check(socObj)) { ncones = PyList_Size(socObj); q = calloc(ncones, sizeof(idxint)); for (i = 0; i < ncones; ++i) { PyObject *qi = PyList_GetItem(socObj, i); if(PyInt_Check(qi) && ((q[i] = (idxint) PyInt_AsLong(qi)) > 0)) { numConicVariables += q[i]; } else { PyErr_SetString(PyExc_TypeError, "dims['q'] ought to be a list of positive integers"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } } } else { PyErr_SetString(PyExc_TypeError, "dims['q'] ought to be a list"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } } PyArrayObject *Ax_arr = NULL; PyArrayObject *Ai_arr = NULL; PyArrayObject *Ap_arr = NULL; PyArrayObject *b_arr = NULL; if(Ax && Ai && Ap && b) { /* set A */ if( !PyArray_ISFLOAT(Ax) || PyArray_NDIM(Ax) != 1 ) { PyErr_SetString(PyExc_TypeError, "Ax must be a numpy array of floats"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } if( !PyArray_ISINTEGER(Ai) || PyArray_NDIM(Ai) != 1) { PyErr_SetString(PyExc_TypeError, "Ai must be a numpy array of ints"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } if( !PyArray_ISINTEGER(Ap) || PyArray_NDIM(Ap) != 1) { PyErr_SetString(PyExc_TypeError, "Ap must be a numpy array of ints"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } // if ((SpMatrix_Check(A) && SP_ID(A) != DOUBLE)){ // PyErr_SetString(PyExc_TypeError, "A must be a sparse 'd' matrix"); // if(q) free(q); // Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); // Py_DECREF(c_arr); Py_DECREF(h_arr); // return NULL; // } // if ((p = SP_NROWS(A)) < 0) { // PyErr_SetString(PyExc_ValueError, "p must be a nonnegative integer"); // if(q) free(q); // Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); // Py_DECREF(c_arr); Py_DECREF(h_arr); // return NULL; // } // if (SP_NCOLS(A) != n) { // PyErr_SetString(PyExc_ValueError, "A has incompatible dimension with c"); // if(q) free(q); // Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); // Py_DECREF(c_arr); Py_DECREF(h_arr); // return NULL; // } // if (p != 0) { // Apr = SP_VALD(A); // Air = SP_ROW(A); // Ajc = SP_COL(A); // } Ax_arr = getContiguous(Ax, doubleType); Ai_arr = getContiguous(Ai, intType); Ap_arr = getContiguous(Ap, intType); Apr = (pfloat *) PyArray_DATA(Ax_arr); Air = (idxint *) PyArray_DATA(Ai_arr); Ajc = (idxint *) PyArray_DATA(Ap_arr); /* set b */ // if (!Matrix_Check(b) || MAT_NCOLS(b) != 1 || MAT_ID(b) != DOUBLE) { // PyErr_SetString(PyExc_TypeError, "b must be a dense 'd' matrix with one column"); // if(q) free(q); // return NULL; // } // if (MAT_NROWS(b) != p){ // PyErr_SetString(PyExc_ValueError, "b has incompatible dimension with A"); // if(q) free(q); // return NULL; // } // if (p != 0) { // bpr = MAT_BUFD(b); // } if (!PyArray_ISFLOAT(b) || PyArray_NDIM(b) != 1) { PyErr_SetString(PyExc_TypeError, "b must be a dense numpy array with one dimension"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); Py_DECREF(Ax_arr); Py_DECREF(Ai_arr); Py_DECREF(Ap_arr); return NULL; } if (PyArray_DIM(b,0) != p){ PyErr_SetString(PyExc_ValueError, "b has incompatible dimension with A"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); Py_DECREF(Ax_arr); Py_DECREF(Ai_arr); Py_DECREF(Ap_arr); return NULL; } b_arr = getContiguous(b, doubleType); bpr = (pfloat *) PyArray_DATA(b_arr); } else if (Ax || Ai || Ap || b) { // check that A and b are both supplied PyErr_SetString(PyExc_ValueError, "A and b arguments must be supplied together"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } /* check that sum(q) + l = m */ if( numConicVariables != m ){ PyErr_SetString(PyExc_ValueError, "Number of rows of G does not match dims.l+sum(dims.q)"); if (q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); if (b_arr) Py_DECREF(b_arr); if (Ax_arr) Py_DECREF(Ax_arr); if (Ai_arr) Py_DECREF(Ai_arr); if (Ap_arr) Py_DECREF(Ap_arr); return NULL; } /* This calls ECOS setup function. */ mywork = ECOS_setup(n, m, p, l, ncones, q, Gpr, Gjc, Gir, Apr, Ajc, Air, cpr, hpr, bpr); if( mywork == NULL ){ PyErr_SetString(PyExc_RuntimeError, "Internal problem occurred in ECOS while setting up the problem.\nPlease send a bug report with data to Alexander Domahidi.\nEmail: [email protected]"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); if (b_arr) Py_DECREF(b_arr); if (Ax_arr) Py_DECREF(Ax_arr); if (Ai_arr) Py_DECREF(Ai_arr); if (Ap_arr) Py_DECREF(Ap_arr); return NULL; } /* Set settings for ECOS. */ if(verbose) { mywork->stgs->verbose = (idxint) PyObject_IsTrue(verbose); } /* Solve! */ idxint exitcode = ECOS_solve(mywork); /* create output (all data is *deep copied*) */ // TODO: request CVXOPT API for constructing from existing pointer /* x */ // matrix *x; // if(!(x = Matrix_New(n,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(x), mywork->x, n*sizeof(double)); npy_intp veclen[1]; veclen[0] = n; PyObject *x = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->x); /* y */ // matrix *y; // if(!(y = Matrix_New(p,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(y), mywork->y, p*sizeof(double)); veclen[0] = p; PyObject *y = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->y); /* info dict */ // infostring const char* infostring; switch( exitcode ){ case ECOS_OPTIMAL: infostring = "Optimal solution found"; break; case ECOS_MAXIT: infostring = "Maximum number of iterations reached"; break; case ECOS_PINF: infostring = "Primal infeasible"; break; case ECOS_DINF: infostring = "Dual infeasible"; break; case ECOS_NUMERICS: infostring = "Run into numerical problems"; break; case ECOS_OUTCONE: infostring = "PROBLEM: Multipliers leaving the cone"; break; default: infostring = "UNKNOWN PROBLEM IN SOLVER"; } // numerical errors idxint numerr = 0; if( (exitcode == ECOS_NUMERICS) || (exitcode == ECOS_OUTCONE) || (exitcode == ECOS_FATAL) ){ numerr = 1; } // timings #if PROFILING > 0 PyObject *tinfos = Py_BuildValue( #if PROFILING > 1 "{s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d}", #else "{s:d,s:d,s:d}", #endif #if PROFILING > 1 "tkktcreate",(double)mywork->info->tkktcreate, "tkktsolve",(double)mywork->info->tkktsolve, "tkktfactor",(double)mywork->info->tfactor, "torder",(double)mywork->info->torder, "ttranspose",(double)mywork->info->ttranspose, #endif "runtime",(double)mywork->info->tsolve + (double)mywork->info->tsetup, "tsetup",(double)mywork->info->tsetup, "tsolve",(double)mywork->info->tsolve); #endif PyObject *infoDict = Py_BuildValue( #if PROFILING > 0 "{s:l,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:l,s:s,s:O,s:l}", #else "{s:l,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:l,s:s,s:l}", #endif "exitFlag", exitcode, "pcost", (double)mywork->info->pcost, "dcost", (double)mywork->info->dcost, "pres", (double)mywork->info->pres, "dres", (double)mywork->info->dres, "pinf", (double)mywork->info->pinf, "dinf", (double)mywork->info->dinf, "pinfres",(double)mywork->info->pinfres, "dinfres",(double)mywork->info->dinfres, "gap",(double)mywork->info->gap, "relgap",(double)mywork->info->relgap, "r0",(double)mywork->stgs->feastol, "iter",mywork->info->iter, "infostring",infostring, #if PROFILING > 0 "timing", tinfos, #endif "numerr",numerr); #if PROFILING > 0 // give reference to infoDict Py_DECREF(tinfos); #endif /* s */ // matrix *s; // if(!(s = Matrix_New(m,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(s), mywork->s, m*sizeof(double)); veclen[0] = m; PyObject *s = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->s); /* z */ // matrix *z; // if(!(z = Matrix_New(m,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(z), mywork->z, m*sizeof(double)); veclen[0] = m; PyObject *z = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->z); /* cleanup */ ECOS_cleanup(mywork, 4); PyObject *returnDict = Py_BuildValue( "{s:O,s:O,s:O,s:O,s:O}", "x",x, "y",y, "z",z, "s",s, "info",infoDict); // give up ownership to the return dictionary Py_DECREF(x); Py_DECREF(y); Py_DECREF(z); Py_DECREF(s); Py_DECREF(infoDict); // no longer need pointers to arrays that held primitives if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); if (b_arr) Py_DECREF(b_arr); if (Ax_arr) Py_DECREF(Ax_arr); if (Ai_arr) Py_DECREF(Ai_arr); if (Ap_arr) Py_DECREF(Ap_arr); return returnDict; }
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; }