⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sparchol2.c

📁 凸优化程序包
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    This file is part of SeDuMi 1.03BETA    Copyright (C) 1999 Jos F. Sturm    Dept. Quantitative Economics, Maastricht University, the Netherlands.    Affiliations up to SeDuMi 1.02 (AUG1998):      CRL, McMaster University, Canada.      Supported by the Netherlands Organization for Scientific Research (NWO).      This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.      This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.      You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <math.h>#include <string.h>#include "blksdp.h"#include "mex.h"/* ------------------------------------------------------------   PROTOTYPES:   ------------------------------------------------------------ */int blkLDL(const int neqns, const int nsuper, const int *xsuper,           const int *snode,  const int *xlindx, const int *lindx,           double *lb,           const int *ljc, double *lpr, double *d, const int *perm,           const double ub, const double maxu, int *skipIr,           int iwsiz, int *iwork, int fwsiz, double *fwork);/* ************************************************************   TIME-CRITICAL PROCEDURE -- isscalarmul(x,alpha,n)   Computes x *= alpha using LEVEL 8 loop-unrolling.   ************************************************************ */void isscalarmul(double *x, const double alpha, const int n){  int i;    for(i=0; i< n-7; i++){          /* LEVEL 8 */    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;    x[i] *= alpha;  }/* ------------------------------------------------------------   Now, i in {n-7, n-6, ..., n}. Do the last n-i elements.   ------------------------------------------------------------ */  if(i < n-3){                           /* LEVEL 4 */    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;    x[i++] *= alpha;  }  if(i < n-1){                           /* LEVEL 2 */    x[i++] *= alpha;    x[i++] *= alpha;  }  if(i < n)                              /* LEVEL 1 */    x[i] *= alpha;}/* ************************************************************   PROCEDURE maxabs - computes inf-norm   INPUT     x - vector of length n     n - length of x.   RETURNS y = norm(x,inf).   ************************************************************ */double maxabs(const double *x,const int n){  int i;  double y,xi;  y = 0.0;  for(i = 0; i < n; i++)    if((xi = fabs(x[i])) > y)      y = xi;  return y;}/* ************************************************************   PROCEDURE cholonBlk - CHOLESKY on a dense diagonal block.            Also updates nonzeros below this diagonal block -            they need merely be divided by the scalar diagonals            "lkk" afterwards.   INPUT     m      - number of rows (length of the first column).     ncols  - number of columns in the supernode.(n <= m)     lb     - Length ncols. Skip k-th pivot if drops below lb[k].     ub     - max(diag(x)) / maxu^2. No stability check for pivots > ub.     maxu   - Max. acceptable |lik|/lkk when lkk suffers cancelation.     first - global column number of column 0. This is used only to insert        the global column numbers into skipIr.   UPDATED     x  - On input, contains the columns of the supernode to          be factored. On output, contains the factored columns of          the supernode.     skipIr - Lists skipped pivots with their global column number        in 0:neqns-1. Active range is first:first+ncols-1.        Skipped if d(k) suffers cancelation and max(abs(L(:,k)) > maxu.     *pnskip - nnz in skip; *pnskip <= order N of sparse matrix.   OUTPUT     d - Length ncols. Diagonal in L*diag(d)*L' with diag(L)=all-1.   ************************************************************ */void cholonBlk(double *x, double *d, int m, const int ncols, const int first,               const double ub, const double maxu, double *lb,               int *skipIr, int *pnskip){  int inz,i,k,n,coltail, nskip;  double xkk, xik, ubk;  double *xi;/* ------------------------------------------------------------   Initialize:   ------------------------------------------------------------ */  n = ncols;  nskip = *pnskip;  inz = 0;  coltail = m - ncols;  for(k = 0; k < ncols; k++, --m, --n){/* -------------------------------------------------------   Let xkk = L(k,k), ubk = max(|xik|) / maxu.   ------------------------------------------------------- */    xkk = x[inz];    if(xkk > lb[k]){ /* now xkk > 0 */      if(xkk < ub){        ubk = maxabs(x+inz+1,m-1) / maxu;        if(xkk < ubk){/* ------------------------------------------------------------   If we need to add on diagonal, store this in (skipIr, lb(k)).   ------------------------------------------------------------ */          skipIr[nskip++] = first + k;	  lb[k] = ubk - xkk;           /* amount added on diagonal */	  xkk = ubk;	}      }/* --------------------------------------------------------------   Set dk = xkk, lkk = 1 (for LDL').   -------------------------------------------------------------- */      d[k] = xkk;                   /* now d[k] > 0 MEANS NO-SKIPPING */      x[inz] = 1.0;      xi = x + inz + m;                 /* point to next column */      ++inz;/* --------------------------------------------------------------   REGULAR JOB: correct remaining n-k cols with col k.   x(k+1:m,k+1:n) -= x(k+1:m,k) * x(k+1:n,k)' / xkk   x(k+1:n,k) /= xkk,   -------------------------------------------------------------- */      for(i = 1; i < n; i++){        xik = x[inz] / xkk;        subscalarmul(xi, xik, x+inz, m-i);        x[inz++] = xik;        xi += m-i;      }      inz += coltail;                 /* Let inz point to next column */    }/* ------------------------------------------------------------   If skipping is enabled and this pivot is too small:   1) don't touch L(k:end,k): allows pivot delaying if desired.   2) List first+k in skipIr. Set dk = 0 (MEANS SKIPPING).   -------------------------------------------------------------- */    else{      skipIr[nskip++] = first + k;      d[k] = 0.0;                 /* tag "0": means column skipped in LDL'.*/      inz += m;                   /* Don't touch nor use L(k:end,k) */    }  } /* k=0:ncols-1 *//* ------------------------------------------------------------   Return updated number of added or skipped pivots.   ------------------------------------------------------------ */  *pnskip = nskip;}/* ************************************************************  getbwIrInv  --  Inverse of the subscript function: given a subscript,      irInv yields the position, counted FROM THE BOTTOM of the sparse column.  INPUT PARAMETERS -     nnz    - LENGTH OF THE FIRST COLUMN OF THE SUPERNODE,              INCLUDING THE DIAGONAL ENTRY.     Lir    - Lir[0:nnz-1] ARE THE ROW INDICES OF THE NONZEROS              OF THE FIRST COLUMN OF THE SUPERNODE.  OUTPUT PARAMETERS -      irInv - On return, irInv[Lir[0:nnz-1]] = nnz:-1:1, so that		           Lir[nnz-irInv[i]]  == i             The position of subscript "xij" is thus			   xjc[j+1] - irInv[i].   ************************************************************ */void getbwIrInv(int *irInv, const int *Lir, const int nnz){  int inz,bwinz;  bwinz = nnz;  for(inz = 0; inz < nnz; inz++, bwinz--)    irInv[Lir[inz]] = bwinz;               /* bwinz = nnz:-1:1 */}/* ************************************************************  suboutprod  --  Computes update from a single previous column "xk" on		a supernode "xj", using dense computations.  INPUT     mj, nj  -  supernode "xj" is mj x nj.  More precisely, the column                lengths are {mj, mj-1, ..., mj-(nj-1)}.     xkk     -  scalar, the 1st nj entries in xk are divided by this number.     mk      -  length of xk.  WE ASSUME mk <= mj.  Only 1st mk rows in xj                are updated.  UPDATED     xj  -  On return, xj -= xk*xk(0:nj-1)'/xkk     xk  -  On return, xk(0:nj-1) /= xkk   ************************************************************ */void suboutprod(double *xj, int mj, const int nj, double *xk,                const double xkk, int mk){  int j;  double xjk;  for(j = 0; j < nj; j++){    xjk = xk[0] / xkk;    subscalarmul(xj, xjk, xk, mk);   /* xj -= xjk * xk */    xk[0] = xjk;                     /* FINAL entry ljk */    xj += mj;                    /* point to next column which is 1 shorter */    --mj; --mk; ++xk;  }}/* ************************************************************  isminoutprod  --  Computes update from a column "xk" and stores it in "xj",	       using dense computations. If "xkk<=0", then let xj = 0.  INPUT     mk, nj  -  output "xj" is mk x nj - nj*(nj-1)/2. Its column lengths are	        {mk, mk-1, ..., mk-(nj-1)}.     xkk     -  scalar, the 1st nj entries in xk are divided by this number.  OUTPUT     xj      -  On return, xj = -xk*xk(0:nj-1)'/xkk       (NOTE THE MINUS !)                BUT: if xkk <= 0, then xj = zeros(nj*(2m-nj+1)/2,1).  UPDATED     xk      -  On return, xk(0:nj-1) /= xkk if xkk > 0, otherwise unchanged.   ************************************************************ */void isminoutprod(double *xj, const int nj, double *xk, const double xkk,                  int mk){  int j;  double xjk;  if(xkk > 0.0)   /* if not phase 2 node */    for(j = 0; j < nj; j++){      xjk = xk[0] / xkk;      memcpy(xj,xk,mk * sizeof(double));      isscalarmul(xj, -xjk, mk);          /* xj = -xjk * xk */      xk[0] = xjk;                     /* FINAL entry ljk */      xj += mk;                /* point to next column which is 1 shorter */      --mk; ++xk;    }  else  /* initialize to all-0 if phase-2 node */    fzeros(xj,(nj * (mk + mk-nj + 1))/2);}/* ************************************************************   spsuboutprod  --  Computes update from a single previous column "xk" on		     a supernode "xj", with a different sparsity structure.                     The relevant nonzeros of xj are accessed by a single                     indirection, via "relind[:]".   INPUT     mj, nj  -  supernode "xj" has mj rows in its 1st column. In total, we	        will update nj columns, corresponding to the 1st nj nonzeros                in xk.     xjjc    - xjjc[0] is start of 1st column of xj (as index into xnz), etc.     xkk     -  scalar, the 1st nj entries in xk are divided by this number.     mk      -  length of xk.  WE ASSUME mk <= mj.     relind  - (mj - relind[0:mk-1]) yields the locations in xj on which the	       xk nonzeros will act.  UPDATED     xnz  -  On return, xj(relind,:) -= xk*xk(0:nj-1)'/xkk     xk   -  On return, xk(0:nj-1) /= xkk   ************************************************************ */void spsuboutprod(const int *xjjc, double *xnz, const int mj, const int nj,                  double *xk,const double xkk,const int mk, const int *relind){  int i, j, jcol, bottomj;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -