Esempio n. 1
0
void CodeGenContext::GenerateDisassmTables()
{
	std::map<std::string, std::map<llvm::APInt,std::string,myAPIntCompare> >::iterator tableIter;

	for (tableIter=disassemblyTable.begin();tableIter!=disassemblyTable.end();++tableIter)
	{
		llvm::APInt tableSize=tableIter->second.rbegin()->first;
		llvm::APInt tableSize32=tableSize.zextOrTrunc(32);
		// Create a global variable to indicate the max size of the table

		llvm::ConstantInt* const_int32_1 = getConstantInt(tableSize32+1);
		llvm::GlobalVariable* gvar_int32_DIS_max = makeGlobal(getIntType(32),true,llvm::GlobalValue::ExternalLinkage,const_int32_1,getSymbolPrefix()+"DIS_max_"+tableIter->first);

		// Create a global array to hold the table
		llvm::PointerType* PointerTy_5 = llvm::PointerType::get(getIntType(8), 0);
       	llvm::ArrayType* ArrayTy_4 = llvm::ArrayType::get(PointerTy_5, tableSize.getLimitedValue()+1);
		llvm::ConstantPointerNull* const_ptr_13 = llvm::ConstantPointerNull::get(PointerTy_5);	
		std::vector<llvm::Constant*> const_array_9_elems;

		std::map<llvm::APInt,std::string,myAPIntCompare>::iterator slot=tableIter->second.begin();
		llvm::APInt trackingSlot(tableSize.getBitWidth(),"0",16);

		while (slot!=tableIter->second.end())
		{
			if (CompareEquals(slot->first,trackingSlot))
			{
				llvm::ArrayType* ArrayTy_0 = llvm::ArrayType::get(getIntType(8), slot->second.length()-1);
				llvm::Constant* const_array_9 = getString(slot->second);
				llvm::GlobalVariable* gvar_array__str = makeGlobal(ArrayTy_0,true,llvm::GlobalValue::PrivateLinkage,const_array_9,getSymbolPrefix()+".str"+trackingSlot.toString(16,false));
				gvar_array__str->setAlignment(1);
  
				std::vector<llvm::Constant*> const_ptr_12_indices;
				llvm::ConstantInt* const_int64_13 = getConstantZero(64);
				const_ptr_12_indices.push_back(const_int64_13);
				const_ptr_12_indices.push_back(const_int64_13);
				llvm::Constant* const_ptr_12 = llvm::ConstantExpr::getGetElementPtr(nullptr,gvar_array__str, const_ptr_12_indices);

				const_array_9_elems.push_back(const_ptr_12);

				++slot;
			}
			else
			{
				const_array_9_elems.push_back(const_ptr_13);
			}
			trackingSlot++;
		}

		llvm::Constant* const_array_9 = llvm::ConstantArray::get(ArrayTy_4, const_array_9_elems);
		llvm::GlobalVariable* gvar_array_table = makeGlobal(ArrayTy_4,true,llvm::GlobalValue::ExternalLinkage,const_array_9, getSymbolPrefix()+"DIS_"+tableIter->first);
	}
}
std::string prettyEval(Expr* e) {
  EvalValue result = eval(e);
  if (result.type == getIntType()) {
    return std::to_string(result.value);
  } else if (result.type == getBoolType()) {
    return result.value ? "true" : "false";
  }
  throw std::runtime_error("Illegal type state");
}
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;
}
Esempio n. 4
0
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;
}