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* 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* linsolve(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *A; matrix *B; #if PY_MAJOR_VERSION >= 3 int trans_ = 'N'; #endif char trans='N'; double info[UMFPACK_INFO]; int oB=0, n, nrhs=-1, ldB=0, k; void *symbolic, *numeric, *x; char *kwlist[] = {"A", "B", "trans", "nrhs", "ldB", "offsetB", NULL}; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ciii", kwlist, &A, &B, &trans_, &nrhs, &ldB, &oB)) return NULL; trans = (char) trans_; #else if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist, &A, &B, &trans, &nrhs, &ldB, &oB)) return NULL; #endif if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) PY_ERR_TYPE("A must be a square sparse matrix"); n = SP_NROWS(A); if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A)) PY_ERR_TYPE("B must a dense matrix of the same numeric type " "as A"); if (nrhs < 0) nrhs = B->ncols; if (n == 0 || nrhs == 0) return Py_BuildValue("i", 0); if (ldB == 0) ldB = MAX(1,B->nrows); 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 (trans != 'N' && trans != 'T' && trans != 'C') err_char("trans", "'N', 'T', 'C'"); if (SP_ID(A) == DOUBLE) UMFD(symbolic)(n, n, SP_COL(A), SP_ROW(A), SP_VAL(A), &symbolic, NULL, info); else UMFZ(symbolic)(n, n, SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, &symbolic, NULL, info); if (info[UMFPACK_STATUS] != UMFPACK_OK){ if (SP_ID(A) == DOUBLE) UMFD(free_symbolic)(&symbolic); else UMFZ(free_symbolic)(&symbolic); if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory) return PyErr_NoMemory(); else { snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR", (int) info[UMFPACK_STATUS]); PyErr_SetString(PyExc_ValueError, umfpack_error); return NULL; } } if (SP_ID(A) == DOUBLE) { UMFD(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), symbolic, &numeric, NULL, info); UMFD(free_symbolic)(&symbolic); } else { UMFZ(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, symbolic, &numeric, NULL, info); UMFZ(free_symbolic)(&symbolic); } if (info[UMFPACK_STATUS] != UMFPACK_OK){ if (SP_ID(A) == DOUBLE) UMFD(free_numeric)(&numeric); else UMFZ(free_numeric)(&numeric); if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory) return PyErr_NoMemory(); else { if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix) PyErr_SetString(PyExc_ArithmeticError, "singular " "matrix"); else { snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR", (int) info[UMFPACK_STATUS]); PyErr_SetString(PyExc_ValueError, umfpack_error); } return NULL; } } if (!(x = malloc(n*E_SIZE[SP_ID(A)]))) { if (SP_ID(A) == DOUBLE) UMFD(free_numeric)(&numeric); else UMFZ(free_numeric)(&numeric); return PyErr_NoMemory(); } for (k=0; k<nrhs; k++){ if (SP_ID(A) == DOUBLE) UMFD(solve)(trans == 'N' ? UMFPACK_A: UMFPACK_Aat, SP_COL(A), SP_ROW(A), SP_VAL(A), x, MAT_BUFD(B) + k*ldB + oB, numeric, NULL, info); else UMFZ(solve)(trans == 'N' ? UMFPACK_A: trans == 'C' ? UMFPACK_At : UMFPACK_Aat, SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, x, NULL, (double *)(MAT_BUFZ(B) + k*ldB + oB), NULL, numeric, NULL, info); if (info[UMFPACK_STATUS] == UMFPACK_OK) memcpy(B->buffer + (k*ldB + oB)*E_SIZE[SP_ID(A)], x, n*E_SIZE[SP_ID(A)]); else break; } free(x); if (SP_ID(A) == DOUBLE) UMFD(free_numeric)(&numeric); else UMFZ(free_numeric)(&numeric); if (info[UMFPACK_STATUS] != UMFPACK_OK){ if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory) return PyErr_NoMemory(); else { if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix) PyErr_SetString(PyExc_ArithmeticError, "singular " "matrix"); else { snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR", (int) info[UMFPACK_STATUS]); PyErr_SetString(PyExc_ValueError, umfpack_error); } return NULL; } } return Py_BuildValue(""); }
static PyObject* symbolic(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *A; cholmod_sparse *Ac = NULL; cholmod_factor *L; matrix *P=NULL; #if PY_MAJOR_VERSION >= 3 int uplo_='L'; #endif char uplo='L'; int n; char *kwlist[] = {"A", "p", "uplo", NULL}; if (!set_options()) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|OC", kwlist, &A, &P, &uplo_)) return NULL; uplo = (char) uplo_; #else if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|Oc", kwlist, &A, &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); 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, "p is 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); CHOL(free_sparse)(&Ac, &Common); if (Common.status != CHOLMOD_OK){ if (Common.status == CHOLMOD_OUT_OF_MEMORY) return PyErr_NoMemory(); else{ PyErr_SetString(PyExc_ValueError, "symbolic factorization " "failed"); return NULL; } } #if PY_MAJOR_VERSION >= 3 return (PyObject *) PyCapsule_New((void *) L, SP_ID(A)==DOUBLE ? (uplo == 'L' ? "CHOLMOD FACTOR D L" : "CHOLMOD FACTOR D U") : (uplo == 'L' ? "CHOLMOD FACTOR Z L" : "CHOLMOD FACTOR Z U"), (PyCapsule_Destructor) &cvxopt_free_cholmod_factor); #else return (PyObject *) PyCObject_FromVoidPtrAndDesc((void *) L, SP_ID(A)==DOUBLE ? (uplo == 'L' ? "CHOLMOD FACTOR D L" : "CHOLMOD FACTOR D U") : (uplo == 'L' ? "CHOLMOD FACTOR Z L" : "CHOLMOD FACTOR Z U"), cvxopt_free_cholmod_factor); #endif }
static int set_defaults(double *control) { int_t pos=0; int param_id; PyObject *param, *key, *value; #if PY_MAJOR_VERSION < 3 char *keystr; #endif char err_str[100]; amd_defaults(control); if (!(param = PyObject_GetAttrString(amd_module, "options")) || !PyDict_Check(param)){ PyErr_SetString(PyExc_AttributeError, "missing amd.options" "dictionary"); return 0; } while (PyDict_Next(param, &pos, &key, &value)) #if PY_MAJOR_VERSION >= 3 if ((PyUnicode_Check(key)) && get_param_idx(_PyUnicode_AsString(key),¶m_id)) { if (!PyLong_Check(value) && !PyFloat_Check(value)){ sprintf(err_str, "invalid value for AMD parameter: %-.20s", _PyUnicode_AsString(key)); #else if ((keystr = PyString_AsString(key)) && get_param_idx(keystr, ¶m_id)) { if (!PyInt_Check(value) && !PyFloat_Check(value)){ sprintf(err_str, "invalid value for AMD parameter: " "%-.20s", keystr); #endif PyErr_SetString(PyExc_ValueError, err_str); Py_DECREF(param); return 0; } control[param_id] = PyFloat_AsDouble(value); } Py_DECREF(param); return 1; } static char doc_order[] = "Computes the approximate minimum degree ordering of a square " "matrix.\n\n" "p = order(A, uplo='L')\n\n" "PURPOSE\n" "Computes a permutation p that reduces fill-in in the Cholesky\n" "factorization of A[p,p].\n\n" "ARGUMENTS\n" "A square sparse matrix\n\n" "uplo 'L' or 'U'. If uplo is 'L', the lower triangular part\n" " of A is used and the upper triangular is ignored. If\n" " uplo is 'U', the upper triangular part is used and the\n" " lower triangular part is ignored.\n\n" "p 'i' matrix of length equal to the order of A"; static PyObject* order_c(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *A; matrix *perm; #if PY_MAJOR_VERSION >= 3 int uplo_ = 'L'; #endif char uplo = 'L'; int j, k, n, nnz, alloc=0, info; int_t *rowind=NULL, *colptr=NULL; double control[AMD_CONTROL]; char *kwlist[] = {"A", "uplo", NULL}; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|C", kwlist, &A, &uplo_)) return NULL; uplo = (char) uplo_; #else if (!PyArg_ParseTupleAndKeywords(args, kwrds, "O|c", kwlist, &A, &uplo)) return NULL; #endif if (!set_defaults(control)) return NULL; if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)){ PyErr_SetString(PyExc_TypeError, "A must be a square sparse " "matrix"); return NULL; } if (uplo != 'U' && uplo != 'L') err_char("uplo", "'L', 'U'"); if (!(perm = (matrix *) Matrix_New((int)SP_NROWS(A),1,INT))) return PyErr_NoMemory(); n = SP_NROWS(A); for (nnz=0, j=0; j<n; j++) { if (uplo == 'L'){ for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k]<j; k++); nnz += SP_COL(A)[j+1] - k; } else { for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j; k++); nnz += k - SP_COL(A)[j]; } } if (nnz == SP_NNZ(A)){ colptr = (int_t *) SP_COL(A); rowind = (int_t *) SP_ROW(A); } else { alloc = 1; colptr = (int_t *) calloc(n+1, sizeof(int_t)); rowind = (int_t *) calloc(nnz, sizeof(int_t)); if (!colptr || !rowind) { Py_XDECREF(perm); free(colptr); free(rowind); return PyErr_NoMemory(); } colptr[0] = 0; for (j=0; j<n; j++) { if (uplo == 'L'){ for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] < j; k++); nnz = SP_COL(A)[j+1] - k; colptr[j+1] = colptr[j] + nnz; memcpy(rowind + colptr[j], (int_t *) SP_ROW(A) + k, nnz*sizeof(int_t)); } else { for (k=SP_COL(A)[j]; k<SP_COL(A)[j+1] && SP_ROW(A)[k] <= j; k++); nnz = k - SP_COL(A)[j]; colptr[j+1] = colptr[j] + nnz; memcpy(rowind + colptr[j], (int_t *) (SP_ROW(A) + SP_COL(A)[j]), nnz*sizeof(int_t)); } } } info = amd_order(n, colptr, rowind, MAT_BUFI(perm), control, NULL); if (alloc){ free(colptr); free(rowind); } switch (info) { case AMD_OUT_OF_MEMORY: Py_XDECREF(perm); return PyErr_NoMemory(); case AMD_INVALID: Py_XDECREF(perm); return Py_BuildValue(""); case AMD_OK: return (PyObject *) perm; } return Py_BuildValue(""); } static PyMethodDef amd_functions[] = { {"order", (PyCFunction) order_c, METH_VARARGS|METH_KEYWORDS, doc_order}, {NULL} /* Sentinel */ }; #if PY_MAJOR_VERSION >= 3 static PyModuleDef amd_module_def = { PyModuleDef_HEAD_INIT, "amd", amd__doc__, -1, amd_functions, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit_amd(void) { if (!(amd_module = PyModule_Create(&amd_module_def))) return NULL; PyModule_AddObject(amd_module, "options", PyDict_New()); if (import_cvxopt() < 0) return NULL; return amd_module; } #else PyMODINIT_FUNC initamd(void) { amd_module = Py_InitModule3("cvxopt.amd", amd_functions, amd__doc__); PyModule_AddObject(amd_module, "options", PyDict_New()); if (import_cvxopt() < 0) return; }