static PyObject *SCMcolumn (PyObject *self, PyObject *args) { PyObject *H,*Av,*Ip,*Jp,*V; int_t m,n,K; int_t i,j,k,l,p,q,r,c; if(!PyArg_ParseTuple(args,"OOOOOn",&H,&Av,&V,&Ip,&Jp,&j)) return NULL; m = MAT_NCOLS(H); n = MAT_NROWS(V); K = MAT_NCOLS(V)/2; //#pragma omp parallel for shared(m,n,K,Av,Ip,Jp,H,V,j) private(i,l,k,r,c,q,p) for (i=j;i<m;i++) { p = SP_COL(Av)[i]; MAT_BUFD(H)[j*m+i] = 0; for (l=0;l<SP_COL(Av)[i+1]-p;l++) { q = SP_ROW(Av)[p+l]; r = MAT_BUFI(Ip)[q]; c = MAT_BUFI(Jp)[q]; for (k=0;k<K;k++) { MAT_BUFD(H)[j*m+i] += SP_VALD(Av)[p+l]* MAT_BUFD(V)[k*n+r]*MAT_BUFD(V)[(K+k)*n+c]; if (r != c) MAT_BUFD(H)[j*m+i] += SP_VALD(Av)[p+l]* MAT_BUFD(V)[k*n+c]*MAT_BUFD(V)[(K+k)*n+r]; } } } Py_RETURN_NONE; }
static PyObject *sub2ind (PyObject *self, PyObject *args) { matrix *Im,*Jm; PyObject *siz; int_t i; int_t m,n; if (!PyArg_ParseTuple(args, "OOO", &siz, &Im, &Jm)) return NULL; if (!PyArg_ParseTuple(siz, "nn", &m, &n)) return NULL; matrix *Ind = Matrix_New(MAT_NROWS(Im),1,INT); if (!Ind) return PyErr_NoMemory(); for (i=0;i< MAT_NROWS(Im) ;i++) { // Add data check: MAT_BUFI(Ind)[i] = MAT_BUFI(Im)[i] + m*MAT_BUFI(Jm)[i]; } return Py_BuildValue("N", Ind); }
static PyObject *ind2sub (PyObject *self, PyObject *args) { matrix *Im; int_t i; int_t n; if (!PyArg_ParseTuple(args, "nO", &n, &Im)) return NULL; matrix *Il = Matrix_New(MAT_NROWS(Im),1,INT); if (!Il) return PyErr_NoMemory(); matrix *Jl = Matrix_New(MAT_NROWS(Im),1,INT); if (!Il) return PyErr_NoMemory(); for (i=0;i< MAT_NROWS(Im);i++) { MAT_BUFI(Il)[i] = MAT_BUFI(Im)[i] % n; MAT_BUFI(Jl)[i] = MAT_BUFI(Im)[i] / n; } return Py_BuildValue("NN", Il, Jl); }
static PyObject *toeplitz (PyObject *self, PyObject *args, PyObject *kwrds) { PyObject *r=NULL, *c=NULL; int_t m,n,i,j; char *kwlist[] = {"c","r",NULL}; if (!PyArg_ParseTupleAndKeywords(args,kwrds,"O|O",kwlist,&c,&r)) return NULL; if (!Matrix_Check(c)) return NULL; if (r==NULL) r = c; else if (!Matrix_Check(r)) return NULL; if (MAT_ID(r) != DOUBLE || MAT_ID(c) != DOUBLE) return NULL; if (MAT_NCOLS(r) > 1 || MAT_NCOLS(c) > 1) return NULL; m = MAT_NROWS(c); n = MAT_NROWS(r); // build dense toeplitz matrix, column by column matrix *T = Matrix_New(m,n,DOUBLE); if (!T) return PyErr_NoMemory(); for(j=0;j<n;j++) { for(i=0;i<(m>j?j:m);i++) { MAT_BUFD(T)[j*m+i] = MAT_BUFD(r)[j-i]; } for(i=j;i<m;i++) { MAT_BUFD(T)[j*m+i] = MAT_BUFD(c)[i-j]; } } return (PyObject*) T; }
static PyObject *scal_diag (PyObject *self, PyObject *args) { PyObject *Vp,*Id; int_t i,n; double t = 0.5; if(!PyArg_ParseTuple(args,"OO|d",&Vp,&Id,&t)) return NULL; n = MAT_NROWS(Id); for (i=0;i<n;i++){ SP_VALD(Vp)[MAT_BUFI(Id)[i]] *= t; } Py_RETURN_NONE; }
static PyObject *SCMcolumn2 (PyObject *self, PyObject *args) { PyObject *H,*Av,*Ip,*Jp,*V,*Kl; int_t m,n; int_t i,j,k,p,q,r,c,r1,c1,pj,pi; double alpha,beta; if(!PyArg_ParseTuple(args,"OOOOOOn",&H,&Av,&V,&Ip,&Jp,&Kl,&j)) return NULL; m = MAT_NCOLS(H); n = MAT_NROWS(V); for (i=j;i<m;i++) MAT_BUFD(H)[j*m+i] = 0; //#pragma omp parallel for shared(m,n,K,Av,Ip,Jp,H,V,j) private(i,l,k,r,c,q,p) pj = SP_COL(Av)[j]; for (p=0;p<SP_COL(Av)[j+1]-pj;p++) { alpha = SP_VALD(Av)[pj+p]; k = SP_ROW(Av)[pj+p]; r = MAT_BUFI(Ip)[k]; c = MAT_BUFI(Jp)[k]; if (r!=c) alpha*=2; // look up columns in V r = MAT_BUFI(Kl)[r]; c = MAT_BUFI(Kl)[c]; for(i=j;i<m;i++) { pi = SP_COL(Av)[i]; for (q=0;q<SP_COL(Av)[i+1]-pi;q++) { beta = SP_VALD(Av)[pi+q]; k = SP_ROW(Av)[pi+q]; r1 = MAT_BUFI(Ip)[k]; c1 = MAT_BUFI(Jp)[k]; MAT_BUFD(H)[j*m+i] += alpha*beta*MAT_BUFD(V)[n*r+r1]*MAT_BUFD(V)[n*c+c1]; if (r1!=c1) MAT_BUFD(H)[j*m+i] += alpha*beta*MAT_BUFD(V)[n*r+c1]*MAT_BUFD(V)[n*c+r1]; } } } Py_RETURN_NONE; }
static PyObject *matperm (PyObject *self, PyObject *args) { PyObject *nzc; matrix *pm; int_t Ns,Nd,m,i,Nmax; if (!PyArg_ParseTuple(args,"On",&nzc,&Nmax)) return NULL; m = MAT_NROWS(nzc); pm = Matrix_New(m,1,INT); if (!pm) return PyErr_NoMemory(); // Check Nmax if (Nmax<0) Nmax = 0; Ns = 0; Nd = 0; for (i=0;i<m;i++){ if(MAT_BUFI(nzc)[i] > Nmax) MAT_BUFI(pm)[Nd++] = i; else MAT_BUFI(pm)[m-1-Ns++] = i; } return Py_BuildValue("Nn",pm,Ns); }
static PyObject* linsolve(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *A; matrix *B, *P=NULL; int i, n, nnz, oB=0, ldB=0, nrhs=-1; cholmod_sparse *Ac=NULL; cholmod_factor *L=NULL; cholmod_dense *x=NULL, *b=NULL; void *b_old; #if PY_MAJOR_VERSION >= 3 int uplo_ = 'L'; #endif char uplo='L'; char *kwlist[] = {"A", "B", "p", "uplo", "nrhs", "ldB", "offsetB", NULL}; if (!set_options()) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|OCiii", kwlist, &A, &B, &P, &uplo_, &nrhs, &ldB, &oB)) return NULL; uplo = (char) uplo_; #else if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ociii", kwlist, &A, &B, &P, &uplo, &nrhs, &ldB, &oB)) return NULL; #endif if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) PY_ERR_TYPE("A is not a sparse matrix"); n = SP_NROWS(A); nnz = SP_NNZ(A); if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A)) PY_ERR_TYPE("B must be a dense matrix of the same numerical " "type as A"); if (nrhs < 0) nrhs = MAT_NCOLS(B); if (n == 0 || nrhs == 0) return Py_BuildValue(""); if (ldB == 0) ldB = MAX(1,MAT_NROWS(B)); if (ldB < MAX(1,n)) err_ld("ldB"); if (oB < 0) err_nn_int("offsetB"); if (oB + (nrhs-1)*ldB + n > MAT_LGT(B)) err_buf_len("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){ free_matrix(Ac); CHOL(free_sparse)(&Ac, &Common); CHOL(free_factor)(&L, &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) { CHOL(free_factor)(&L, &Common); switch (Common.status) { case CHOLMOD_OUT_OF_MEMORY: return PyErr_NoMemory(); default: PyErr_SetString(PyExc_ValueError, "factorization " "failed"); return NULL; } } 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"); } b = CHOL(allocate_dense)(n, 1, n, (MAT_ID(B) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX) , &Common); if (Common.status == CHOLMOD_OUT_OF_MEMORY) { CHOL(free_factor)(&L, &Common); CHOL(free_dense)(&b, &Common); return PyErr_NoMemory(); } b_old = b->x; for (i=0; i<nrhs; i++) { b->x = MAT_BUF(B) + (i*ldB + oB)*E_SIZE[MAT_ID(B)]; x = CHOL(solve) (CHOLMOD_A, L, b, &Common); if (Common.status != CHOLMOD_OK){ PyErr_SetString(PyExc_ValueError, "solve step failed"); CHOL(free_factor)(&L, &Common); b->x = b_old; CHOL(free_dense)(&b, &Common); CHOL(free_dense)(&x, &Common); return NULL; } memcpy(b->x, x->x, SP_NROWS(A)*E_SIZE[MAT_ID(B)]); CHOL(free_dense)(&x, &Common); } b->x = b_old; CHOL(free_dense)(&b, &Common); CHOL(free_factor)(&L, &Common); return Py_BuildValue(""); }
static PyObject* solve(PyObject *self, PyObject *args, PyObject *kwrds) { matrix *B; PyObject *F; int i, n, oB=0, ldB=0, nrhs=-1, sys=0; #if PY_MAJOR_VERSION >= 3 const char *descr; #else char *descr; #endif char *kwlist[] = {"F", "B", "sys", "nrhs", "ldB", "offsetB", 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|iiii", kwlist, &F, &B, &sys, &nrhs, &ldB, &oB)) 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"); 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"); 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 (!Matrix_Check(B) || MAT_ID(B) == INT || (MAT_ID(B) == DOUBLE && L->xtype == CHOLMOD_COMPLEX) || (MAT_ID(B) == COMPLEX && L->xtype == CHOLMOD_REAL)) PY_ERR_TYPE("B must a dense matrix of the same numerical " "type as F"); if (nrhs < 0) nrhs = MAT_NCOLS(B); if (n == 0 || nrhs == 0) return Py_BuildValue(""); if (ldB == 0) ldB = MAX(1,MAT_NROWS(B)); if (ldB < MAX(1,n)) err_ld("ldB"); if (oB < 0) err_nn_int("offsetB"); if (oB + (nrhs-1)*ldB + n > MAT_LGT(B)) err_buf_len("B"); cholmod_dense *x; cholmod_dense *b = CHOL(allocate_dense)(n, 1, n, (MAT_ID(B) == DOUBLE ? CHOLMOD_REAL : CHOLMOD_COMPLEX), &Common); if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory(); void *b_old = b->x; for (i=0; i<nrhs; i++){ b->x = MAT_BUF(B) + (i*ldB + oB)*E_SIZE[MAT_ID(B)]; x = CHOL(solve) (sysvalues[sys], L, b, &Common); if (Common.status != CHOLMOD_OK){ PyErr_SetString(PyExc_ValueError, "solve step failed"); CHOL(free_dense)(&x, &Common); CHOL(free_dense)(&b, &Common); return NULL; } memcpy(b->x, x->x, n*E_SIZE[MAT_ID(B)]); CHOL(free_dense)(&x, &Common); } b->x = b_old; CHOL(free_dense)(&b, &Common); return Py_BuildValue(""); }
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_write (PyObject *self, PyObject *args, PyObject *kwrds) { int i,Il,Jl,Bl,Ml; int_t n; spmatrix *A; matrix *b,*bstruct; PyObject *f; PyObject *neg = Py_False; char *kwlist[] = {"f","A","b","bstruct","neg",NULL}; const char* fname; double v; if (!PyArg_ParseTupleAndKeywords(args,kwrds, "OOOO|O", kwlist, &f, &A, &b, &bstruct,&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) { Py_DECREF(f); return NULL; } fprintf(fp,"* sparse SDPA data file (created by SMCP)\n"); fprintf(fp,"%i = m\n",(int) MAT_NROWS(b)); fprintf(fp,"%i = nBlocks\n", (int) MAT_NROWS(bstruct)); // compute n and write blockstruct n = 0; for (i=0;i<MAT_NROWS(bstruct);i++) { fprintf(fp,"%i ", (int) MAT_BUFI(bstruct)[i]); n += (int_t) labs(MAT_BUFI(bstruct)[i]); } fprintf(fp,"\n"); // write vector b if (neg == Py_True) { for (i=0;i<MAT_NROWS(b);i++) fprintf(fp,"%.12g ",-MAT_BUFD(b)[i]); } else { for (i=0;i<MAT_NROWS(b);i++) fprintf(fp,"%.12g ",MAT_BUFD(b)[i]); } fprintf(fp,"\n"); // Write data matrices A0,A1,A2,...,Am for (Ml=0;Ml<=MAT_NROWS(b);Ml++) { for (i=0;i<SP_COL(A)[Ml+1]-SP_COL(A)[Ml];i++){ Jl = 1 + SP_ROW(A)[SP_COL(A)[Ml]+i] / n; Il = 1 + SP_ROW(A)[SP_COL(A)[Ml]+i] % n; // Skip if element is in strict upper triangle if (Jl > Il) PyErr_Warn(PyExc_Warning,"Ignored strictly upper triangular element."); Bl = 1; while ((Il > labs(MAT_BUFI(bstruct)[Bl-1])) && (Jl > labs(MAT_BUFI(bstruct)[Bl-1]))) { Il -= (int_t) labs(MAT_BUFI(bstruct)[Bl-1]); Jl -= (int_t) labs(MAT_BUFI(bstruct)[Bl-1]); Bl += 1; } /* Error check */ if ((Il > labs(MAT_BUFI(bstruct)[Bl-1])) || (Jl > labs(MAT_BUFI(bstruct)[Bl-1]))) printf("Error: Matrix contains elements outside blocks!\n"); // print upper triangle entries: // <matno> <blkno> <i> <j> <entry> v = SP_VALD(A)[SP_COL(A)[Ml]+i]; if ( v != 0.0) { if (neg == Py_True) fprintf(fp,"%i %i %i %i %.12g\n", (int) Ml,(int) Bl,(int) Jl,(int) Il, -v); else fprintf(fp,"%i %i %i %i %.12g\n", (int) Ml,(int) Bl,(int) Jl,(int) Il, v); } } } fclose(fp); Py_DECREF(f); Py_RETURN_NONE; }
static PyObject *integer(PyObject *self, PyObject *args, PyObject *kwrds) { matrix *c, *h, *b=NULL, *x=NULL; PyObject *G, *A=NULL, *IntSet=NULL, *BinSet = NULL; PyObject *t=NULL; pyiocp *iocpParm = NULL;; glp_iocp *options = NULL; glp_prob *lp; int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL; double *a=NULL, val; char *kwlist[] = {"c", "G", "h", "A", "b", "I", "B","iocp", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|OOOOO!", kwlist, &c, &G, &h, &A, &b, &IntSet, &BinSet,iocp_t,&iocpParm)) return NULL; if(!iocpParm) { iocpParm = (pyiocp*)malloc(sizeof(*iocpParm)); glp_init_iocp(&(iocpParm->obj)); } if(iocpParm) { Py_INCREF(iocpParm); options = &iocpParm->obj; options->presolve = 1; } if ((Matrix_Check(G) && MAT_ID(G) != DOUBLE) || (SpMatrix_Check(G) && SP_ID(G) != DOUBLE) || (!Matrix_Check(G) && !SpMatrix_Check(G))){ PyErr_SetString(PyExc_TypeError, "G must be a 'd' matrix"); return NULL; } if ((m = Matrix_Check(G) ? MAT_NROWS(G) : SP_NROWS(G)) <= 0) err_p_int("m"); if ((n = Matrix_Check(G) ? MAT_NCOLS(G) : SP_NCOLS(G)) <= 0) err_p_int("n"); if (!Matrix_Check(h) || h->id != DOUBLE) err_dbl_mtrx("h"); if (h->nrows != m || h->ncols != 1){ PyErr_SetString(PyExc_ValueError, "incompatible dimensions"); return NULL; } if (A){ if ((Matrix_Check(A) && MAT_ID(A) != DOUBLE) || (SpMatrix_Check(A) && SP_ID(A) != DOUBLE) || (!Matrix_Check(A) && !SpMatrix_Check(A))){ PyErr_SetString(PyExc_ValueError, "A must be a dense " "'d' matrix or a general sparse matrix"); return NULL; } if ((p = Matrix_Check(A) ? MAT_NROWS(A) : SP_NROWS(A)) < 0) err_p_int("p"); if ((Matrix_Check(A) ? MAT_NCOLS(A) : SP_NCOLS(A)) != n){ PyErr_SetString(PyExc_ValueError, "incompatible " "dimensions"); return NULL; } } else p = 0; if (b && (!Matrix_Check(b) || b->id != DOUBLE)) err_dbl_mtrx("b"); if ((b && (b->nrows != p || b->ncols != 1)) || (!b && p !=0 )){ PyErr_SetString(PyExc_ValueError, "incompatible dimensions"); return NULL; } if ((IntSet) && (!PyAnySet_Check(IntSet))) PY_ERR_TYPE("invalid integer index set"); if ((BinSet) && (!PyAnySet_Check(BinSet))) PY_ERR_TYPE("invalid binary index set"); lp = glp_create_prob(); glp_add_rows(lp, m+p); glp_add_cols(lp, n); for (i=0; i<n; i++){ glp_set_obj_coef(lp, i+1, MAT_BUFD(c)[i]); glp_set_col_bnds(lp, i+1, GLP_FR, 0.0, 0.0); } for (i=0; i<m; i++) glp_set_row_bnds(lp, i+1, GLP_UP, 0.0, MAT_BUFD(h)[i]); for (i=0; i<p; i++) glp_set_row_bnds(lp, i+m+1, GLP_FX, MAT_BUFD(b)[i], MAT_BUFD(b)[i]); nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) + ((A && SpMatrix_Check(A)) ? SP_NNZ(A) : p*n); a = (double *) calloc(nnzmax+1, sizeof(double)); rn = (int *) calloc(nnzmax+1, sizeof(int)); cn = (int *) calloc(nnzmax+1, sizeof(int)); if (!a || !rn || !cn){ free(a); free(rn); free(cn); glp_delete_prob(lp); return PyErr_NoMemory(); } nnz = 0; if (SpMatrix_Check(G)) { for (j=0; j<n; j++) for (k=SP_COL(G)[j]; k<SP_COL(G)[j+1]; k++) if ((val = SP_VALD(G)[k]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = SP_ROW(G)[k]+1; cn[1+nnz] = j+1; nnz++; } } else for (j=0; j<n; j++) for (i=0; i<m; i++) if ((val = MAT_BUFD(G)[i+j*m]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = i+1; cn[1+nnz] = j+1; nnz++; } if (A && SpMatrix_Check(A)){ for (j=0; j<n; j++) for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1]; k++) if ((val = SP_VALD(A)[k]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = m+SP_ROW(A)[k]+1; cn[1+nnz] = j+1; nnz++; } } else for (j=0; j<n; j++) for (i=0; i<p; i++) if ((val = MAT_BUFD(A)[i+j*p]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = m+i+1; cn[1+nnz] = j+1; nnz++; } glp_load_matrix(lp, nnz, rn, cn, a); free(rn); free(cn); free(a); if (!(t = PyTuple_New(2))) { glp_delete_prob(lp); return PyErr_NoMemory(); } if (IntSet) { PyObject *iter = PySequence_Fast(IntSet, "Critical error: not sequence"); for (i=0; i<PySet_GET_SIZE(IntSet); i++) { PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i); #if PY_MAJOR_VERSION >= 3 if (!PyLong_Check(tmp)) { #else if (!PyInt_Check(tmp)) { #endif glp_delete_prob(lp); Py_DECREF(iter); PY_ERR_TYPE("non-integer element in I"); } #if PY_MAJOR_VERSION >= 3 int k = PyLong_AS_LONG(tmp); #else int k = PyInt_AS_LONG(tmp); #endif if ((k < 0) || (k >= n)) { glp_delete_prob(lp); Py_DECREF(iter); PY_ERR(PyExc_IndexError, "index element out of range in I"); } glp_set_col_kind(lp, k+1, GLP_IV); } Py_DECREF(iter); } if (BinSet) { PyObject *iter = PySequence_Fast(BinSet, "Critical error: not sequence"); for (i=0; i<PySet_GET_SIZE(BinSet); i++) { PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i); #if PY_MAJOR_VERSION >= 3 if (!PyLong_Check(tmp)) { #else if (!PyInt_Check(tmp)) { #endif glp_delete_prob(lp); Py_DECREF(iter); PY_ERR_TYPE("non-binary element in I"); } #if PY_MAJOR_VERSION >= 3 int k = PyLong_AS_LONG(tmp); #else int k = PyInt_AS_LONG(tmp); #endif if ((k < 0) || (k >= n)) { glp_delete_prob(lp); Py_DECREF(iter); PY_ERR(PyExc_IndexError, "index element out of range in B"); } glp_set_col_kind(lp, k+1, GLP_BV); } Py_DECREF(iter); } switch (glp_intopt(lp,options)){ case 0: x = (matrix *) Matrix_New(n,1,DOUBLE); if (!x) { Py_XDECREF(iocpParm); Py_XDECREF(t); glp_delete_prob(lp); return PyErr_NoMemory(); } set_output_string(t,"optimal"); set_output_string(t,"optimal"); for (i=0; i<n; i++) MAT_BUFD(x)[i] = glp_mip_col_val(lp, i+1); PyTuple_SET_ITEM(t, 1, (PyObject *) x); Py_XDECREF(iocpParm); glp_delete_prob(lp); return (PyObject *) t; case GLP_ETMLIM: x = (matrix *) Matrix_New(n,1,DOUBLE); if (!x) { Py_XDECREF(t); Py_XDECREF(iocpParm); glp_delete_prob(lp); return PyErr_NoMemory(); } set_output_string(t,"time limit exceeded"); for (i=0; i<n; i++) MAT_BUFD(x)[i] = glp_mip_col_val(lp, i+1); PyTuple_SET_ITEM(t, 1, (PyObject *) x); Py_XDECREF(iocpParm); glp_delete_prob(lp); return (PyObject *) t; case GLP_EBOUND: set_output_string(t,"incorrect bounds"); break; case GLP_EFAIL: set_output_string(t,"invalid MIP formulation"); break; case GLP_ENOPFS: set_output_string(t,"primal infeasible"); break; case GLP_ENODFS: set_output_string(t,"dual infeasible"); break; case GLP_EMIPGAP: set_output_string(t,"Relative mip gap tolerance reached"); break; /*case LPX_E_ITLIM: set_output_string(t,"maxiters exceeded"); break;*/ /*case LPX_E_SING: set_output_string(t,"singular or ill-conditioned basis"); break;*/ default: set_output_string(t,"unknown"); } Py_XDECREF(iocpParm); glp_delete_prob(lp); PyTuple_SET_ITEM(t, 1, Py_BuildValue("")); return (PyObject *) t; } static PyMethodDef glpk_functions[] = { {"lp", (PyCFunction) simplex, METH_VARARGS|METH_KEYWORDS, doc_simplex}, {"ilp", (PyCFunction) integer, METH_VARARGS|METH_KEYWORDS, doc_integer}, {NULL} /* Sentinel */ }; #if PY_MAJOR_VERSION >= 3 static PyModuleDef glpk_module_def = { PyModuleDef_HEAD_INIT, "glpk", glpk__doc__, -1, glpk_functions, NULL, NULL, NULL, NULL }; void addglpkConstants (void) { PyModule_AddIntMacro(glpk_module, GLP_ON); PyModule_AddIntMacro(glpk_module,GLP_OFF); /* reason codes: */ PyModule_AddIntMacro(glpk_module,GLP_IROWGEN); PyModule_AddIntMacro(glpk_module,GLP_IBINGO); PyModule_AddIntMacro(glpk_module,GLP_IHEUR); PyModule_AddIntMacro(glpk_module,GLP_ICUTGEN); PyModule_AddIntMacro(glpk_module,GLP_IBRANCH); PyModule_AddIntMacro(glpk_module,GLP_ISELECT); PyModule_AddIntMacro(glpk_module,GLP_IPREPRO); /* branch selection indicator: */ PyModule_AddIntMacro(glpk_module,GLP_NO_BRNCH); PyModule_AddIntMacro(glpk_module,GLP_DN_BRNCH); PyModule_AddIntMacro(glpk_module,GLP_UP_BRNCH); /* return codes: */ PyModule_AddIntMacro(glpk_module,GLP_EBADB); PyModule_AddIntMacro(glpk_module,GLP_ESING); PyModule_AddIntMacro(glpk_module,GLP_ECOND); PyModule_AddIntMacro(glpk_module,GLP_EBOUND); PyModule_AddIntMacro(glpk_module,GLP_EFAIL); PyModule_AddIntMacro(glpk_module,GLP_EOBJLL); PyModule_AddIntMacro(glpk_module,GLP_EOBJUL); PyModule_AddIntMacro(glpk_module,GLP_EITLIM); PyModule_AddIntMacro(glpk_module,GLP_ETMLIM); PyModule_AddIntMacro(glpk_module,GLP_ENOPFS); PyModule_AddIntMacro(glpk_module,GLP_ENODFS); PyModule_AddIntMacro(glpk_module,GLP_EROOT); PyModule_AddIntMacro(glpk_module,GLP_ESTOP); PyModule_AddIntMacro(glpk_module,GLP_EMIPGAP); PyModule_AddIntMacro(glpk_module,GLP_ENOFEAS); PyModule_AddIntMacro(glpk_module,GLP_ENOCVG); PyModule_AddIntMacro(glpk_module,GLP_EINSTAB); PyModule_AddIntMacro(glpk_module,GLP_EDATA); PyModule_AddIntMacro(glpk_module,GLP_ERANGE); /* condition indicator: */ PyModule_AddIntMacro(glpk_module,GLP_KKT_PE); PyModule_AddIntMacro(glpk_module,GLP_KKT_PB); PyModule_AddIntMacro(glpk_module,GLP_KKT_DE); PyModule_AddIntMacro(glpk_module,GLP_KKT_DB); PyModule_AddIntMacro(glpk_module,GLP_KKT_CS); /* MPS file format: */ PyModule_AddIntMacro(glpk_module,GLP_MPS_DECK); PyModule_AddIntMacro(glpk_module,GLP_MPS_FILE); /* simplex method control parameters */ /* message level: */ PyModule_AddIntMacro(glpk_module,GLP_MSG_OFF); PyModule_AddIntMacro(glpk_module,GLP_MSG_ERR); PyModule_AddIntMacro(glpk_module,GLP_MSG_ON); PyModule_AddIntMacro(glpk_module,GLP_MSG_ALL); PyModule_AddIntMacro(glpk_module,GLP_MSG_DBG); /* simplex method option: */ PyModule_AddIntMacro(glpk_module,GLP_PRIMAL); PyModule_AddIntMacro(glpk_module,GLP_DUALP); PyModule_AddIntMacro(glpk_module,GLP_DUAL); /* pricing technique: */ PyModule_AddIntMacro(glpk_module,GLP_PT_STD); PyModule_AddIntMacro(glpk_module,GLP_PT_PSE); /* ratio test technique: */ PyModule_AddIntMacro(glpk_module,GLP_RT_STD); PyModule_AddIntMacro(glpk_module,GLP_RT_HAR); /* interior-point solver control parameters */ /* ordering algorithm: */ PyModule_AddIntMacro(glpk_module,GLP_ORD_NONE); PyModule_AddIntMacro(glpk_module,GLP_ORD_QMD); PyModule_AddIntMacro(glpk_module,GLP_ORD_AMD); PyModule_AddIntMacro(glpk_module,GLP_ORD_SYMAMD); } PyMODINIT_FUNC PyInit_glpk(void) { if (!(glpk_module = PyModule_Create(&glpk_module_def))) return NULL; if (PyType_Ready(&iocp_t) < 0 || (PyType_Ready(&smcp_t) < 0)) return NULL; /* Adding macros */ addglpkConstants(); /* Adding option lists as objects */ Py_INCREF(&smcp_t); PyModule_AddObject(glpk_module,"smcp",(PyObject*)&smcp_t); Py_INCREF(&iocp_t); PyModule_AddObject(glpk_module,"iocp",(PyObject*)&iocp_t); if (import_cvxopt() < 0) return NULL; return glpk_module; } #else PyMODINIT_FUNC initglpk(void) { glpk_module = Py_InitModule3("cvxopt.glpk", glpk_functions, glpk__doc__); if (PyType_Ready(&iocp_t) < 0 || (PyType_Ready(&smcp_t) < 0)) return NULL; addglpkConstants(); Py_INCREF(&smcp_t); PyModule_AddObject(glpk_module,"smcp",(PyObject*)&smcp_t); Py_INCREF(&iocp_t); PyModule_AddObject(glpk_module,"iocp",(PyObject*)&iocp_t); if (import_cvxopt() < 0) return; }
static PyObject *simplex(PyObject *self, PyObject *args, PyObject *kwrds) { matrix *c, *h, *b=NULL, *x=NULL, *z=NULL, *y=NULL; PyObject *G, *A=NULL, *t=NULL; glp_prob *lp; glp_smcp *options = NULL; pysmcp *smcpParm = NULL; int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL; double *a=NULL, val; char *kwlist[] = {"c", "G", "h", "A", "b","options", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|OOO!", kwlist, &c, &G, &h, &A, &b,&smcp_t,&smcpParm)) return NULL; if ((Matrix_Check(G) && MAT_ID(G) != DOUBLE) || (SpMatrix_Check(G) && SP_ID(G) != DOUBLE) || (!Matrix_Check(G) && !SpMatrix_Check(G))){ PyErr_SetString(PyExc_TypeError, "G must be a 'd' matrix"); return NULL; } if ((m = Matrix_Check(G) ? MAT_NROWS(G) : SP_NROWS(G)) <= 0) err_p_int("m"); if ((n = Matrix_Check(G) ? MAT_NCOLS(G) : SP_NCOLS(G)) <= 0) err_p_int("n"); if (!Matrix_Check(h) || h->id != DOUBLE) err_dbl_mtrx("h"); if (h->nrows != m || h->ncols != 1){ PyErr_SetString(PyExc_ValueError, "incompatible dimensions"); return NULL; } if (A){ if ((Matrix_Check(A) && MAT_ID(A) != DOUBLE) || (SpMatrix_Check(A) && SP_ID(A) != DOUBLE) || (!Matrix_Check(A) && !SpMatrix_Check(A))){ PyErr_SetString(PyExc_ValueError, "A must be a dense " "'d' matrix or a general sparse matrix"); return NULL; } if ((p = Matrix_Check(A) ? MAT_NROWS(A) : SP_NROWS(A)) < 0) err_p_int("p"); if ((Matrix_Check(A) ? MAT_NCOLS(A) : SP_NCOLS(A)) != n){ PyErr_SetString(PyExc_ValueError, "incompatible " "dimensions"); return NULL; } } else p = 0; if (b && (!Matrix_Check(b) || b->id != DOUBLE)) err_dbl_mtrx("b"); if ((b && (b->nrows != p || b->ncols != 1)) || (!b && p !=0 )){ PyErr_SetString(PyExc_ValueError, "incompatible dimensions"); return NULL; } if(!smcpParm) { smcpParm = (pysmcp*)malloc(sizeof(*smcpParm)); glp_init_smcp(&(smcpParm->obj)); } if(smcpParm) { Py_INCREF(smcpParm); options = &smcpParm->obj; options->presolve = 1; } lp = glp_create_prob(); glp_add_rows(lp, m+p); glp_add_cols(lp, n); for (i=0; i<n; i++){ glp_set_obj_coef(lp, i+1, MAT_BUFD(c)[i]); glp_set_col_bnds(lp, i+1, GLP_FR, 0.0, 0.0); } for (i=0; i<m; i++) glp_set_row_bnds(lp, i+1, GLP_UP, 0.0, MAT_BUFD(h)[i]); for (i=0; i<p; i++) glp_set_row_bnds(lp, i+m+1, GLP_FX, MAT_BUFD(b)[i], MAT_BUFD(b)[i]); nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) + ((A && SpMatrix_Check(A)) ? SP_NNZ(A) : p*n); a = (double *) calloc(nnzmax+1, sizeof(double)); rn = (int *) calloc(nnzmax+1, sizeof(int)); cn = (int *) calloc(nnzmax+1, sizeof(int)); if (!a || !rn || !cn){ free(a); free(rn); free(cn); glp_delete_prob(lp); return PyErr_NoMemory(); } nnz = 0; if (SpMatrix_Check(G)) { for (j=0; j<n; j++) for (k=SP_COL(G)[j]; k<SP_COL(G)[j+1]; k++) if ((val = SP_VALD(G)[k]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = SP_ROW(G)[k]+1; cn[1+nnz] = j+1; nnz++; } } else for (j=0; j<n; j++) for (i=0; i<m; i++) if ((val = MAT_BUFD(G)[i+j*m]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = i+1; cn[1+nnz] = j+1; nnz++; } if (A && SpMatrix_Check(A)){ for (j=0; j<n; j++) for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1]; k++) if ((val = SP_VALD(A)[k]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = m+SP_ROW(A)[k]+1; cn[1+nnz] = j+1; nnz++; } } else for (j=0; j<n; j++) for (i=0; i<p; i++) if ((val = MAT_BUFD(A)[i+j*p]) != 0.0){ a[1+nnz] = val; rn[1+nnz] = m+i+1; cn[1+nnz] = j+1; nnz++; } glp_load_matrix(lp, nnz, rn, cn, a); free(rn); free(cn); free(a); if (!(t = PyTuple_New(A ? 4 : 3))){ glp_delete_prob(lp); return PyErr_NoMemory(); } switch (glp_simplex(lp,options)){ case 0: x = (matrix *) Matrix_New(n,1,DOUBLE); z = (matrix *) Matrix_New(m,1,DOUBLE); if (A) y = (matrix *) Matrix_New(p,1,DOUBLE); if (!x || !z || (A && !y)){ Py_XDECREF(x); Py_XDECREF(z); Py_XDECREF(y); Py_XDECREF(t); Py_XDECREF(smcpParm); glp_delete_prob(lp); return PyErr_NoMemory(); } set_output_string(t,"optimal"); for (i=0; i<n; i++) MAT_BUFD(x)[i] = glp_get_col_prim(lp, i+1); PyTuple_SET_ITEM(t, 1, (PyObject *) x); for (i=0; i<m; i++) MAT_BUFD(z)[i] = -glp_get_row_dual(lp, i+1); PyTuple_SET_ITEM(t, 2, (PyObject *) z); if (A){ for (i=0; i<p; i++) MAT_BUFD(y)[i] = -glp_get_row_dual(lp, m+i+1); PyTuple_SET_ITEM(t, 3, (PyObject *) y); } Py_XDECREF(smcpParm); glp_delete_prob(lp); return (PyObject *) t; case GLP_EBADB: set_output_string(t,"incorrect initial basis"); break; case GLP_ESING: set_output_string(t,"singular initial basis matrix"); break; case GLP_ECOND: set_output_string(t,"ill-conditioned initial basis matrix"); break; case GLP_EBOUND: set_output_string(t,"incorrect bounds"); break; case GLP_EFAIL: set_output_string(t,"solver failure"); break; case GLP_EOBJLL: set_output_string(t,"objective function reached lower limit"); break; case GLP_EOBJUL: set_output_string(t,"objective function reached upper limit"); break; case GLP_EITLIM: set_output_string(t,"iteration limit exceeded"); break; case GLP_ETMLIM: set_output_string(t,"time limit exceeded"); break; case GLP_ENOPFS: set_output_string(t,"primal infeasible"); break; case GLP_ENODFS: set_output_string(t,"dual infeasible"); break; default: set_output_string(t,"unknown"); break; } Py_XDECREF(smcpParm); glp_delete_prob(lp); PyTuple_SET_ITEM(t, 1, Py_BuildValue("")); PyTuple_SET_ITEM(t, 2, Py_BuildValue("")); if (A) PyTuple_SET_ITEM(t, 3, Py_BuildValue("")); return (PyObject *) t; }