/* % Lden = finsymbden(LAD,perm,dz,firstq) % FINSYMBDEN Updates perm and dz by inserting the % last Lorentz trace columns (last columns of LAD). It creates the fields % Lden.sign - +1 for "normal" columns, -1 for Lorentz trace columns % Lden.first - First pivot column that will affect this one % NOTE: sign and first correspond to columns in LAD (without perm-reordering). % % SEE ALSO incorder % ******************** INTERNAL FUNCTION OF SEDUMI ******************** function Lden = finsymbden(LAD,perm,dz,firstq) % This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko % Copyright (C) 2005 McMaster University, Hamilton, CANADA (since 1.1) % % Copyright (C) 2001 Jos F. Sturm (up to 1.05R5) % Dept. Econometrics & O.R., Tilburg University, the Netherlands. % Supported by the Netherlands Organization for Scientific Research (NWO). % % Affiliation SeDuMi 1.03 and 1.04Beta (2000): % 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., 51 Franklin Street, Fifth Floor, Boston, MA % 02110-1301, USA */ #include #include "mex.h" #include "blksdp.h" #define LDEN_OUT plhs[0] #define NPAROUT 1 #define LAD_IN prhs[0] #define PERM_IN prhs[1] #define DZ_IN prhs[2] #define FIRSTQ_IN prhs[3] #define NPARIN 4 /* ************************************************************ PROCEDURE getfirstpiv - Find first affecting pivot on column j = 1:n. These column numbers are in NON-PIVOTED ORDER, i.e. the order in which they appear in Xjc. INPUT invperm - length n array, yields position in list of nonzeros "dzir". xsuper - length n (though it may have n+1) array, partitioning of permuted subscripts, is "dzjc". Xjc - length n+1 array Xir - length Xjc[n] array n - number of columns in X. OUTPUT firstpiv - length n array ************************************************************ */ void getfirstpiv(mwIndex *firstpiv, const mwIndex *invperm, const mwIndex *xsuper, const mwIndex *Xjc, const mwIndex *Xir, const mwIndex n) { mwIndex i,j,inz,firstj; inz = Xjc[0]; /* typically inz = 0*/ for(j = 0; j < n; j++){ /* ------------------------------------------------------------ Let firstj = min(invperm(find(X(:,j)))) ------------------------------------------------------------ */ if(inz < Xjc[j+1]){ firstj = invperm[Xir[inz]]; for(++inz; inz < Xjc[j+1]; inz++) if((i = invperm[Xir[inz]]) < firstj) firstj = i; /* ------------------------------------------------------------ First node covering firstj, i.e. xsuper[y] < firstj+1 <= xsuper[y+1], with y denoting firstpiv[j]. ------------------------------------------------------------ */ firstpiv[j] = 0; /* search from start */ intbsearch(firstpiv+j,xsuper+1,n-1,firstj+1); } else firstpiv[j] = n; /* if all-0 then no affecting pivot */ } } /* ============================================================ MAIN: MEXFUNCTION ============================================================ */ #define NLDEN_FIELDS 4 /* ************************************************************ PROCEDURE mexFunction - Entry for Matlab ************************************************************ */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { mxArray *LDEN_FIELD; mwIndex i,inz, j,m,n,nperm, firstQ, lastQ, nnzdz; const mwIndex *LADjc, *LADir, *dzJc, *dzIr; mwIndex *invdz,*firstpiv,*perm, *dznewJc; double *permPr, *firstPr; const char *LdenFieldnames[] = {"LAD","perm","dz","first"}; /* ------------------------------------------------------------ Check for proper number of arguments ------------------------------------------------------------ */ mxAssert(nrhs >= NPARIN, "finsymbden requires more input arguments"); mxAssert(nlhs <= NPAROUT, "finsymbden produces less output arguments"); /* ------------------------------------------------------------ Get inputs LAD,perm,dz,firstq n = total number of dense columns/blocks, i.e. #cols in LAD m = number of constraints nperm = n - number of removed lorentz trace columns. ------------------------------------------------------------ */ mxAssert(mxIsSparse(LAD_IN), "LAD must be sparse"); /* LAD */ m = mxGetM(LAD_IN); n = mxGetN(LAD_IN); LADjc = mxGetJc(LAD_IN); LADir = mxGetIr(LAD_IN); permPr = mxGetPr(PERM_IN); /* perm */ nperm = mxGetM(PERM_IN) * mxGetN(PERM_IN); dzJc = mxGetJc(DZ_IN); /* dz */ dzIr = mxGetIr(DZ_IN); mxAssert(mxGetM(DZ_IN) == m && mxGetN(DZ_IN) == nperm, "dz size mismatch"); /* ------------------------------------------------------------ INPUT firstQ == dense.l+1, points to 1st entry in dense.cols dealing with Lorentz-trace entries. Let lastQ point just beyond Lorentz trace/block entries, i.e. add n-nperm. ------------------------------------------------------------ */ firstQ = (mwIndex) mxGetScalar(FIRSTQ_IN); /*firstq, F-double to C-mwIndex.*/ mxAssert(firstQ>0,""); --firstQ; lastQ = firstQ + n - nperm; /* ------------------------------------------------------------ Allocate integer working arrays: invdz(m), firstpiv(n), perm(n) ------------------------------------------------------------ */ invdz = (mwIndex *) mxCalloc(MAX(1,m), sizeof(mwIndex)); firstpiv = (mwIndex *) mxCalloc(MAX(1,n), sizeof(mwIndex)); perm = (mwIndex *) mxCalloc(MAX(1,n), sizeof(mwIndex)); /* ------------------------------------------------------------ Allocate OUTPUT mwIndex array dznewJc(n+1) ------------------------------------------------------------ */ dznewJc = (mwIndex *) mxCalloc(n+1, sizeof(mwIndex)); /* ------------------------------------------------------------ Let invdz(dzIr) = 1:nnz(dz). Note that nnz(dz)= firstQ && j < lastQ){ /* ------------------------------------------------------------ Attach Lorentz trace col. These cols are at nperm:n-1. ------------------------------------------------------------ */ perm[inz] = nperm + j - firstQ; /* insert associated trace column */ mxAssert(perm[inz] < n,""); dznewJc[inz++] = dzJc[i+1]; /* no extra subscripts->start at end */ } } mxAssert(inz == n,""); dznewJc[n] = dzJc[nperm]; /* ------------------------------------------------------------ Compute firstpiv ------------------------------------------------------------ */ getfirstpiv(firstpiv, invdz, dznewJc, LADjc,LADir, n); /* ------------------------------------------------------------ Outputs Lden.(LAD, perm, dz, first) ------------------------------------------------------------ */ LDEN_OUT = mxCreateStructMatrix((mwSize)1,(mwSize)1, NLDEN_FIELDS, LdenFieldnames); LDEN_FIELD = mxDuplicateArray(LAD_IN); /* LAD */ mxSetField(LDEN_OUT,(mwIndex)0,"LAD",LDEN_FIELD); LDEN_FIELD = mxCreateDoubleMatrix(n, (mwSize)1, mxREAL); /* perm */ mxSetField(LDEN_OUT,(mwIndex)0,"perm",LDEN_FIELD); permPr = mxGetPr(LDEN_FIELD); for(i = 0; i < n; i++) permPr[i] = perm[i] + 1.0; /* C-mwIndex to F-double */ LDEN_FIELD = mxDuplicateArray(DZ_IN); /* dz */ /* NOTE: here we replace jc by dznewJc */ mxFree(mxGetJc(LDEN_FIELD)); mxSetJc(LDEN_FIELD, dznewJc); mxSetN(LDEN_FIELD, n); mxSetField(LDEN_OUT,(mwIndex)0,"dz",LDEN_FIELD); LDEN_FIELD = mxCreateDoubleMatrix(n, (mwSize)1, mxREAL); /* first */ mxSetField(LDEN_OUT,(mwIndex)0,"first",LDEN_FIELD); firstPr = mxGetPr(LDEN_FIELD); for(i = 0; i < n; i++) firstPr[i] = firstpiv[i] + 1.0; /* C-mwIndex to F-double */ /* ------------------------------------------------------------ Release working arrays ------------------------------------------------------------ */ mxFree(perm); mxFree(firstpiv); mxFree(invdz); }