Ejemplo n.º 1
0
/* ************************************************************
   PROCEDURE psdinvscale - Computes y = D(d^{-1})x.
   (transp == 0) Y = U\X/U'
   (transp == 1) Y = U'\X/U.
   INPUT
     x - length lenud input vector.
     ud - Cholesky factor of d for PSD part (after PERM ordering).
     psdNL - length psdN array
     rpsdN - number of real symmetric PSD blocks
     sdpN  - total number of psd blocks
     transp - boolean
   OUTPUT
     y - length lenud output vector, y=D(d)x.
   WORK
     fwork - length max(rmaxn^2,2*hmaxn^2) working vector.
   ************************************************************ */
void psdinvscale(double *y, const double *ud, const double *x,
                 const mwIndex *psdNL, const mwIndex rsdpN, const mwIndex sdpN,
                 bool transp, double *fwork)
{
  mwIndex k,nk,nksqr;
/* ------------------------------------------------------------
   PSD, !transp: triu(Y) = triu(Ld' \ (X(perm,perm) / Ld)).
   Needs ony tril(X/Ld).
   ------------------------------------------------------------ */
  if(!transp){
    for(k = 0; k < rsdpN; k++){                /* real symmetric */
      nk = psdNL[k];
      invltxl(y,ud,x,nk,fwork);
      tril2sym(y,nk);
      nksqr = SQR(nk);
      y += nksqr; ud += nksqr;
      x += nksqr;
    }
    for(; k < sdpN; k++){                    /* complex Hermitian */
      nk = psdNL[k];
      nksqr = SQR(nk);
      prpiinvltxl(y,y+nksqr,ud,ud+nksqr,x,x+nksqr,nk,fwork);
      tril2herm(y,y+nksqr,nk);
      nksqr += nksqr;
      y += nksqr; ud += nksqr;
      x += nksqr;
    }
  } /* !transp */
  else{
/* ------------------------------------------------------------
   PSD, transp: triu(Y) = triu(Ud' \ (X(perm,perm) / Ud)).
   Needs ony triu(X/Ud).
   ------------------------------------------------------------ */
    for(k = 0; k < rsdpN; k++){                /* real symmetric */
      nk = psdNL[k];
      invutxu(y,ud,x,nk,fwork);
      triu2sym(y,nk);
      nksqr = SQR(nk);
      y += nksqr; ud += nksqr;
      x += nksqr;
    }
    for(; k < sdpN; k++){                    /* complex Hermitian */
      nk = psdNL[k];
      nksqr = SQR(nk);
      prpiinvutxu(y,y+nksqr,ud,ud+nksqr,x,x+nksqr,nk,fwork);
      triu2herm(y,y+nksqr,nk);
      nksqr += nksqr;
      y += nksqr; ud += nksqr;
      x += nksqr;
    }
  }
}
Ejemplo n.º 2
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   [ux,ispos] = psdfactor(x,K);
   ************************************************************ */
void mexFunction(const int nlhs, mxArray *plhs[],
  const int nrhs, const mxArray *prhs[])
{
  mxArray *myplhs[NPAROUT];
  coneK cK;
  mwIndex k,nk,nksqr, sdplen,sdpdim,lenfull, ispos;
  const double *x;
  double *ux;
/* ------------------------------------------------------------
   Check for proper number of arguments
   ------------------------------------------------------------ */
  mxAssert(nrhs >= NPARIN, "psdfactor requires more input arguments");
  mxAssert(nlhs <= NPAROUT, "psdfactor produces less output arguments");
/* ------------------------------------------------------------
   Disassemble cone K structure
   ------------------------------------------------------------ */
  conepars(K_IN, &cK);
/* ------------------------------------------------------------
   Compute statistics: sdpdim = rdim+hdim, sdplen = sum(K.s).
   ------------------------------------------------------------ */
  lenfull = cK.lpN +  cK.qDim + cK.rDim + cK.hDim;
  sdpdim = cK.rDim + cK.hDim;
  sdplen = cK.rLen + cK.hLen;
/* ------------------------------------------------------------
   Get input vector x, skip LP + Lorentz part
   ------------------------------------------------------------ */
  x = mxGetPr(X_IN);
  if(mxGetM(X_IN) * mxGetN(X_IN) == lenfull)
    x += cK.lpN + cK.qDim;
  else mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == sdpdim, "x size mismatch.");
/* ------------------------------------------------------------
   Allocate output UX(sdpdim), ispos(1).
   ------------------------------------------------------------ */
  UX_OUT = mxCreateDoubleMatrix(sdpdim, (mwSize)1, mxREAL);
  ux = mxGetPr(UX_OUT);
  ISPOS_OUT = mxCreateDoubleMatrix((mwSize)1,(mwSize)1,mxREAL);
/* ------------------------------------------------------------
   PSD: Cholesky factorization.
   Initialize  ispos = 1 and ux = x.
   ------------------------------------------------------------ */
  ispos = 1;
  memcpy(ux, x, sdpdim * sizeof(double));       /* copy real + complex */
  for(k = 0; k < cK.rsdpN; k++){                /* real symmetric */
    nk = cK.sdpNL[k];
/* ------------------------------------------------------------
   Attempt Cholesky on block k. Returns 1 if fail (i.e. not psd).
   ------------------------------------------------------------ */
    if(cholnopiv(ux,nk)){
      ispos = 0;
      break;
    }
    triu2sym(ux,nk);
    ux += SQR(nk);
  }
/* ------------------------------------------------------------
   Complex Hermitian PSD Cholesky factorization, no pivoting.
   ------------------------------------------------------------ */
  if(ispos)
    for(; k < cK.sdpN; k++){                    /* complex Hermitian */
      nk = cK.sdpNL[k];
      nksqr = SQR(nk);
      if(prpicholnopiv(ux,ux+nksqr,nk)){
        ispos = 0;
        break;
      }
      triu2herm(ux,ux+nksqr,nk);
      ux += 2 * nksqr;
    }
/* ------------------------------------------------------------
   Return parameter ispos
   ------------------------------------------------------------ */
  *mxGetPr(ISPOS_OUT) = ispos;
/* ------------------------------------------------------------
   Copy requested output parameters (at least 1), release others.
   ------------------------------------------------------------ */
  k = MAX(nlhs, 1);
  memcpy(plhs,myplhs, k * sizeof(mxArray *));
  for(; k < NPAROUT; k++)
    mxDestroyArray(myplhs[k]);
}
Ejemplo n.º 3
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   [qdetx,ux,ispos,perm] = factorK(x,K);
   ************************************************************ */
void mexFunction(const int nlhs, mxArray *plhs[],
  const int nrhs, const mxArray *prhs[])
{
  mxArray *myplhs[NPAROUT];
  coneK cK;
  int i,k,nk,nksqr, sdplen,sdpdim,lenfull, fwsiz, ispos;
  const double *x;
  double *ux, *fwork, *permPr, *qdetx, *up, *uppi;
  int *iwork, *perm;
  double uxk;
  char use_pivot;
/* ------------------------------------------------------------
   Check for proper number of arguments
   ------------------------------------------------------------ */
  mxAssert(nrhs >= NPARIN, "factorK requires more input arguments");
  mxAssert(nlhs <= NPAROUT, "factorK produces less output arguments");
  use_pivot = (nlhs == NPAROUT);
/* ------------------------------------------------------------
   Disassemble cone K structure
   ------------------------------------------------------------ */
  conepars(K_IN, &cK);
/* ------------------------------------------------------------
   Compute statistics: sdpdim = rdim+hdim, sdplen = sum(K.s).
   ------------------------------------------------------------ */
  lenfull = cK.lpN +  cK.qDim + cK.rDim + cK.hDim;
  sdpdim = cK.rDim + cK.hDim;
  sdplen = cK.rLen + cK.hLen;
/* ------------------------------------------------------------
   Get input vector x, skip LP part
   ------------------------------------------------------------ */
  mxAssert(mxGetM(X_IN) * mxGetN(X_IN) == lenfull, "x size mismatch.");
  x = mxGetPr(X_IN) + cK.lpN;
/* ------------------------------------------------------------
   Allocate output qdetx(lorN), UX(sdpdim), perm(sdplen), ispos(1).
   ------------------------------------------------------------ */
  QDETX_OUT = mxCreateDoubleMatrix(cK.lorN, 1, mxREAL);
  qdetx = mxGetPr(QDETX_OUT);
  UX_OUT = mxCreateDoubleMatrix(sdpdim, 1, mxREAL);
  ux = mxGetPr(UX_OUT);
  ISPOS_OUT = mxCreateDoubleMatrix(1,1,mxREAL);
  PERM_OUT =  mxCreateDoubleMatrix(sdplen, 1, mxREAL);
  permPr = mxGetPr(PERM_OUT);
/* ------------------------------------------------------------
   Allocate working arrays iwork(sdplen),
   fwork(MAX(rmaxn^2,2*hmaxn^2) + MAX(rmaxn,hmaxn))
   ------------------------------------------------------------ */
  iwork = (int *) mxCalloc(sdplen, sizeof(int));
  perm = iwork;
  fwsiz = MAX(cK.rMaxn,cK.hMaxn);
  fwork = (double *) mxCalloc(fwsiz + MAX(SQR(cK.rMaxn),2*SQR(cK.hMaxn)),
                              sizeof(double));
  up = fwork + fwsiz;
  uppi = up + SQR(cK.hMaxn);
/* ------------------------------------------------------------
   LORENTZ:  qdetx = sqrt(qdet(x))
   ------------------------------------------------------------ */
  ispos = 1;
  for(k = 0; k < cK.lorN; k++){
    nk = cK.lorNL[k];
    if( (uxk = qdet(x,nk)) < 0.0){
      ispos = 0;
      break;
    }
    else
      qdetx[k] = sqrt(uxk);
    x += nk;
  }
/* ------------------------------------------------------------
   PSD: Cholesky factorization. If use_pivot, then do pivoting.
   ------------------------------------------------------------ */
  if(use_pivot){
    if(ispos)
      for(k = 0; k < cK.rsdpN; k++){                /* real symmetric */
        nk = cK.sdpNL[k];
        if(cholpivot(up,perm, x,nk, fwork)){
          ispos = 0;
          break;
        }
        uperm(ux, up, perm, nk);
        triu2sym(ux,nk);
        nksqr = SQR(nk);
        x += nksqr; ux += nksqr;
        perm += nk;
      }
/* ------------------------------------------------------------
   Complex Hermitian PSD pivoted Cholesky factorization
   ------------------------------------------------------------ */
    if(ispos)
      for(; k < cK.sdpN; k++){                    /* complex Hermitian */
        nk = cK.sdpNL[k];
        nksqr = SQR(nk);
        if(prpicholpivot(up,uppi,perm, x,x+nksqr,nk, fwork)){
          ispos = 0;
          break;
        }
        uperm(ux, up, perm, nk);                  /* real part */
        uperm(ux+nksqr, uppi, perm, nk);          /* imaginary part */
        triu2herm(ux,ux+nksqr,nk);
        nksqr += nksqr;                           /* 2*n^2 for real+imag */
        x += nksqr; ux += nksqr;
        perm += nk;
      }
/* ------------------------------------------------------------
   Convert "perm" to Fortran-index in doubles.
   ------------------------------------------------------------ */
    for(i = 0; i < sdplen; i++)
      permPr[i] = 1.0 + iwork[i];
  }
/* ------------------------------------------------------------
   PSD, !use_pivot: Cholesky without pivoting.
   First let ux = x, then ux=chol(ux).
   ------------------------------------------------------------ */
  else{           /* Cholesky real sym PSD without pivoting */
    if(ispos){
      memcpy(ux, x, sdpdim * sizeof(double));       /* copy real + complex */
      for(k = 0; k < cK.rsdpN; k++){                /* real symmetric */
        nk = cK.sdpNL[k];
        if(cholnopiv(ux,nk)){
          ispos = 0;
          break;
        }
        triu2sym(ux,nk);
        ux += SQR(nk);
      }
    }
/* ------------------------------------------------------------
   Complex Hermitian PSD Cholesky factorization, no pivoting.
   ------------------------------------------------------------ */
    if(ispos)
      for(; k < cK.sdpN; k++){                    /* complex Hermitian */
        nk = cK.sdpNL[k];
        nksqr = SQR(nk);
        if(prpicholnopiv(ux,ux+nksqr,nk)){
          ispos = 0;
         break;
        }
        triu2herm(ux,ux+nksqr,nk);
        ux += 2 * nksqr;
      }
  } /* !use_pivot */
/* ------------------------------------------------------------
   Return parameter ispos
   ------------------------------------------------------------ */
  *mxGetPr(ISPOS_OUT) = ispos;
/* ------------------------------------------------------------
   Release working arrays
   ------------------------------------------------------------ */
  mxFree(iwork);
  mxFree(fwork);
/* ------------------------------------------------------------
   Copy requested output parameters (at least 1), release others.
   ------------------------------------------------------------ */
  i = MAX(nlhs, 1);
  memcpy(plhs,myplhs, i * sizeof(mxArray *));
  for(; i < NPAROUT; i++)
    mxDestroyArray(myplhs[i]);
}
Ejemplo n.º 4
0
/* ************************************************************
   PROCEDURE mexFunction - Entry for Matlab
   ************************************************************ */
void mexFunction(const int nlhs, mxArray *plhs[],
                 const int nrhs, const mxArray *prhs[])
{
    mxArray *myplhs[NPAROUT];
    int i,j,k, nk, nksqr, lenud, sdplen, gnnz, inz, maxKs,maxKssqr, rgnnz, hgnnz;
    const double *uOld, *permOld;
    double *u, *d, *gjcPr, *permPr, *fwork, *fworkpi;
    int *perm, *gjc;
    double *g, *gk;
    double maxusqr;
    coneK cK;
    char use_pivot;
    /* ------------------------------------------------------------
       Check for proper number of arguments
       ------------------------------------------------------------ */
    mxAssert(nrhs >= NPARINMIN, "urotorder requires more input arguments.");
    mxAssert(nlhs <= NPAROUT, "urotorder generates less output arguments.");
    /* ------------------------------------------------------------
       Disassemble cone K structure
       ------------------------------------------------------------ */
    conepars(K_IN, &cK);
    /* ------------------------------------------------------------
       Get statistics of cone K structure
       ------------------------------------------------------------ */
    lenud = cK.rDim + cK.hDim;
    sdplen = cK.rLen + cK.hLen;
    /* ------------------------------------------------------------
       Get scalar input MAXU and input vectors U_IN, PERM_IN
       ------------------------------------------------------------ */
    maxusqr = mxGetScalar(MAXU_IN);
    maxusqr *= maxusqr;
    mxAssert(mxGetM(U_IN) * mxGetN(U_IN) == lenud, "u size mismatch");
    uOld = mxGetPr(U_IN);
    use_pivot = 0;
    if(nrhs >= NPARIN)                              /* Optional permIN */
        if(mxGetM(PERM_IN) * mxGetN(PERM_IN) > 0) {
            mxAssert(mxGetM(PERM_IN) * mxGetN(PERM_IN) == sdplen, "perm size mismatch");
            use_pivot = 1;
            permOld = mxGetPr(PERM_IN);
        }
    /* ------------------------------------------------------------
       Allocate output U_OUT, and initialize u_out = u_in.
       ------------------------------------------------------------ */
    U_OUT = mxCreateDoubleMatrix(lenud, 1, mxREAL);
    u = mxGetPr(U_OUT);
    memcpy(u, mxGetPr(U_IN), lenud * sizeof(double));
    /* ------------------------------------------------------------
       Allocate outputs PERM(sum(K.s)), GJC(sum(K.s))
       ------------------------------------------------------------ */
    PERM_OUT = mxCreateDoubleMatrix(sdplen, 1, mxREAL);
    permPr = mxGetPr(PERM_OUT);
    GJC_OUT  = mxCreateDoubleMatrix(sdplen, 1, mxREAL);
    gjcPr = mxGetPr(GJC_OUT);
    /* ------------------------------------------------------------
       Allocate g initially as length (lenud - cK.rLen) / 2. The final
       length can be shorter (viz. gjc[sum(K.s)])
       ------------------------------------------------------------ */
    rgnnz = (cK.rDim - cK.rLen) / 2;               /* n(n-1)/2 real sym */
    hgnnz = (cK.hDim - 2*cK.hLen) / 4;             /* n(n-1)/2 complex herm */
    gnnz = rgnnz * 2 + hgnnz * 3;
    g = (double *) mxCalloc(MAX(1, gnnz),sizeof(double));
    /* ------------------------------------------------------------
       Allocate working arrays:
       Let maxKssqr = max(rMaxn^2, 2*hMaxn^2), then
       integer perm(max(K.s)), gjc(max(K.s))
       double d(max(K.s)), fwork(maxKs)
       ------------------------------------------------------------ */
    maxKs = MAX(cK.rMaxn,cK.hMaxn);                     /* max(K.s) */
    maxKssqr = MAX(SQR(cK.rMaxn),2 * SQR(cK.hMaxn));    /* max(K.s.^2) */
    perm = (int *) mxCalloc(MAX(1,maxKs), sizeof(int));
    gjc  = (int *) mxCalloc(MAX(1,maxKs), sizeof(int));
    d     = (double *) mxCalloc(MAX(1,maxKs), sizeof(double));
    fwork = (double *) mxCalloc(MAX(1,maxKssqr), sizeof(double));
    fworkpi = fwork + SQR(cK.hMaxn);
    /* ------------------------------------------------------------
       The actual job is done here: U_NEW = Q(g) * U_OLD
       ------------------------------------------------------------ */
    inz = 0;
    for(k = 0; k < cK.rsdpN; k++) {               /* real symmetric */
        nk = cK.sdpNL[k];
        nksqr = SQR(nk);
        memcpy(fwork, uOld, nksqr *sizeof(double));   /* k-th U-matrix */
        gk = g+inz;
        rotorder(perm, fwork, gjc, (twodouble *) gk, d, maxusqr, nk);
        /* ------------------------------------------------------------
           Physically reorder the columns from fwork into u. Then Let
           tril(U) = triu(U)'
           ------------------------------------------------------------ */
        uperm(u, fwork, perm, nk);
        triu2sym(u,nk);
        /* ------------------------------------------------------------
           Let perm_out = perm_in(perm)
           ------------------------------------------------------------ */
        if(use_pivot) {
            for(i = 0; i < nk; i++)
                permPr[i] = permOld[perm[i]];
            permOld += nk;
        }
        else
            for(i = 0; i < nk; i++)
                permPr[i] = 1.0 + perm[i];
        for(i = 0; i < nk; i++)
            gjcPr[i] = gjc[i];               /* don't add 1 */
        inz += 2 * gjc[nk-1];     /* next PSD block. Rotation g is 2 doubles */
        gjcPr += nk;
        permPr += nk;
        uOld += nksqr;
        u += nksqr;
    }
    /* ------------------------------------------------------------
       Complex Hermitian
       ------------------------------------------------------------ */
    for(; k < cK.sdpN; k++) {                   /* complex Hermitian */
        nk = cK.sdpNL[k];
        nksqr = SQR(nk);
        memcpy(fwork, uOld, nksqr *sizeof(double));   /* k-th complex U-matrix */
        memcpy(fworkpi, uOld+nksqr, nksqr *sizeof(double));
        gk = g+inz;
        prpirotorder(perm, fwork,fworkpi, gjc, (tridouble *) gk, d, maxusqr, nk);
        /* ------------------------------------------------------------
           Physically reorder the columns from fwork into u. Then Let
           tril(U) = triu(U)'
           ------------------------------------------------------------ */
        uperm(u, fwork, perm, nk);                  /* real part */
        uperm(u+nksqr, fworkpi, perm, nk);      /* imaginary part */
        triu2herm(u,u+nksqr, nk);
        /* ------------------------------------------------------------
           Let perm_out = perm_in(perm)
           ------------------------------------------------------------ */
        if(use_pivot) {
            for(i = 0; i < nk; i++)
                permPr[i] = permOld[perm[i]];
            permOld += nk;
        }
        else
            for(i = 0; i < nk; i++)
                permPr[i] = 1.0 + perm[i];
        for(i = 0; i < nk; i++)
            gjcPr[i] = gjc[i];               /* don't add 1 */
        inz += 3 * gjc[nk-1];     /* next PSD block. Rotation g is 3 doubles */
        gjcPr += nk;
        permPr += nk;
        nksqr += nksqr;
        uOld += nksqr;
        u += nksqr;
    }
    /* ------------------------------------------------------------
       In total, we used inz doubles in Givens rotations.
       Reallocate (shrink) g accordingly.
       ------------------------------------------------------------ */
    mxAssert(inz <= gnnz,"");
    if(inz > 0) {
        if((g = (double *) mxRealloc(g, inz * sizeof(double))) == NULL)
            mexErrMsgTxt("Memory allocation error.");
    }
    else {
        mxFree(g);
        g = (double *) NULL;
    }
    /* ------------------------------------------------------------
       Assign g to a length inz output vector
       ------------------------------------------------------------ */
    G_OUT = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxFree(mxGetPr(G_OUT));
    mxSetPr(G_OUT, (double *) g);
    mxSetM(G_OUT, inz);
    /* ------------------------------------------------------------
       Release working arrays
       ------------------------------------------------------------ */
    mxFree(fwork);
    mxFree(d);
    mxFree(gjc);
    mxFree(perm);
    /* ------------------------------------------------------------
       Copy requested output parameters (at least 1), release others.
       ------------------------------------------------------------ */
    i = MAX(nlhs, 1);
    memcpy(plhs,myplhs, i * sizeof(mxArray *));
    for(; i < NPAROUT; i++)
        mxDestroyArray(myplhs[i]);
}