static PyObject *phase1_sdp (PyObject *self, PyObject *args, PyObject *kwrds) { matrix *u; spmatrix *Ai,*Ao; int_t k,i,j,n,m,nnz,nz,col; if(!PyArg_ParseTuple(args,"OO",&Ai,&u)) return NULL; n = (int_t) sqrt((double)SP_NROWS(Ai)); m = SP_NCOLS(Ai) - 1; nnz = SP_NNZ(Ai) - SP_COL(Ai)[1] + 1 + m + n + 1; Ao = SpMatrix_New((n+2)*(n+2),m+2,nnz,DOUBLE); if (!Ao) return PyErr_NoMemory(); // A_0 SP_VALD(Ao)[0] = 1.0; SP_ROW(Ao)[0] = n*(n+2)+n; SP_COL(Ao)[0] = 0; SP_COL(Ao)[1] = 1; // A_i, i=1,..,m for (i=1;i<=m;i++){ k = SP_COL(Ao)[i]; nz = SP_COL(Ai)[i+1]-SP_COL(Ai)[i]; // nonzeros in Ai // copy Ai memcpy(SP_VALD(Ao)+k,SP_VALD(Ai)+SP_COL(Ai)[i],nz*sizeof(double)); // insert -u[i] SP_VALD(Ao)[k+nz] = -MAT_BUFD(u)[i-1]; // update row colptr SP_COL(Ao)[i+1] = SP_COL(Ao)[i]+nz+1; // generate row indices for (j=0;j<nz;j++) { col = SP_ROW(Ai)[SP_COL(Ai)[i]+j] / n; SP_ROW(Ao)[k+j] = SP_ROW(Ai)[SP_COL(Ai)[i]+j] + col*2; } SP_ROW(Ao)[k+nz] = n*(n+2)+n; } // last constraint k = SP_COL(Ao)[m+1]; for (i=0;i<n;i++){ SP_VALD(Ao)[k+i] = 1.0; SP_ROW(Ao)[k+i] = i*(n+2)+i; } SP_VALD(Ao)[k+n] = 1.0; SP_ROW(Ao)[k+n] = (n+2)*(n+2)-1; SP_COL(Ao)[m+2] = SP_COL(Ao)[m+1] + n + 1; return (PyObject*) Ao; }
static PyObject* getfactor(PyObject *self, PyObject *args) { PyObject *F; cholmod_factor *Lf; cholmod_sparse *Ls; #if PY_MAJOR_VERSION >= 3 const char *descr; #else char *descr; #endif if (!set_options()) return NULL; if (!PyArg_ParseTuple(args, "O", &F)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(F) || !(descr = PyCapsule_GetName(F))) err_CO("F"); if (strncmp(descr, "CHOLMOD FACTOR", 14)) PY_ERR_TYPE("F is not a CHOLMOD factor"); Lf = (cholmod_factor *) PyCapsule_GetPointer(F, descr); #else if (!PyCObject_Check(F)) err_CO("F"); descr = PyCObject_GetDesc(F); if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14)) PY_ERR_TYPE("F is not a CHOLMOD factor"); Lf = (cholmod_factor *) PyCObject_AsVoidPtr(F); #endif /* Check factorization */ if (Lf->xtype == CHOLMOD_PATTERN) PY_ERR(PyExc_ValueError, "F must be a numeric Cholesky factor"); if (!(Ls = CHOL(factor_to_sparse)(Lf, &Common))) return PyErr_NoMemory(); spmatrix *ret = SpMatrix_New(Ls->nrow, Ls->ncol, Ls->nzmax, (Ls->xtype == CHOLMOD_REAL ? DOUBLE : COMPLEX)); if (!ret) { CHOL(free_sparse)(&Ls, &Common); return PyErr_NoMemory(); } memcpy(SP_COL(ret), Ls->p, (Ls->ncol+1)*sizeof(int_t)); memcpy(SP_ROW(ret), Ls->i, (Ls->nzmax)*sizeof(int_t)); memcpy(SP_VAL(ret), Ls->x, (Ls->nzmax)*E_SIZE[SP_ID(ret)]); CHOL(free_sparse)(&Ls, &Common); return (PyObject *)ret; }
static PyObject *Av_to_spmatrix (PyObject *self, PyObject *args, PyObject *kwrds) { PyObject *scale = Py_False; spmatrix *Av,*Ip,*Jp; int_t i,j,n,nnz,c,ci,p,q; char *kwlist[] = {"Av","Ip","Jp","j","n","scale",NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOOnn|O", kwlist, &Av,&Ip,&Jp,&j,&n, &scale)) return NULL; p = SP_COL(Av)[j]; nnz = SP_COL(Av)[j+1]-p; spmatrix *Aj = SpMatrix_New(n,n,nnz,DOUBLE); if (!Aj) return PyErr_NoMemory(); // Generate col-ptr and row index SP_COL(Aj)[0] = 0; if (scale==Py_False) { for (ci=0,i=0;i<nnz;i++) { q = SP_ROW(Av)[p+i]; SP_ROW(Aj)[i] = MAT_BUFI(Ip)[q]; c = MAT_BUFI(Jp)[q]; SP_VALD(Aj)[i] = SP_VALD(Av)[p+i]; while (ci < c) SP_COL(Aj)[++ci] = i; } while (ci < n) SP_COL(Aj)[++ci] = nnz; } else { for (ci=0,i=0;i<nnz;i++) { q = SP_ROW(Av)[p+i]; SP_ROW(Aj)[i] = MAT_BUFI(Ip)[q]; c = MAT_BUFI(Jp)[q]; SP_VALD(Aj)[i] = SP_VALD(Av)[p+i]; if (c == SP_ROW(Aj)[i]) SP_VALD(Aj)[i] *= 0.5; // scale diag. element while (ci < c) SP_COL(Aj)[++ci] = i; } while (ci < n) SP_COL(Aj)[++ci] = nnz; } return (PyObject *) Aj; }
static PyObject* splinsolve(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *A, *B, *X; matrix *P=NULL; int n, nnz; cholmod_sparse *Ac=NULL, *Bc=NULL, *Xc=NULL; cholmod_factor *L=NULL; #if PY_MAJOR_VERSION >= 3 int uplo_='L'; #endif char uplo='L'; char *kwlist[] = {"A", "B", "p", "uplo", NULL}; if (!set_options()) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|OC", kwlist, &A, &B, &P, &uplo_)) return NULL; uplo = (char) uplo_; #else if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Oc", kwlist, &A, &B, &P, &uplo)) return NULL; #endif if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) PY_ERR_TYPE("A is not a square sparse matrix"); n = SP_NROWS(A); nnz = SP_NNZ(A); if (!SpMatrix_Check(B) || SP_ID(A) != SP_ID(B)) PY_ERR_TYPE("B must be a sparse matrix of the same type as A"); if (SP_NROWS(B) != n) PY_ERR(PyExc_ValueError, "incompatible dimensions for B"); if (P) { if (!Matrix_Check(P) || MAT_ID(P) != INT) err_int_mtrx("p"); if (MAT_LGT(P) != n) err_buf_len("p"); if (!CHOL(check_perm)(P->buffer, n, n, &Common)) PY_ERR(PyExc_ValueError, "not a valid permutation"); } if (uplo != 'U' && uplo != 'L') err_char("uplo", "'L', 'U'"); if (!(Ac = pack(A, uplo))) return PyErr_NoMemory(); L = CHOL(analyze_p) (Ac, P ? MAT_BUFI(P): NULL, NULL, 0, &Common); if (Common.status != CHOLMOD_OK){ CHOL(free_factor)(&L, &Common); CHOL(free_sparse)(&Ac, &Common); if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory(); else { PyErr_SetString(PyExc_ValueError, "symbolic factorization " "failed"); return NULL; } } CHOL(factorize) (Ac, L, &Common); CHOL(free_sparse)(&Ac, &Common); if (Common.status > 0) switch (Common.status) { case CHOLMOD_NOT_POSDEF: PyErr_SetObject(PyExc_ArithmeticError, Py_BuildValue("i", L->minor)); CHOL(free_factor)(&L, &Common); return NULL; break; case CHOLMOD_DSMALL: /* This never happens unless we change the default value * of Common.dbound (0.0). */ if (L->is_ll) PyErr_Warn(PyExc_RuntimeWarning, "tiny diagonal " "elements in L"); else PyErr_Warn(PyExc_RuntimeWarning, "tiny diagonal " "elements in D"); break; default: PyErr_Warn(PyExc_UserWarning, ""); } if (L->minor<n) { CHOL(free_factor)(&L, &Common); PY_ERR(PyExc_ArithmeticError, "singular matrix"); } if (!(Bc = create_matrix(B))) { CHOL(free_factor)(&L, &Common); return PyErr_NoMemory(); } Xc = CHOL(spsolve)(0, L, Bc, &Common); free_matrix(Bc); CHOL(free_factor)(&L, &Common); if (Common.status != CHOLMOD_OK){ CHOL(free_sparse)(&Xc, &Common); if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory(); else PY_ERR(PyExc_ValueError, "solve step failed"); } if (!(X = SpMatrix_New(Xc->nrow, Xc->ncol, ((int_t*)Xc->p)[Xc->ncol], SP_ID(A)))) { CHOL(free_sparse)(&Xc, &Common); return PyErr_NoMemory(); } memcpy(SP_COL(X), (int_t *) Xc->p, (Xc->ncol+1)*sizeof(int_t)); memcpy(SP_ROW(X), (int_t *) Xc->i, ((int_t *) Xc->p)[Xc->ncol]*sizeof(int_t)); memcpy(SP_VAL(X), (double *) Xc->x, ((int_t *) Xc->p)[Xc->ncol]*E_SIZE[SP_ID(X)]); CHOL(free_sparse)(&Xc, &Common); return (PyObject *) X; }
static PyObject* spsolve(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *B, *X=NULL; cholmod_sparse *Bc=NULL, *Xc=NULL; PyObject *F; cholmod_factor *L; int n, sys=0; #if PY_MAJOR_VERSION >= 3 const char *descr; #else char *descr; #endif char *kwlist[] = {"F", "B", "sys", NULL}; int sysvalues[] = {CHOLMOD_A, CHOLMOD_LDLt, CHOLMOD_LD, CHOLMOD_DLt, CHOLMOD_L, CHOLMOD_Lt, CHOLMOD_D, CHOLMOD_P, CHOLMOD_Pt }; if (!set_options()) return NULL; if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|i", kwlist, &F, &B, &sys)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(F) || !(descr = PyCapsule_GetName(F))) err_CO("F"); if (strncmp(descr, "CHOLMOD FACTOR", 14)) PY_ERR_TYPE("F is not a CHOLMOD factor"); L = (cholmod_factor *) PyCapsule_GetPointer(F, descr); #else if (!PyCObject_Check(F)) err_CO("F"); descr = PyCObject_GetDesc(F); if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14)) PY_ERR_TYPE("F is not a CHOLMOD factor"); L = (cholmod_factor *) PyCObject_AsVoidPtr(F); #endif if (L->xtype == CHOLMOD_PATTERN) PY_ERR(PyExc_ValueError, "called with symbolic factor"); n = L->n; if (L->minor<n) PY_ERR(PyExc_ArithmeticError, "singular matrix"); if (sys < 0 || sys > 8) PY_ERR(PyExc_ValueError, "invalid value for sys"); if (!SpMatrix_Check(B) || (SP_ID(B) == DOUBLE && L->xtype == CHOLMOD_COMPLEX) || (SP_ID(B) == COMPLEX && L->xtype == CHOLMOD_REAL)) PY_ERR_TYPE("B must a sparse matrix of the same " "numerical type as F"); if (SP_NROWS(B) != n) PY_ERR(PyExc_ValueError, "incompatible dimensions for B"); if (!(Bc = create_matrix(B))) return PyErr_NoMemory(); Xc = CHOL(spsolve)(sysvalues[sys], L, Bc, &Common); free_matrix(Bc); if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory(); if (Common.status != CHOLMOD_OK) PY_ERR(PyExc_ValueError, "solve step failed"); if (!(X = SpMatrix_New(Xc->nrow, Xc->ncol, ((int_t*)Xc->p)[Xc->ncol], (L->xtype == CHOLMOD_REAL ? DOUBLE : COMPLEX)))) { CHOL(free_sparse)(&Xc, &Common); return PyErr_NoMemory(); } memcpy(SP_COL(X), Xc->p, (Xc->ncol+1)*sizeof(int_t)); memcpy(SP_ROW(X), Xc->i, ((int_t *)Xc->p)[Xc->ncol]*sizeof(int_t)); memcpy(SP_VAL(X), Xc->x, ((int_t *) Xc->p)[Xc->ncol]*E_SIZE[SP_ID(X)]); CHOL(free_sparse)(&Xc, &Common); return (PyObject *) X; }
static PyObject *robustLS_to_sdp (PyObject *self, PyObject *args, PyObject *kwrds) { PyObject *Alist,*bt, *Ai; spmatrix *A,*b; int_t m,n,mp,np,pt,i,j,k,N,nnz=0,ri=0; char *kwlist[] = {"Alist","bt",NULL}; if(!PyArg_ParseTupleAndKeywords(args,kwrds,"OO",kwlist,&Alist,&bt)) return NULL; if(!PyList_Check(Alist)) { PyErr_SetString(PyExc_TypeError,"Alist must be a list of matrices"); return NULL; } // get pt = p + 1 pt = PyList_Size(Alist); // get size of bt if(Matrix_Check(bt)){ m = MAT_NROWS(bt); np = MAT_NCOLS(bt); } else if (SpMatrix_Check(bt)){ m = SP_NROWS(bt); np = SP_NCOLS(bt); } else { PyErr_SetString(PyExc_TypeError,"b must be a vector"); return NULL; } if (np!=1) { PyErr_SetString(PyExc_TypeError,"b must be a vector"); return NULL; } // get n and check A0 if (!(Ai = PyList_GetItem(Alist,0))) return NULL; if (Matrix_Check(Ai)) { n = MAT_NCOLS(Ai); nnz += m*n; } else if (SpMatrix_Check(Ai)) { n = SP_NCOLS(Ai); nnz += SP_NNZ(Ai); } else { PyErr_SetString(PyExc_TypeError,"only spmatrix and matrix types allowed"); return NULL; } // check remaining matrices in Alist for (i=1;i<pt;i++) { if (!(Ai = PyList_GetItem(Alist,i))) return NULL; if (Matrix_Check(Ai)) { mp = MAT_NROWS(Ai); np = MAT_NCOLS(Ai); nnz += m*n; } else if (SpMatrix_Check(Ai)) { mp = SP_NROWS(Ai); np = SP_NCOLS(Ai); nnz += SP_NNZ(Ai); } else { PyErr_SetString(PyExc_TypeError,"only spmatrix and matrix types allowed"); return NULL; } if (!(mp==m && np==n)){ PyErr_SetString(PyExc_TypeError,"matrices in Alist must have same size"); return NULL; } } nnz += 2*m + pt; // generate b b = SpMatrix_New(n+2,1,2,DOUBLE); if (!b) return PyErr_NoMemory(); SP_COL(b)[0] = 0; SP_VALD(b)[0] = -1; SP_ROW(b)[0] = 0; SP_VALD(b)[1] = -1; SP_ROW(b)[1] = 1; SP_COL(b)[1] = 2; // generate A N = m+pt; A = SpMatrix_New(N*N,n+3,nnz,DOUBLE); if (!A) return PyErr_NoMemory(); // build A0 SP_COL(A)[0] = ri; for(i=0;i<m;i++){ if(SpMatrix_Check(bt)){ SP_VALD(A)[ri] = -SP_VALD(bt)[i]; SP_ROW(A)[ri++] = pt+i; } else{ SP_VALD(A)[ri] = -MAT_BUFD(bt)[i]; SP_ROW(A)[ri++] = pt+i; } } for(i=0;i<m;i++) { SP_VALD(A)[ri] = 1; SP_ROW(A)[ri++] = (N+1)*pt + i*N+i; } // build A1 SP_COL(A)[1] = ri; for(i=0;i<pt-1;i++){ SP_VALD(A)[ri] = -1; SP_ROW(A)[ri++] = N+1 + i*N+i; } // build A2 SP_COL(A)[2] = ri; SP_VALD(A)[ri] = -1; SP_ROW(A)[ri++] = 0; SP_COL(A)[3] = ri; // build A3,... for(j=0;j<n;j++){ // generate col. i for(i=0;i<pt;i++){ Ai = PyList_GetItem(Alist,i); if(SpMatrix_Check(Ai)) { nnz = SP_COL(Ai)[j+1]-SP_COL(Ai)[j]; for(k=0;k<nnz;k++) { SP_VALD(A)[ri] = -SP_VALD(Ai)[SP_COL(Ai)[j]+k]; SP_ROW(A)[ri++] = pt+i*N + SP_ROW(Ai)[SP_COL(Ai)[j]+k]; } } else { for (k=0;k<m;k++) { SP_VALD(A)[ri] = -MAT_BUFD(Ai)[j*m+k]; SP_ROW(A)[ri++] = pt+i*N + k; } } } SP_COL(A)[j+4] = ri; } return Py_BuildValue("NN",A,b); }
static PyObject* sdpa_readhead (PyObject *self, PyObject *args) { int i,j,t; int_t m=0,n=0,nblocks=0; matrix *bstruct = NULL; PyObject *f; char buf[2048]; // buffer char *info; if (!PyArg_ParseTuple(args,"O",&f)) return NULL; #if PY_MAJOR_VERSION >= 3 if (PyUnicode_Check(f)) { const char* fname = PyUnicode_AsUTF8AndSize(f,NULL); #else if (PyString_Check(f)) { const char* fname = PyString_AsString(f); #endif FILE *fp = fopen(fname,"r"); if (!fp) { return NULL; } /* Skip comments and read m */ while (1) { info = fgets(buf,1024,fp); if (buf[0] != '*' && buf[0] != '"') { sscanf(buf,"%d",&i); break; } } m = (int_t) i; /* read nblocks */ j = fscanf(fp,"%d",&i); nblocks = (int_t) i; /* read blockstruct and compute block offsets*/ bstruct = Matrix_New(nblocks,1,INT); if (!bstruct) return PyErr_NoMemory(); n = 0; for (i=0; i<nblocks; i++) { j = fscanf(fp,"%*[^0-9+-]%d",&t); MAT_BUFI(bstruct)[i] = (int_t) t; n += (int_t) labs(MAT_BUFI(bstruct)[i]); } fclose(fp); } return Py_BuildValue("iiN",n,m,bstruct); } static char doc_sdpa_read[] = "Reads sparse SDPA data file (dat-s).\n" "\n" "A,b,bstruct = sdpa_read(f[,neg=False])\n" "\n" "PURPOSE\n" "Reads problem data from sparse SDPA data file for\n" "the semidefinite programs:\n" "\n" " (P) minimize <A0,X>\n" " subject to <Ai,X> = bi, i = 1,...,m\n" " X >= 0\n" "\n" " (D) maximize b'*y\n" " subject to sum_i Ai*yi + S = A0\n" " S >= 0\n" "\n" "Here '>=' means that X and S must be positive semidefinite.\n" "The matrices A0,A1,...Am are symmetric and of order n.\n" "If the optional argument 'neg' is True, the negative of the\n" "problem data is returned.\n" "\n" "ARGUMENTS\n" "f Python file object\n" "\n" "neg Python boolean (optional)\n" "\n" "RETURNS\n" "A CVXOPT sparse matrix of doubles with columns Ai[:]\n" " (Only lower trianglular elements of Ai are stored.)\n" "\n" "b CVXOPT matrix\n" "\n" "bstruct CVXOPT integer matrix\n"; static PyObject* sdpa_read (PyObject *self, PyObject *args, PyObject *kwrds) { int i,j,mno,bno,ii,jj,t; int_t k,m,n,nblocks,nlines; double v; long fpos; PyObject *f; PyObject *neg = Py_False; char *info; const char* fname; int_t* boff; // block offset char buf[2048]; // buffer char *kwlist[] = {"f","neg",NULL}; if (!PyArg_ParseTupleAndKeywords(args,kwrds,"O|O",kwlist,&f,&neg)) return NULL; #if PY_MAJOR_VERSION >= 3 if (PyUnicode_Check(f)) fname = PyUnicode_AsUTF8AndSize(f,NULL); #elif PY_MAJOR_VERSION == 2 if (PyString_Check(f)) fname = PyString_AsString(f); #endif FILE *fp = fopen(fname,"r"); if (!fp) { return NULL; } /* Skip comments and read m */ while (1) { info = fgets(buf,1024,fp); if (buf[0] != '*' && buf[0] != '"') { sscanf(buf,"%d",&i); break; } } m = (int_t) i; /* read nblocks */ j = fscanf(fp,"%d",&i); nblocks = (int_t) i; /* read blockstruct and compute block offsets*/ matrix *bstruct = Matrix_New(nblocks,1,INT); if (!bstruct) return PyErr_NoMemory(); boff = malloc(sizeof(int_t)*(nblocks+1)); if(!boff) return PyErr_NoMemory(); boff[0] = 0; n = 0; for (i=0; i<nblocks; i++) { j = fscanf(fp,"%*[^0-9+-]%d",&t); MAT_BUFI(bstruct)[i] = (int_t) t; n += (int_t) labs(MAT_BUFI(bstruct)[i]); boff[i+1] = n; } /* read vector b */ matrix *b = Matrix_New(m,1,DOUBLE); if (!b) return PyErr_NoMemory(); for (i=0;i<m;i++) { j = fscanf(fp,"%*[^0-9+-]%lf",&MAT_BUFD(b)[i]); if (neg == Py_True) MAT_BUFD(b)[i] *= -1; } /* count remaining lines */ fpos = ftell(fp); for (nlines = 0; fgets(buf, 1023, fp) != NULL; nlines++); //nlines--; fseek(fp,fpos,SEEK_SET); /* Create data matrix A */ spmatrix *A = SpMatrix_New(n*n,m+1,nlines,DOUBLE); if (!A) return PyErr_NoMemory(); // read data matrices fseek(fp,fpos,SEEK_SET); for (i=0,j=-1,k=0;k<nlines;k++){ if (fscanf(fp,"%*[^0-9+-]%d",&mno) <=0 ) break; if (fscanf(fp,"%*[^0-9+-]%d",&bno) <=0 ) break; if (fscanf(fp,"%*[^0-9+-]%d",&ii) <=0 ) break; if (fscanf(fp,"%*[^0-9+-]%d",&jj) <=0 ) break; if (fscanf(fp,"%*[^0-9+-]%lf",&v) <=0 ) break; // check that value is nonzero if (v != 0) { // add block offset ii += boff[bno-1]; jj += boff[bno-1]; // insert index and value SP_ROW(A)[i] = (int_t) ((ii-1)*n + (jj-1)); if (neg == Py_True) SP_VALD(A)[i] = -v; else SP_VALD(A)[i] = v; // update col. ptr. while (mno > j) SP_COL(A)[++j] = i; i++; } } // update last element(s) of col. ptr. while (m+1 > j) SP_COL(A)[++j] = i; fclose(fp); // free temp. memory free(boff); return Py_BuildValue("NNN",A,b,bstruct); }