├── .gitattributes ├── Citation.txt ├── Copyright.txt ├── QSDPNAL_main ├── NAL │ ├── LSnal.m │ ├── LSnalI.m │ ├── qsdpnal.m │ ├── qsdpnal_BIQ.m │ ├── qsdpnal_NCM.m │ ├── qsdpnal_NCMP.m │ └── qsdpnal_QAP.m ├── SCB │ ├── SCB_LS.m │ ├── SCB_LSI.m │ ├── SCB_NCM.m │ ├── SCB_NCMP.m │ └── SCB_qsdp.m └── submain │ ├── Nalmain.p │ ├── nal_LSImain.p │ ├── nal_LSmain.p │ ├── nal_NCMPmain.p │ ├── nal_NCMmain.p │ ├── nal_qsdpBIQmain.p │ └── nal_qsdpQAPmain.p │ ├── SCBmain.p │ ├── SCB_LSImain.p │ ├── SCB_LSmain.p │ ├── SCB_NCMPmain.p │ ├── SCB_NCMmain.p │ └── SCB_qsdpmain.p │ └── SNCG.p │ ├── ssncgABtest.p │ ├── ssncgLS1.p │ ├── ssncgLSI1.p │ ├── ssncgNCM2.p │ ├── ssncgNCM3.p │ └── ssncgQSDP.p ├── README.md ├── datafiles ├── 2d250n10nf.mat ├── 3d250n10nf.mat ├── ER.mat ├── Lymph.mat ├── be250.2.sparse ├── chr15c.dat └── divergentGH.mat ├── mexfun ├── mexFnorm.mexa64 ├── mexFnorm.mexmaci64 ├── mexFnorm.mexw64 ├── mexbwsolve.mexa64 ├── mexbwsolve.mexmaci64 ├── mexbwsolve.mexw64 ├── mexeig.mexa64 ├── mexeig.mexmaci64 ├── mexeig.mexw64 ├── mexeigPartial.mexa64 ├── mexeigPartial.mexmaci64 ├── mexeigPartial.mexw64 ├── mexfwsolve.mexa64 ├── mexfwsolve.mexmaci64 ├── mexfwsolve.mexw64 ├── mexmat.mexa64 ├── mexmat.mexmaci64 ├── mexmat.mexw64 ├── mexnnz.mexa64 ├── mexnnz.mexmaci64 ├── mexnnz.mexw64 ├── mexsmat.mexa64 ├── mexsmat.mexmaci64 ├── mexsmat.mexw64 ├── mexsvec.mexa64 ├── mexsvec.mexmaci64 ├── mexsvec.mexw64 ├── mextriang.mexa64 ├── mextriang.mexmaci64 └── mextriang.mexw64 ├── problems_QSDP.m ├── qsdpdemo.m ├── solvers.p ├── bicgQAB.p ├── diagABPi.p ├── diagAPi.p ├── diagHABPi.p ├── diagapproxsym.p ├── matvecA.p ├── matvecAB.p ├── matvecHA.p ├── matvecHALS.p ├── matvecLSHAB.p ├── matvecLSyI.p ├── matvecQAB.p ├── matvecxi.p ├── matvecyE.p ├── matvecyI.p ├── mycholAAt.p ├── projSDP.p ├── proj_LU_new.p ├── projectSDP2.p ├── psqmrAB.p ├── psqmrLSHAB.p ├── psqmrQW.p ├── psqmry.p ├── sdpnalAXfun.p ├── sdpnalAtyfun.p ├── smat.p └── svec.p ├── startup.m └── util ├── NCM_Hnorm.m ├── QXfun_corr.m ├── Qfun_stein.m ├── biq_sqsdp.m ├── biq_sqsdp_new.m ├── biqread.m ├── qapAW.m ├── qapAW2.m ├── qapread.m ├── qmapfuncorr.m ├── randQXfun.m ├── read_sdpa.m └── read_sedumi.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Citation.txt: -------------------------------------------------------------------------------- 1 | ******* Citation Information ***************************** 2 | If you find the software QSDPNAL 3 | useful, please cite it in you publication as follows: 4 | 5 | Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703–743. 6 | -------------------------------------------------------------------------------- /Copyright.txt: -------------------------------------------------------------------------------- 1 | 2 | QSDPNAL version 0.1: 3 | A MATLAB software for convex quadratic semidefinite programming 4 | with inequality, equality and bound constraints 5 | 6 | The software QSDPNAL is a research software. It is not 7 | intended nor designed to be a general purpose software 8 | at the moment. QSDPNAL is available for use under the following 9 | license, commonly known as the 3-clause (or "modified") BSD license. 10 | For commercial applications that may be incompatible with this license, 11 | please contact the authors to discuss alternatives. 12 | 13 | ============================================= 14 | Copyright (c) 2020 Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | 16 | Redistribution and use in source and binary forms, with or without 17 | modification, are permitted provided that the following conditions 18 | are met: 19 | 1. Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 2. Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in the 23 | documentation and/or other materials provided with the distribution. 24 | 3. The name of the author may not be used to endorse or promote products 25 | derived from this software without specific prior written permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 32 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 36 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/LSnal.m: -------------------------------------------------------------------------------- 1 | %%************************************************************************* 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Netwon based ALM for solving the following Least Squre problem 4 | %% (P) min {1/2||H(X)||_F^2 + | A(X)=b, X \in K} 5 | %% where K = psd cone 6 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H(X) = Y, X\in K} 7 | %% 8 | %% (D') max -1/2 ||Xi||^2 + 9 | %% s.t. H*(Xi) + S + A*y = C, 10 | %% S \in PSD. 11 | %%************************************************************************* 12 | %% QSDPNAL: 13 | %% Copyright (c) 2015 by 14 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | %%************************************************************************* 16 | function [obj,xi,S,yE,X,runhist,info] = LSnal(blk,H,A,b,C,options,X,xi,S,yE) 17 | %% General options 18 | rng('default'); 19 | maxiter = 5000; 20 | stoptol = 1e-6; 21 | printyes = 1; 22 | printminoryes=1; 23 | startfun = @SCB_LS; % Algorithm QSDPNAL-Phase I for initial point 24 | sigma0 = 1; 25 | sGS.iter = 0; 26 | sGS.time = 0; 27 | use_proximal = 1; 28 | % options from users 29 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 30 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 31 | if isfield(options,'printyes'); printyes = options.printyes; end 32 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 33 | if isfield(options,'sigma'); sigma0 = options.sigma; end 34 | 35 | 36 | fprintf('\n'); 37 | fprintf('\n============================================================================================================'); 38 | fprintf('\n************************************************************************************************************'); 39 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 40 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 41 | fprintf('\n************************************************************************************************************'); 42 | fprintf('\n============================================================================================================'); 43 | fprintf('\n************************************************************************************************************'); 44 | fprintf('\n* Reference *'); 45 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 46 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 47 | fprintf('\n************************************************************************************************************'); 48 | fprintf('\n============================================================================================================'); 49 | fprintf('\n'); 50 | 51 | %% problem property 52 | existA = ~isempty(A); 53 | existH = ~isempty(H); 54 | tstart = clock; 55 | n = blk{1,2}; 56 | nbar = n*(n+1)/2; 57 | Zero = sparse(n,n); 58 | Fnorm = @(X) mexFnorm(X); 59 | %% AEmap, AETmap, Qmap 60 | if existA 61 | if isstruct(A) 62 | if isfield(A,'At'); At = A.At; end 63 | if isfield(A,'Amap'); Amap0 = A.Amap; end 64 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 65 | else 66 | At = A; 67 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 68 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 69 | end 70 | else 71 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 72 | end 73 | if existH 74 | if isstruct(H) 75 | if isfield(H,'Ht'); Ht = H.Ht; end 76 | if isfield(H,'Hmap'); Hmap0 = H.Hmap; end 77 | if isfield(H,'HTmap'); HTmap0 = H.HTmap; end 78 | else 79 | Ht = H; 80 | Hmap0 = @(X) sdpnalAXfun(blk,Ht,X); 81 | HTmap0 = @(y) sdpnalAtyfun(blk,Ht,y); 82 | end 83 | else 84 | Hmap0 = @(X) []; HTmap0 = @(y) Zero; 85 | end 86 | %% 87 | %% 88 | if ~exist('X','var'); X = Zero; end 89 | if ~exist('yE','var'); yE = zeros(length(b),1); end 90 | if ~exist('S','var'); S = Zero; end 91 | if ~existA; yE = []; b = []; end 92 | if ~exist('Xi','var'); xi = zeros(size(Ht,2),1); end 93 | %% initial scaling 94 | %% 95 | Atorg = At; borg = b; 96 | Corg = C; Htorg = Ht; 97 | normHorg = Fnorm(Htorg); 98 | normCorg = 1 + Fnorm(Corg); 99 | normborg = 1 + norm(borg); 100 | %% 101 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 102 | sGS.op.stoptol = 1e-3; 103 | sGS.op.maxiter = 1000; 104 | sGS.op.phase2 = 1; 105 | fprintf('\n********************************************************'); 106 | fprintf('\n QSDPNAL Phase I '); 107 | fprintf('\n********************************************************'); 108 | [obj,xi,S,yE,X,runhist_sGS,info_sGS] = startfun(blk,Htorg,A,borg,Corg,sGS.op,X,xi,S,yE); 109 | fprintf('\n -------------------------------------------------------'); 110 | sGS.xi0 = xi; sGS.S0 = S; 111 | sGS.yE0= yE; sGS.X0=X; 112 | nE = info_sGS.nE; 113 | nxi = length(xi); 114 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 115 | sigma = info_sGS.sigma; 116 | normA = info_sGS.normA; DA = info_sGS.DA; 117 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 118 | b = info_sGS.b; 119 | C = info_sGS.C; 120 | sGS.iter = sGS.iter + info_sGS.iter; 121 | sGS.time = sGS.time + info_sGS.totaltime; 122 | %% 123 | At = At*DA; 124 | X = X/bscale; yE = (normA.*yE)/Cscale; 125 | S = S/Cscale; Htxi = HTmap0(xi)/Cscale; 126 | xi = xi/sqrt(bscale*Cscale); 127 | objscale = bscale*Cscale; 128 | %%------------------------------------------------------------------- 129 | %% end of intial stage 130 | %%------------------------------------------------------------------- 131 | %% start QSDPNAL-Phase II 132 | parmain.existH = existH; parmain.existA = existA; 133 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 134 | parmain.nE = nE; parmain.n = n; parmain.nxi = nxi; 135 | parmain.normA = normA; 136 | parmain.Htorg = Htorg; 137 | parmain.Htxi = Htxi; 138 | parmain.normHorg = normHorg; 139 | parmain.normborg = normborg; 140 | parmain.normCorg = normCorg; 141 | parmain.use_proximal = use_proximal; 142 | 143 | parmain.sigma = sigma; 144 | parmain.tstart= tstart; 145 | parmain.maxiter = maxiter; 146 | parmain.stoptol = stoptol; 147 | parmain.printyes = printyes; 148 | parmain.sGS = sGS; 149 | 150 | parmain.info_sGS = info_sGS; 151 | parmain.obj = obj; 152 | 153 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.At = At; 154 | % main solver QSDPNAL-Phase II with restart technique 155 | [X,yE,S,xi,info_main,runhist] = ... 156 | nal_LSmain(blk,Hmap0,HTmap0,Ainput,b,C,parmain,X,yE,S,xi); 157 | iter = info_main.iter; 158 | msg = info_main.msg; 159 | bscale = info_main.bscale; 160 | Cscale = info_main.Cscale; 161 | %%----------------------------------------------------------------- 162 | %% recover orignal variables 163 | %%----------------------------------------------------------------- 164 | if (iter == maxiter) 165 | msg = ' maximum iteration reached'; 166 | info.termcode = 3; 167 | end 168 | X = X*bscale; normX = norm(X,'fro'); 169 | HX = Hmap0(X); 170 | yE = Cscale*(DA*yE); 171 | S = Cscale*S; normS = norm(S,'fro'); 172 | xi = xi*sqrt(bscale*Cscale); 173 | Htxi = HTmap0(xi); 174 | AX = Amap0(X); AtyE = ATmap0(yE); 175 | if existA; bTyE = borg'*yE; end 176 | primobj = 0.5*norm(HX)^2 + sum(sum(Corg.*X)); 177 | dualobj = bTyE - 0.5*Fnorm(xi)^2; 178 | obj = [primobj,dualobj]; 179 | etaQ = Fnorm(xi + Hmap0(X))^2/(1+normHorg^2); 180 | if (true) 181 | etaSp = compnormXn(X) /(1+normX); 182 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 183 | etaS = max(etaSp,etaSc); 184 | end 185 | primfeasorg = norm(AX-borg)/normborg; 186 | dualfeasorg = norm(S+AtyE+Htxi-Corg,'fro')/normCorg; 187 | ttime = etime(clock,tstart); 188 | runhist.nE = nE; 189 | runhist.ns = n; 190 | runhist.iter = iter; 191 | runhist.totaltime = ttime; 192 | runhist.primobjorg = primobj; 193 | runhist.dualobjorg = dualobj; 194 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 195 | runhist.primfeasorg(iter) = primfeasorg; 196 | runhist.dualfeasorg(iter) = dualfeasorg; 197 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS]); 198 | info.nE = nE; 199 | info.ns = n; 200 | info.iter = iter; 201 | info.totaltime = ttime; 202 | info.primobjorg = primobj; 203 | info.dualobjorg = dualobj; 204 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 205 | info.relerrS = etaS; 206 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 207 | info.relerrQ = etaQ; 208 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 209 | info.minX = min(min(X)); 210 | info.maxX = max(max(X)); 211 | info.sGS_iter = sGS.iter; 212 | info.sGS_time = sGS.time; 213 | info.totalNT = sum(runhist.innerNT); 214 | info.totalCG = sum(runhist.innerCG); 215 | if (printminoryes) 216 | if ~isempty(msg); fprintf('\n %s',msg); end 217 | fprintf('\n--------------------------------------------------------------'); 218 | fprintf('------------------'); 219 | fprintf('\n number iter = %2.0d',iter); 220 | fprintf('\n time = %3.2f',ttime); 221 | %fprintf('\n time per iter = %5.4f',ttime/iter); 222 | fprintf('\n time of Phase I = %3.2f', sGS.time); 223 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 224 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 225 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 226 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 227 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 228 | fprintf('\n relerrQ = %3.2e', etaQ); 229 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 230 | info.minX,info.maxX); 231 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 232 | fprintf('\n--------------------------------------------------------------'); 233 | fprintf('------------------\n'); 234 | end 235 | %%********************************************************************** 236 | function normXn = compnormXn(X) 237 | 238 | d = eig(full(X)); 239 | normXn = norm(d(d<0)); 240 | %%********************************************************************** 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/LSnalI.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Netwon based ALM for solving the following Least Squre problem 4 | %% (P) min {1/2||H(X)||_F^2 + | A(X)=b, B(X)>=d, X \in K} 5 | %% where K = psd cone 6 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H(X) = Y, B(X) - alpha*v =d, X\in K, v>=0} 7 | %% 8 | %% (D') max -1/2 ||Xi||^2 + + 9 | %% s.t. H^*(Xi) + S + A^*yE + B^*yI= C, 10 | %% alpha*(u - yI) = 0, 11 | %% S \in PSD, u>=0 12 | %%************************************************************************* 13 | %% QSDPNAL: 14 | %% Copyright (c) 2015 by 15 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 16 | %%************************************************************************* 17 | 18 | function [obj,xi,S,yE,yI,X,runhist,info] = LSnalI(blk,H,A,b,B,d,C,options,X,xi,S,yE,yI) 19 | %% General options 20 | rng('default'); 21 | maxiter = 5000; 22 | stoptol = 1e-6; 23 | printyes = 1; 24 | printminoryes=1; 25 | startfun = @SCB_LSI; % Algorithm QSDPNAL-Phase I for initial point 26 | sigma0 = 1; 27 | sGS.iter = 0; 28 | sGS.time = 0; 29 | use_proximal = 1; 30 | restart = 1; 31 | % options from users 32 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 33 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 34 | if isfield(options,'printyes'); printyes = options.printyes; end 35 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 36 | if isfield(options,'sigma'); sigma0 = options.sigma; end 37 | 38 | 39 | fprintf('\n'); 40 | fprintf('\n============================================================================================================'); 41 | fprintf('\n************************************************************************************************************'); 42 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 43 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 44 | fprintf('\n************************************************************************************************************'); 45 | fprintf('\n============================================================================================================'); 46 | fprintf('\n************************************************************************************************************'); 47 | fprintf('\n* Reference *'); 48 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 49 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 50 | fprintf('\n************************************************************************************************************'); 51 | fprintf('\n============================================================================================================'); 52 | fprintf('\n'); 53 | 54 | %% problem property 55 | existA = ~isempty(A); 56 | existH = ~isempty(H); 57 | existB = ~isempty(B); 58 | tstart = clock; 59 | n = blk{1,2}; 60 | nbar = n*(n+1)/2; 61 | Zero = sparse(n,n); 62 | Fnorm = @(X) mexFnorm(X); 63 | %% AEmap, AETmap, AImap, AITmap, Qmap 64 | if existA 65 | if isstruct(A) 66 | if isfield(A,'At'); At = A.At; end 67 | if isfield(A,'Amap'); Amap0 = A.Amap; end 68 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 69 | else 70 | At = A; 71 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 72 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 73 | end 74 | else 75 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 76 | end 77 | if existH 78 | if isstruct(H) 79 | if isfield(H,'Ht'); Ht = H.Ht; end 80 | if isfield(H,'Hmap'); Hmap0 = H.Hmap; end 81 | if isfield(H,'HTmap'); HTmap0 = H.HTmap; end 82 | else 83 | Ht = H; 84 | Hmap0 = @(X) sdpnalAXfun(blk,Ht,X); 85 | HTmap0 = @(y) sdpnalAtyfun(blk,Ht,y); 86 | end 87 | else 88 | Hmap0 = @(X) []; HTmap0 = @(y) Zero; 89 | end 90 | if existB 91 | if isstruct(B) 92 | if isfield(B,'Bt'); Bt = B.Bt; end 93 | if isfield(B,'Bmap'); Bmap0 = B.Bmap; end 94 | if isfield(B,'BTmap'); BTmap0 = B.BTmap; end 95 | else 96 | Bt = B; 97 | Bmap0 = @(X) sdpnalAXfun(blk,Bt,X); 98 | BTmap0 = @(y) sdpnalAtyfun(blk,Bt,y); 99 | end 100 | else 101 | Bmap0 = @(X) []; BTmap0 = @(y) Zero; 102 | end 103 | %% 104 | %% 105 | if ~exist('X','var'); X = Zero; end 106 | if ~exist('yE','var'); yE = zeros(length(b),1); end 107 | if ~exist('yI','var'); yI = zeros(length(d),1); end 108 | if ~exist('S','var'); S = Zero; end 109 | if ~existA; yE = []; b = []; end 110 | if ~exist('Xi','var'); xi = zeros(size(Ht,2),1); end 111 | %% initial scaling 112 | %% 113 | Atorg = At; borg = b; 114 | Corg = C; Htorg = Ht; 115 | if existB 116 | Btorg = Bt; dorg = d; 117 | normdorg = 1 + norm(dorg); 118 | else 119 | dorg = 0; 120 | end 121 | normHorg = Fnorm(Htorg); 122 | normCorg = 1 + Fnorm(Corg); 123 | normborg = 1 + norm(borg); 124 | %% 125 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 126 | sGS.op.stoptol = 1e-3; 127 | sGS.op.maxiter = 5000; 128 | sGS.op.phase2 = 1; 129 | sGS.op.stopoption = 3; 130 | fprintf('\n********************************************************'); 131 | fprintf('\n QSDPNAL Phase I '); 132 | fprintf('\n********************************************************'); 133 | [obj,xi,S,yE,yI,X,runhist_sGS,info_sGS] = startfun(blk,H,A,borg,B,dorg,Corg,sGS.op,X,xi,S,yE,yI); 134 | fprintf('\n -------------------------------------------------------'); 135 | sGS.xi0 = xi; sGS.S0 = S; sGS.yI0 = yI; 136 | sGS.yE0= yE; sGS.X0=X; 137 | nE = info_sGS.nE; 138 | nI = info_sGS.nI; 139 | nxi = length(xi); 140 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 141 | sigma = info_sGS.sigma; 142 | normA = info_sGS.normA; DA = info_sGS.DA; 143 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 144 | b = info_sGS.b; 145 | C = info_sGS.C; 146 | sGS.iter = sGS.iter + info_sGS.iter; 147 | sGS.time = sGS.time + info_sGS.totaltime; 148 | Bmap = info_sGS.Bmap; BTmap = info_sGS.BTmap; 149 | if existB 150 | normB = info_sGS.normB; DB = info_sGS.DB; 151 | d = info_sGS.d; 152 | u = info_sGS.u; v = info_sGS.v; 153 | alpha = 1*info_sGS.alpha; 154 | yI = (normB.*yI)/Cscale; 155 | Bt = Bt*DB; 156 | end 157 | At = At*DA; 158 | %% 159 | X = X/bscale; yE = (normA.*yE)/Cscale; 160 | S = S/Cscale; Htxi = HTmap0(xi)/Cscale; 161 | xi = xi/sqrt(bscale*Cscale); 162 | objscale = bscale*Cscale; 163 | %%------------------------------------------------------------------- 164 | %% end of intial stage 165 | %%------------------------------------------------------------------- 166 | %% start QSDPNAL-Phase II 167 | parmain.existH = existH; parmain.existA = existA; parmain.existB = existB; 168 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 169 | parmain.nE = nE; parmain.n = n; parmain.nxi = nxi; parmain.nI = nI; 170 | parmain.normA = normA; 171 | parmain.Htorg = Htorg; 172 | parmain.Htxi = Htxi; 173 | parmain.normHorg = normHorg; 174 | parmain.normborg = normborg; 175 | parmain.normCorg = normCorg; 176 | parmain.normdorg = normdorg; 177 | parmain.use_proximal = use_proximal; 178 | 179 | parmain.sigma = sigma; 180 | parmain.tstart= tstart; 181 | parmain.maxiter = maxiter; 182 | parmain.stoptol = stoptol; 183 | parmain.printyes = printyes; 184 | parmain.sGS = sGS; 185 | 186 | if existB 187 | parmain.Bt = Bt; 188 | parmain.normB = normB; parmain.DB = DB; 189 | parmain.d = d; 190 | parmain.u = u; parmain.v = v; 191 | parmain.alpha = alpha; 192 | end 193 | 194 | parmain.info_sGS = info_sGS; 195 | parmain.obj = obj; 196 | 197 | Binput.Bmap = Bmap; Binput.BTmap = BTmap; 198 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.At = At; 199 | % main solver QSDPNAL-Phase II with restart technique 200 | [X,yE,yI,S,xi,info_main,runhist] = ... 201 | nal_LSImain(blk,Hmap0,HTmap0,Ainput,Binput,b,d,C,parmain,X,yE,yI,S,xi); 202 | iter = info_main.iter; 203 | msg = info_main.msg; 204 | bscale = info_main.bscale; 205 | Cscale = info_main.Cscale; 206 | %%----------------------------------------------------------------- 207 | %% recover orignal variables 208 | %%----------------------------------------------------------------- 209 | if (iter == maxiter) 210 | msg = ' maximum iteration reached'; 211 | info.termcode = 3; 212 | end 213 | X = X*bscale; normX = norm(X,'fro'); 214 | HX = Hmap0(X); 215 | yE = Cscale*(DA*yE); 216 | S = Cscale*S; normS = norm(S,'fro'); 217 | xi = xi*sqrt(bscale*Cscale); 218 | Htxi = HTmap0(xi); 219 | AX = Amap0(X); AtyE = ATmap0(yE); 220 | if existB; 221 | yI = Cscale*(DB*yI); 222 | BtyI = BTmap0(yI); 223 | normyI = norm(yI); 224 | RpI = dorg - Bmap0(X); 225 | dTyI = dorg'*yI; 226 | end 227 | if existA; bTyE = borg'*yE; end 228 | primobj = 0.5*norm(HX)^2 + sum(sum(Corg.*X)); 229 | dualobj = full(dTyI + bTyE - 0.5*Fnorm(xi)^2); 230 | obj = [primobj,dualobj]; 231 | etaQ = Fnorm(xi + Hmap0(X))^2/(1+normHorg^2); 232 | if (true) 233 | etaSp = compnormXn(X) /(1+normX); 234 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 235 | etaS = max(etaSp,etaSc); 236 | if existB 237 | etayId = norm(min(yI,0))/(1+normyI); 238 | normRpI = norm(RpI); 239 | etayIp = norm(max(RpI,0))/(1+normRpI); 240 | etayIc = full(abs(yI'*RpI)/(1+normyI+normRpI)); 241 | etayI = max([etayId,etayIp,etayIc]); 242 | else 243 | etayI = 0; etayId = 0; etayIp = 0; etayIc = 0; 244 | end 245 | end 246 | primfeasorg = max([norm(AX-borg)/normborg,etayIp]); 247 | dualfeasorg = norm(S+AtyE+BtyI+Htxi-Corg,'fro')/normCorg; 248 | ttime = etime(clock,tstart); 249 | runhist.nE = nE; 250 | runhist.ns = n; 251 | runhist.nI = nI; 252 | runhist.iter = iter; 253 | runhist.totaltime = ttime; 254 | runhist.primobjorg = primobj; 255 | runhist.dualobjorg = dualobj; 256 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 257 | runhist.primfeasorg(iter) = primfeasorg; 258 | runhist.dualfeasorg(iter) = dualfeasorg; 259 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS]); 260 | info.nE = nE; 261 | info.ns = n; 262 | info.nI = nI; 263 | info.iter = iter; 264 | info.totaltime = ttime; 265 | info.primobjorg = primobj; 266 | info.dualobjorg = dualobj; 267 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 268 | info.etayI = etayI; 269 | info.etayI1 = etayId; 270 | info.etayI2 = etayIp; 271 | info.etayI3 = etayIc; 272 | info.relerrS = etaS; 273 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 274 | info.relerrQ = etaQ; 275 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ,etayIc]); 276 | info.minX = min(min(X)); 277 | info.maxX = max(max(X)); 278 | info.sGS_iter = sGS.iter; 279 | info.sGS_time = sGS.time; 280 | info.totalNT = sum(runhist.innerNT); 281 | info.totalCG = sum(runhist.innerCG); 282 | if (printminoryes) 283 | if ~isempty(msg); fprintf('\n %s',msg); end 284 | fprintf('\n--------------------------------------------------------------'); 285 | fprintf('------------------'); 286 | fprintf('\n number iter = %2.0d',iter); 287 | fprintf('\n time = %3.2f',ttime); 288 | %fprintf('\n time per iter = %5.4f',ttime/iter); 289 | fprintf('\n time of Phase I = %3.2f', sGS.time); 290 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 291 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 292 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 293 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 294 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 295 | fprintf('\n relerrQ = %3.2e', etaQ); 296 | if existB 297 | fprintf('\n [etayI, etayIp, etayId, etayIc] = [%3.2e %3.2e %3.2e %3.2e]',... 298 | etayI,etayIp,etayId,etayIc); 299 | end 300 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 301 | info.minX,info.maxX); 302 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 303 | fprintf('\n--------------------------------------------------------------'); 304 | fprintf('------------------\n'); 305 | end 306 | %%********************************************************************** 307 | function normXn = compnormXn(X) 308 | 309 | d = eig(full(X)); 310 | normXn = norm(d(d<0)); 311 | %%********************************************************************** 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/qsdpnal.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Netwon based ALM for solving the following QSDP problem 4 | %% D'): max -(\delta_{\cP}^*(-Z) + 1/2 - - ) 5 | %% s.t. Z + S - QW + AE^*yE + B^* yI = C, 6 | %% alpha(u - y_I) = 0, S \in PSD, u >= 0, W \in Range(Q) 7 | %% 8 | %% P): min 1/2 + , s.t., AE X = bE, B X >= d, X\in \cP 9 | %% P'): min 1/2 + , s.t., AE X = bE, B X -alpha v = b_I, X\in \cP, v>=0. 10 | %%************************************************************************* 11 | %% QSDPNAL: 12 | %% Copyright (c) 2015 by 13 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 14 | %%************************************************************************* 15 | 16 | function [obj,Z,W,QW,S,yE,yI,X,runhist,info] = qsdpnal(blk,Q,A,b,C,B,d,options) 17 | %% General options 18 | rng('default'); 19 | maxiter = 5000; 20 | stoptol = 1e-6; 21 | printyes = 1; 22 | printminoryes=1; 23 | startfun = @SCB_qsdp;% Algorithm QSDPNAL-Phase I for initial point 24 | sigma0 = 1; 25 | sGS.iter = 0; 26 | sGS.time = 0; 27 | restart = 1; 28 | restartnum =0; 29 | sGSmaxiter = 1500; 30 | sGSstoptol = 1e-4; 31 | %% information for \cP 32 | nonnegative = 0; L = []; U = []; SignP = []; fV = []; 33 | if isfield(options,'U'); U = options.U; end 34 | if isfield(options,'L'); L = options.L; end 35 | if isfield(options,'SignP'); SignP = options.SignP; end 36 | if isfield(options,'fV'); fV = options.fV; end 37 | if isfield(options,'nonnegative'); nonnegative = options.nonnegative; end 38 | %% other options 39 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 40 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 41 | if isfield(options,'sGSmaxiter'); sGSmaxiter = options.sGSmaxiter; end 42 | if isfield(options,'sGSstoptol'); sGSstoptol = options.sGSstoptol; end 43 | 44 | fprintf('\n'); 45 | fprintf('\n============================================================================================================'); 46 | fprintf('\n************************************************************************************************************'); 47 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 48 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 49 | fprintf('\n************************************************************************************************************'); 50 | fprintf('\n============================================================================================================'); 51 | fprintf('\n************************************************************************************************************'); 52 | fprintf('\n* Reference *'); 53 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 54 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 55 | fprintf('\n************************************************************************************************************'); 56 | fprintf('\n============================================================================================================'); 57 | fprintf('\n'); 58 | %% problem property 59 | existQ = ~isempty(Q); 60 | existA = ~isempty(A); 61 | existB = ~isempty(B); 62 | tstart = clock; 63 | n = blk{1,2}; 64 | nbar = n*(n+1)/2; 65 | Zero = sparse(n,n); 66 | Fnorm = @(X) mexFnorm(X); 67 | %% AEmap, AETmap, AImap, AITmap, Qmap 68 | if existA 69 | if isstruct(A) 70 | if isfield(A,'At'); At = A.At; end 71 | if isfield(A,'Amap'); Amap0 = A.Amap; end 72 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 73 | else 74 | At = A; 75 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 76 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 77 | end 78 | end 79 | if existB 80 | if isstruct(B) 81 | if isfield(B,'Bt'); Bt = B.Bt; end 82 | if isfield(B,'Bmap'); Bmap0 = B.Bmap; end 83 | if isfield(B,'BTmap'); BTmap0 = B.BTmap; end 84 | else 85 | Bt = B; 86 | Bmap0 = @(X) sdpnalAXfun(blk,Bt,X); 87 | BTmap0 = @(y) sdpnalAtyfun(blk,Bt,y); 88 | end 89 | end 90 | if existQ 91 | Qmap0 = @(X) feval(Q.QXfun,X); 92 | else 93 | Qmap0 = @(X) sparse(n,n); 94 | end 95 | %% 96 | %% initial scaling 97 | %% 98 | Atorg = At; borg = b; 99 | Corg = C; Lorg = L; Uorg = U; fVorg = fV; 100 | normCorg = 1 + Fnorm(Corg); 101 | normborg = 1 + norm(borg); 102 | if existB; 103 | Btorg = Bt; dorg = d; 104 | normdorg = 1 + norm(dorg); 105 | else 106 | dorg = 0; d = 0; 107 | end 108 | %% 109 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 110 | sGS.op.stoptol = sGSstoptol; %1e-4; % tol of initial stage 111 | sGS.op.maxiter = sGSmaxiter; %1500; % maxiter of initial stage 112 | sGS.op.lowerbound = Lorg; sGS.op.SignP = SignP; 113 | sGS.op.upperbound = Uorg; sGS.op.fV = fVorg; 114 | sGS.op.nonnegative = nonnegative; 115 | fprintf('\n********************************************************'); 116 | fprintf('\n QSDPNAL Phase I '); 117 | fprintf('\n********************************************************'); 118 | [obj,Z,W,QW,S,yE,yI,X,runhist_sGS,info_sGS] = startfun(blk,Q,A,borg,Corg,B,dorg,sGS.op); 119 | fprintf('\n -------------------------------------------------------'); 120 | sGS.Z0 = Z; sGS.W0 = W; sGS.QW0 = QW; sGS.S0 = S; 121 | sGS.yE0= yE; sGS.yI0=yI; sGS.X0=X; 122 | nE = info_sGS.nE; nI = info_sGS.nI; 123 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 124 | sigma = info_sGS.sigma; 125 | if existQ; 126 | Qmap = info_sGS.Qmap; parQ = info_sGS.parQ; 127 | normQorg = info_sGS.normQorg; 128 | else 129 | Qmap = Qmap0; 130 | end 131 | normA = info_sGS.normA; DA = info_sGS.DA; 132 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 133 | Bmap = info_sGS.Bmap; BTmap = info_sGS.BTmap; 134 | b = info_sGS.b; 135 | C = info_sGS.C; 136 | if existB; 137 | normB = info_sGS.normB; DB = info_sGS.DB; 138 | parB = info_sGS.parB; 139 | d = info_sGS.d; 140 | u = info_sGS.u; v = info_sGS.v; 141 | alpha = info_sGS.alpha; 142 | end 143 | sGS.iter = sGS.iter + info_sGS.iter; 144 | sGS.time = sGS.time + info_sGS.totaltime; 145 | %% 146 | X = X/bscale; yE = (normA.*yE)/Cscale; 147 | Z = Z/Cscale; S = S/Cscale; 148 | QW = QW/Cscale; W = W/bscale; 149 | objscale = bscale*Cscale; 150 | if existB; yI = (normB.*yI)/Cscale; end 151 | L = L/bscale; U = U/bscale; fV = fV/bscale; 152 | %%------------------------------------------------------------------- 153 | %% end of intial stage 154 | %%------------------------------------------------------------------- 155 | %% start QSDPNAL-Phase II 156 | parmain.existQ = existQ; parmain.existB = existB; parmain.existA = existA; 157 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 158 | 159 | parmain.DA = DA; 160 | parmain.nE = nE; parmain.nI = nI; parmain.n = n; 161 | 162 | parmain.nonnegative = nonnegative; parmain.L = L; parmain.U = U; 163 | parmain.SignP = SignP; parmain.fV = fV; 164 | 165 | parmain.normA = normA; 166 | parmain.normborg = normborg; 167 | parmain.normCorg = normCorg; 168 | parmain.normQorg = normQorg; 169 | 170 | parmain.sigma = sigma; 171 | 172 | parmain.tstart= tstart; 173 | parmain.maxiter = maxiter; 174 | parmain.stoptol = stoptol; 175 | parmain.printyes = printyes; 176 | parmain.sGS = sGS; 177 | parmain.restart = restart; 178 | 179 | if existB 180 | parmain.alpha = alpha; 181 | parmain.normB = normB; 182 | parmain.parB = parB; 183 | parmain.normB = normB; parmain.DB = DB; 184 | parmain.d = d; 185 | parmain.normdorg = normdorg; 186 | parmain.u = u; parmain.v = v; 187 | parmain.alpha = alpha; 188 | end 189 | 190 | parmain.info_sGS = info_sGS; 191 | parmain.obj = obj; 192 | 193 | parmain.parQ = parQ; 194 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; 195 | Binput.Bmap = Bmap; Binput.BTmap = BTmap; 196 | 197 | parmain.Lorg = Lorg; parmain.Uorg = Uorg; parmain.fVorg = fVorg; 198 | parmain.borg = borg; parmain.Corg = Corg; parmain.dorg = dorg; 199 | parmain.startfun = startfun; 200 | 201 | % main solver QSDPNAL-Phase II with restart technique 202 | [Z,W,QW,S,yE,yI,X,info_main,runhist] = ... 203 | nal_qsdpBIQmain(blk,Q,Qmap,A,Ainput,B,Binput,b,C,d,parmain,Z,W,QW,S,yE,yI,X); 204 | iter = info_main.iter; 205 | msg = info_main.msg; 206 | Ztmp = info_main.Ztmp; 207 | bscale = info_main.bscale; 208 | Cscale = info_main.Cscale; 209 | sGS = info_main.sGS; 210 | %%----------------------------------------------------------------- 211 | %% recover orignal variables 212 | %%----------------------------------------------------------------- 213 | if (iter == maxiter) 214 | msg = ' maximum iteration reached'; 215 | info.termcode = 3; 216 | end 217 | X = X*bscale; normX = norm(X,'fro'); 218 | QX = Qmap0(X); 219 | yE = Cscale*(DA*yE); 220 | Z = Cscale*Z; normZ = norm(Z,'fro'); Ztmp = Ztmp*bscale; 221 | S = Cscale*S; normS = norm(S,'fro'); 222 | QW = Cscale*QW; W = W*bscale; 223 | if existB; 224 | yI = Cscale*(DB*yI); 225 | BtyI = BTmap0(yI); 226 | normyI = norm(yI); 227 | RpI = dorg - Bmap0(X); 228 | dTyI = dorg'*yI; 229 | else 230 | dTyI = 0; BtyI = Zero; 231 | end 232 | AX = Amap0(X); AtyE = ATmap0(yE); 233 | primobj = 0.5*sum(sum(X.*QX)) + sum(sum(Corg.*X)); 234 | %if existB; dTyI = dorg'*yI; else dTyI = 0; end 235 | dualobj = borg'*yE + sum(sum(Z.*Ztmp)) - 0.5*sum(sum(W.*QW)) + dTyI; 236 | obj = [primobj,dualobj]; 237 | if ~isempty(L) 238 | minLX = min(min(X(SignP.L == 1))); 239 | end 240 | if ~isempty(U) 241 | maxUX = max(max(X(SignP.U == 3))); 242 | end 243 | if existQ 244 | etaQ = Fnorm(QX - QW)/normQorg; 245 | else 246 | etaQ = 0; 247 | end 248 | if (true) 249 | relerrS1 = compnormXn(X) /(1+normX); 250 | relerrS2 = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 251 | etaS = max(relerrS1,relerrS2); 252 | projPXmZ = proj_LU_new(X-Z,nonnegative,SignP,Lorg,Uorg,fVorg); 253 | etaZ = Fnorm(X-projPXmZ)/(1+normZ+normX); 254 | if existB 255 | etayId = norm(min(yI,0))/(1+normyI); 256 | normRpI = norm(RpI); 257 | etayIp = norm(max(RpI,0))/(1+normRpI); 258 | etayIc = full(abs(yI'*RpI)/(1+normyI+normRpI)); 259 | etayI = max([etayId,etayIp,etayIc]); 260 | else 261 | etayI = 0; etayId = 0; etayIp = 0; etayIc = 0; 262 | end 263 | end 264 | primfeasorg = max(norm(AX-borg)/normborg,etayIp); 265 | dualfeasorg = max(norm(Z+S+AtyE+BtyI-QW-Corg,'fro')/normCorg,etayId); 266 | ttime = etime(clock,tstart); 267 | runhist.nE = nE; 268 | runhist.ns = n; 269 | runhist.nI = nI; 270 | runhist.iter = iter; 271 | runhist.totaltime = ttime; 272 | runhist.primobjorg = primobj; 273 | runhist.dualobjorg = dualobj; 274 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 275 | runhist.primfeasorg(iter) = primfeasorg; 276 | runhist.dualfeasorg(iter) = dualfeasorg; 277 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaZ,etayIc]); 278 | info.nE = nE; 279 | info.nI = nI; 280 | info.ns = n; 281 | info.iter = iter; 282 | info.totaltime = ttime; 283 | info.primobjorg = primobj; 284 | info.dualobjorg = dualobj; 285 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 286 | info.etaS = etaS; 287 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 288 | info.etaZ = etaZ; 289 | info.etaQ = etaQ; 290 | info.etayI = etayI; 291 | info.etayI1 = etayId; 292 | info.etayI2 = etayIp; 293 | info.etayI3 = etayIc; 294 | info.eta = max([dualfeasorg,primfeasorg,etaS,etaQ,etaZ,etayIc]); 295 | info.minX = min(min(X)); 296 | info.maxX = max(max(X)); 297 | info.sGS_iter = sGS.iter; 298 | info.sGS_time = sGS.time; 299 | info.totalNT = sum(runhist.innerNT); 300 | info.totalCG = sum(runhist.innerCG); 301 | if (printminoryes) 302 | if ~isempty(msg); fprintf('\n %s',msg); end 303 | fprintf('\n--------------------------------------------------------------'); 304 | fprintf('------------------'); 305 | fprintf('\n number iter = %2.0d',iter); 306 | fprintf('\n time = %3.2f',ttime); 307 | %fprintf('\n time per iter = %5.4f',ttime/iter); 308 | fprintf('\n time of Phase I = %3.2f', sGS.time); 309 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 310 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 311 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 312 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 313 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 314 | fprintf('\n relerrQ = %3.2e', etaQ); 315 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 316 | fprintf('\n etaZ = %3.2e', etaZ); 317 | fprintf('\n etaS = %3.2e', etaS); 318 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 319 | info.minX,info.maxX); 320 | if ~isempty(L) 321 | fprintf('\n Lower bound for bounded part = %3.2e',minLX); 322 | end 323 | if ~isempty(U) 324 | fprintf('\n Upper bound for bounded part = %3.2e',maxUX); 325 | end 326 | fprintf('\n--------------------------------------------------------------'); 327 | fprintf('------------------\n'); 328 | end 329 | %%********************************************************************** 330 | function normXn = compnormXn(X) 331 | 332 | d = eig(full(X)); 333 | normXn = norm(d(d<0)); 334 | %%********************************************************************** 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/qsdpnal_BIQ.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Netwon based ALM for solving the following QSDP problem 4 | %% QSDP-BIQ problem 5 | %% D'): max -(\delta_{\cP}^*(-Z) + 1/2 - - ) 6 | %% s.t. Z + S - QW + AE^*yE + B^* yI = C, 7 | %% alpha(u - y_I) = 0, S \in PSD, u >= 0, W \in Range(Q) 8 | %% 9 | %% P): min 1/2 + , s.t., AE X = bE, B X >= d, X\in \cP 10 | %% P'): min 1/2 + , s.t., AE X = bE, B X -alpha v = b_I, X\in \cP, v>=0. 11 | %%************************************************************************* 12 | %% QSDPNAL: 13 | %% Copyright (c) 2015 by 14 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | %%************************************************************************* 16 | 17 | function [obj,Z,W,QW,S,yE,yI,X,runhist,info] = qsdpnal_BIQ(blk,Q,A,b,C,B,d,options) 18 | %% General options 19 | rng('default'); 20 | maxiter = 5000; 21 | stoptol = 1e-6; 22 | printyes = 1; 23 | printminoryes=1; 24 | startfun = @SCB_qsdp;% Algorithm QSDPNAL-Phase I for initial point 25 | sigma0 = 1; 26 | sGS.iter = 0; 27 | sGS.time = 0; 28 | restart = 1; 29 | restartnum =0; 30 | %% information for \cP 31 | nonnegative = 0; L = []; U = []; SignP = []; fV = []; 32 | if isfield(options,'upperbound'); U = options.upperbound; end 33 | if isfield(options,'lowerbound'); L = options.lowerbound; end 34 | if isfield(options,'SignP'); SignP = options.SignP; end 35 | if isfield(options,'fV'); fV = options.fV; end 36 | if isfield(options,'nonnegative'); nonnegative = options.nonnegative; end 37 | 38 | 39 | fprintf('\n'); 40 | fprintf('\n============================================================================================================'); 41 | fprintf('\n************************************************************************************************************'); 42 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 43 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 44 | fprintf('\n************************************************************************************************************'); 45 | fprintf('\n============================================================================================================'); 46 | fprintf('\n************************************************************************************************************'); 47 | fprintf('\n* Reference *'); 48 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 49 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 50 | fprintf('\n************************************************************************************************************'); 51 | fprintf('\n============================================================================================================'); 52 | fprintf('\n'); 53 | %% problem property 54 | existQ = ~isempty(Q); 55 | existA = ~isempty(A); 56 | existB = ~isempty(B); 57 | tstart = clock; 58 | n = blk{1,2}; 59 | nbar = n*(n+1)/2; 60 | Zero = sparse(n,n); 61 | Fnorm = @(X) mexFnorm(X); 62 | %% AEmap, AETmap, AImap, AITmap, Qmap 63 | if existA 64 | if isstruct(A) 65 | if isfield(A,'At'); At = A.At; end 66 | if isfield(A,'Amap'); Amap0 = A.Amap; end 67 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 68 | else 69 | At = A; 70 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 71 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 72 | end 73 | end 74 | if existB 75 | if isstruct(B) 76 | if isfield(B,'Bt'); Bt = B.Bt; end 77 | if isfield(B,'Bmap'); Bmap0 = B.Bmap; end 78 | if isfield(B,'BTmap'); BTmap0 = B.BTmap; end 79 | else 80 | Bt = B; 81 | Bmap0 = @(X) sdpnalAXfun(blk,Bt,X); 82 | BTmap0 = @(y) sdpnalAtyfun(blk,Bt,y); 83 | end 84 | end 85 | if existQ 86 | Qmap0 = @(X) feval(Q.QXfun,X); 87 | else 88 | Qmap0 = @(X) sparse(n,n); 89 | end 90 | %% 91 | %% initial scaling 92 | %% 93 | Atorg = At; borg = b; 94 | Corg = C; Lorg = L; Uorg = U; fVorg = fV; 95 | normCorg = 1 + Fnorm(Corg); 96 | normborg = 1 + norm(borg); 97 | if existB; 98 | Btorg = Bt; dorg = d; 99 | normdorg = 1 + norm(dorg); 100 | else 101 | dorg = 0; d = 0; 102 | end 103 | %% 104 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 105 | sGS.op.stoptol = 1e-4; % tol of initial stage 106 | sGS.op.maxiter = 1500; % maxiter of initial stage 107 | sGS.op.lowerbound = Lorg; sGS.op.SignP = SignP; 108 | sGS.op.upperbound = Uorg; sGS.op.fV = fVorg; 109 | sGS.op.nonnegative = nonnegative; 110 | fprintf('\n********************************************************'); 111 | fprintf('\n QSDPNAL Phase I '); 112 | fprintf('\n********************************************************'); 113 | [obj,Z,W,QW,S,yE,yI,X,runhist_sGS,info_sGS] = startfun(blk,Q,A,borg,Corg,B,dorg,sGS.op); 114 | fprintf('\n -------------------------------------------------------'); 115 | sGS.Z0 = Z; sGS.W0 = W; sGS.QW0 = QW; sGS.S0 = S; 116 | sGS.yE0= yE; sGS.yI0=yI; sGS.X0=X; 117 | nE = info_sGS.nE; nI = info_sGS.nI; 118 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 119 | sigma = info_sGS.sigma; 120 | if existQ; 121 | Qmap = info_sGS.Qmap; parQ = info_sGS.parQ; 122 | normQorg = info_sGS.normQorg; 123 | else 124 | Qmap = Qmap0; 125 | end 126 | normA = info_sGS.normA; DA = info_sGS.DA; 127 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 128 | Bmap = info_sGS.Bmap; BTmap = info_sGS.BTmap; 129 | b = info_sGS.b; 130 | C = info_sGS.C; 131 | if existB; 132 | normB = info_sGS.normB; DB = info_sGS.DB; 133 | parB = info_sGS.parB; 134 | d = info_sGS.d; 135 | u = info_sGS.u; v = info_sGS.v; 136 | alpha = info_sGS.alpha; 137 | end 138 | sGS.iter = sGS.iter + info_sGS.iter; 139 | sGS.time = sGS.time + info_sGS.totaltime; 140 | %% 141 | X = X/bscale; yE = (normA.*yE)/Cscale; 142 | Z = Z/Cscale; S = S/Cscale; 143 | QW = QW/Cscale; W = W/bscale; 144 | objscale = bscale*Cscale; 145 | if existB; yI = (normB.*yI)/Cscale; end 146 | L = L/bscale; U = U/bscale; fV = fV/bscale; 147 | %%------------------------------------------------------------------- 148 | %% end of intial stage 149 | %%------------------------------------------------------------------- 150 | %% start QSDPNAL-Phase II 151 | parmain.existQ = existQ; parmain.existB = existB; parmain.existA = existA; 152 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 153 | 154 | parmain.DA = DA; 155 | parmain.nE = nE; parmain.nI = nI; parmain.n = n; 156 | 157 | parmain.nonnegative = nonnegative; parmain.L = L; parmain.U = U; 158 | parmain.SignP = SignP; parmain.fV = fV; 159 | 160 | parmain.normA = normA; 161 | parmain.normborg = normborg; 162 | parmain.normCorg = normCorg; 163 | parmain.normQorg = normQorg; 164 | 165 | parmain.sigma = sigma; 166 | 167 | parmain.tstart= tstart; 168 | parmain.maxiter = maxiter; 169 | parmain.stoptol = stoptol; 170 | parmain.printyes = printyes; 171 | parmain.sGS = sGS; 172 | parmain.restart = restart; 173 | 174 | if existB 175 | parmain.alpha = alpha; 176 | parmain.normB = normB; 177 | parmain.parB = parB; 178 | parmain.normB = normB; parmain.DB = DB; 179 | parmain.d = d; 180 | parmain.normdorg = normdorg; 181 | parmain.u = u; parmain.v = v; 182 | parmain.alpha = alpha; 183 | end 184 | 185 | parmain.info_sGS = info_sGS; 186 | parmain.obj = obj; 187 | 188 | parmain.parQ = parQ; 189 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; 190 | Binput.Bmap = Bmap; Binput.BTmap = BTmap; 191 | 192 | parmain.Lorg = Lorg; parmain.Uorg = Uorg; parmain.fVorg = fVorg; 193 | parmain.borg = borg; parmain.Corg = Corg; parmain.dorg = dorg; 194 | parmain.startfun = startfun; 195 | 196 | % main solver QSDPNAL-Phase II with restart technique 197 | [Z,W,QW,S,yE,yI,X,info_main,runhist] = ... 198 | nal_qsdpBIQmain(blk,Q,Qmap,A,Ainput,B,Binput,b,C,d,parmain,Z,W,QW,S,yE,yI,X); 199 | iter = info_main.iter; 200 | msg = info_main.msg; 201 | Ztmp = info_main.Ztmp; 202 | bscale = info_main.bscale; 203 | Cscale = info_main.Cscale; 204 | sGS = info_main.sGS; 205 | %%----------------------------------------------------------------- 206 | %% recover orignal variables 207 | %%----------------------------------------------------------------- 208 | if (iter == maxiter) 209 | msg = ' maximum iteration reached'; 210 | info.termcode = 3; 211 | end 212 | X = X*bscale; normX = norm(X,'fro'); 213 | QX = Qmap0(X); 214 | yE = Cscale*(DA*yE); 215 | Z = Cscale*Z; normZ = norm(Z,'fro'); Ztmp = Ztmp*bscale; 216 | S = Cscale*S; normS = norm(S,'fro'); 217 | QW = Cscale*QW; W = W*bscale; 218 | if existB; 219 | yI = Cscale*(DB*yI); 220 | BtyI = BTmap0(yI); 221 | normyI = norm(yI); 222 | RpI = dorg - Bmap0(X); 223 | end 224 | AX = Amap0(X); AtyE = ATmap0(yE); 225 | primobj = full(0.5*sum(sum(X.*QX)) + sum(sum(Corg.*X))); 226 | if existB; dTyI = dorg'*yI; else dTyI = 0; end 227 | dualobj = full(borg'*yE + sum(sum(Z.*Ztmp)) - 0.5*sum(sum(W.*QW)) + dTyI); 228 | obj = [primobj,dualobj]; 229 | if ~isempty(L) 230 | minLX = min(min(X(SignP.L == 1))); 231 | end 232 | if ~isempty(U) 233 | maxUX = max(max(X(SignP.U == 3))); 234 | end 235 | if existQ 236 | etaQ = Fnorm(QX - QW)/normQorg; 237 | else 238 | etaQ = 0; 239 | end 240 | if (true) 241 | relerrS1 = compnormXn(X) /(1+normX); 242 | relerrS2 = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 243 | etaS = max(relerrS1,relerrS2); 244 | projPXmZ = proj_LU_new(X-Z,nonnegative,SignP,Lorg,Uorg,fVorg); 245 | etaZ = Fnorm(X-projPXmZ)/(1+normZ+normX); 246 | if existB 247 | etayId = norm(min(yI,0))/(1+normyI); 248 | normRpI = norm(RpI); 249 | etayIp = norm(max(RpI,0))/(1+normRpI); 250 | etayIc = full(abs(yI'*RpI)/(1+normyI+normRpI)); 251 | etayI = max([etayId,etayIp,etayIc]); 252 | else 253 | etayI = 0; etayId = 0; etayIp = 0; etayIc = 0; 254 | end 255 | end 256 | primfeasorg = max(norm(AX-borg)/normborg,etayIp); 257 | dualfeasorg = max(norm(Z+S+AtyE+BtyI-QW-Corg,'fro')/normCorg,etayId); 258 | ttime = etime(clock,tstart); 259 | runhist.nE = nE; 260 | runhist.ns = n; 261 | runhist.nI = nI; 262 | runhist.iter = iter; 263 | runhist.totaltime = ttime; 264 | runhist.primobjorg = primobj; 265 | runhist.dualobjorg = dualobj; 266 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 267 | runhist.primfeasorg(iter) = primfeasorg; 268 | runhist.dualfeasorg(iter) = dualfeasorg; 269 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaZ,etayIc]); 270 | info.nE = nE; 271 | info.nI = nI; 272 | info.ns = n; 273 | info.iter = iter; 274 | info.totaltime = ttime; 275 | info.primobjorg = primobj; 276 | info.dualobjorg = dualobj; 277 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 278 | info.relerrS = etaS; 279 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 280 | info.relerrZ = etaZ; 281 | info.relerrQ = etaQ; 282 | info.etayI = etayI; 283 | info.etayI1 = etayId; 284 | info.etayI2 = etayIp; 285 | info.etayI3 = etayIc; 286 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ,etaZ,etayIc]); 287 | info.minX = min(min(X)); 288 | info.maxX = max(max(X)); 289 | info.sGS_iter = sGS.iter; 290 | info.sGS_time = sGS.time; 291 | info.totalNT = sum(runhist.innerNT); 292 | info.totalCG = sum(runhist.innerCG); 293 | if (printminoryes) 294 | if ~isempty(msg); fprintf('\n %s',msg); end 295 | fprintf('\n--------------------------------------------------------------'); 296 | fprintf('------------------'); 297 | fprintf('\n number iter = %2.0d',iter); 298 | fprintf('\n time = %3.2f',ttime); 299 | %fprintf('\n time per iter = %5.4f',ttime/iter); 300 | fprintf('\n time of Phase I = %3.2f', sGS.time); 301 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 302 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 303 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 304 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 305 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 306 | fprintf('\n relerrQ = %3.2e', etaQ); 307 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 308 | fprintf('\n etaZ = %3.2e', etaZ); 309 | fprintf('\n etaS = %3.2e', etaS); 310 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 311 | info.minX,info.maxX); 312 | if ~isempty(L) 313 | fprintf('\n Lower bound for bounded part = %3.2e',minLX); 314 | end 315 | if ~isempty(U) 316 | fprintf('\n Upper bound for bounded part = %3.2e',maxUX); 317 | end 318 | fprintf('\n--------------------------------------------------------------'); 319 | fprintf('------------------\n'); 320 | end 321 | %%********************************************************************** 322 | function normXn = compnormXn(X) 323 | 324 | d = eig(full(X)); 325 | normXn = norm(d(d<0)); 326 | %%********************************************************************** 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/qsdpnal_NCM.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Netwon based ALM for solving the following NCM problem 4 | %% (P) min {1/2||H o X||_F^2 + | A(X)=b, X \in K} 5 | %% where K = psd cone 6 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H o X = Y, X\in K} 7 | %% 8 | %% (D') max -1/2 ||Xi||^2 + 9 | %% s.t. H o Xi + S + A*y = C, 10 | %% S \in PSD. 11 | %%************************************************************************* 12 | %% QSDPNAL: 13 | %% Copyright (c) 2015 by 14 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | %%************************************************************************* 16 | 17 | function [obj,Xi,S,yE,X,runhist,info] = qsdpnal_NCM(blk,H,A,b,C,options,X,Xi,S,yE) 18 | %% General options 19 | rng('default'); 20 | maxiter = 5000; 21 | stoptol = 1e-6; 22 | printyes = 1; 23 | printminoryes=1; 24 | startfun = @SCB_NCM; % Algorithm QSDPNAL-Phase I for initial point 25 | sigma0 = 1; 26 | sGS.iter = 0; 27 | sGS.time = 0; 28 | use_proximal = 1; 29 | restart = 1; 30 | %% options from users 31 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 32 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 33 | if isfield(options,'printyes'); printyes = options.printyes; end 34 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 35 | if isfield(options,'sigma'); sigma0 = options.sigma; end 36 | 37 | fprintf('\n'); 38 | fprintf('\n============================================================================================================'); 39 | fprintf('\n************************************************************************************************************'); 40 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 41 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 42 | fprintf('\n************************************************************************************************************'); 43 | fprintf('\n============================================================================================================'); 44 | fprintf('\n************************************************************************************************************'); 45 | fprintf('\n* Reference *'); 46 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 47 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 48 | fprintf('\n************************************************************************************************************'); 49 | fprintf('\n============================================================================================================'); 50 | fprintf('\n'); 51 | %% problem property 52 | existA = ~isempty(A); 53 | tstart = clock; 54 | n = blk{1,2}; 55 | nbar = n*(n+1)/2; 56 | Zero = sparse(n,n); 57 | Fnorm = @(X) mexFnorm(X); 58 | Qsolver = 'pcg'; 59 | %% AEmap, AETmap, AImap, AITmap, Qmap 60 | if existA 61 | if isstruct(A) 62 | if isfield(A,'At'); At = A.At; end 63 | if isfield(A,'Amap'); Amap0 = A.Amap; end 64 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 65 | else 66 | At = A; 67 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 68 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 69 | end 70 | else 71 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 72 | end 73 | %% 74 | %% initial scaling 75 | %% 76 | Atorg = At; borg = b; 77 | Corg = C; Horg = H; 78 | normHorg = Fnorm(Horg); 79 | normCorg = 1 + Fnorm(Corg); 80 | normborg = 1 + norm(borg); 81 | %% 82 | if ~exist('X','var'); X = Zero; end 83 | if ~exist('yE','var'); yE = zeros(length(b),1); end 84 | if ~exist('S','var'); S = Zero; end 85 | if ~existA; yE = []; b = []; end 86 | if ~exist('Xi','var'); Xi = Zero; end 87 | %% 88 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 89 | sGS.op.stoptol = 1e-4; % tol of initial stage 90 | sGS.op.maxiter = 200; % maxiter of initial stage 91 | sGS.op.phase2 = 1; 92 | fprintf('\n********************************************************'); 93 | fprintf('\n QSDPNAL Phase I '); 94 | fprintf('\n********************************************************'); 95 | [obj,Xi,S,yE,X,runhist_sGS,info_sGS] = startfun(blk,Horg,A,borg,Corg,sGS.op,X,Xi,S,yE); 96 | fprintf('\n -------------------------------------------------------'); 97 | sGS.Xi0 = Xi; sGS.S0 = S; 98 | sGS.yE0= yE; sGS.X0=X; 99 | nE = info_sGS.nE; 100 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 101 | sigma = info_sGS.sigma; 102 | normA = info_sGS.normA; DA = info_sGS.DA; 103 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 104 | b = info_sGS.b; 105 | C = info_sGS.C; 106 | sGS.iter = sGS.iter + info_sGS.iter; 107 | sGS.time = sGS.time + info_sGS.totaltime; 108 | %% 109 | X = X/bscale; yE = (normA.*yE)/Cscale; 110 | S = S/Cscale; HXi = Horg.*Xi/Cscale; 111 | Xi = Xi/sqrt(bscale*Cscale); 112 | H = sqrt(bscale/Cscale)*Horg; 113 | objscale = bscale*Cscale; 114 | At = At*DA; 115 | 116 | %%------------------------------------------------------------------- 117 | %% end of intial stage 118 | %%------------------------------------------------------------------- 119 | %% start QSDPNAL-Phase II 120 | parmain.existA = existA; 121 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 122 | parmain.nE = nE; parmain.n = n; 123 | parmain.normA = normA; 124 | parmain.HXi = HXi; 125 | parmain.normHorg = normHorg; 126 | parmain.normborg = normborg; 127 | parmain.normCorg = normCorg; 128 | parmain.use_proximal = use_proximal; 129 | 130 | parmain.sigma = sigma; 131 | parmain.tstart= tstart; 132 | parmain.maxiter = maxiter; 133 | parmain.stoptol = stoptol; 134 | parmain.printyes = printyes; 135 | parmain.sGS = sGS; 136 | 137 | parmain.info_sGS = info_sGS; 138 | parmain.obj = obj; 139 | 140 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; 141 | % main solver QSDPNAL-Phase II with restart technique 142 | [X,yE,S,Xi,info_main,runhist] = ... 143 | nal_NCMmain(blk,H,At,Ainput,b,C,parmain,X,yE,S,Xi); 144 | iter = info_main.iter; 145 | msg = info_main.msg; 146 | bscale = info_main.bscale; 147 | Cscale = info_main.Cscale; 148 | %%----------------------------------------------------------------- 149 | %%----------------------------------------------------------------- 150 | %% recover orignal variables 151 | %%----------------------------------------------------------------- 152 | if (iter == maxiter) 153 | msg = ' maximum iteration reached'; 154 | info.termcode = 3; 155 | end 156 | X = X*bscale; normX = norm(X,'fro'); 157 | HX = Horg.*X; 158 | yE = Cscale*(DA*yE); 159 | S = Cscale*S; normS = norm(S,'fro'); 160 | Xi = Xi*sqrt(bscale*Cscale); 161 | HXi = Horg.*Xi; 162 | AX = Amap0(X); AtyE = ATmap0(yE); 163 | if existA; bTyE = borg'*yE; end 164 | primobj = 0.5*Fnorm(HX)^2 + sum(sum(Corg.*X)); 165 | dualobj = bTyE - 0.5*Fnorm(Xi)^2; 166 | obj = [primobj,dualobj]; 167 | etaQ = Fnorm(Xi + Horg.*X)^2/(1+normHorg^2); 168 | if (true) 169 | etaSp = compnormXn(X) /(1+normX); 170 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 171 | etaS = max(etaSp,etaSc); 172 | end 173 | primfeasorg = norm(AX-borg)/normborg; 174 | dualfeasorg = norm(S+AtyE+HXi-Corg,'fro')/normCorg; 175 | ttime = etime(clock,tstart); 176 | runhist.nE = nE; 177 | runhist.ns = n; 178 | runhist.iter = iter; 179 | runhist.totaltime = ttime; 180 | runhist.primobjorg = primobj; 181 | runhist.dualobjorg = dualobj; 182 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 183 | runhist.primfeasorg(iter) = primfeasorg; 184 | runhist.dualfeasorg(iter) = dualfeasorg; 185 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS]); 186 | info.nE = nE; 187 | info.ns = n; 188 | info.iter = iter; 189 | info.totaltime = ttime; 190 | info.primobjorg = primobj; 191 | info.dualobjorg = dualobj; 192 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 193 | info.relerrS = etaS; 194 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 195 | info.relerrQ = etaQ; 196 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 197 | info.minX = min(min(X)); 198 | info.maxX = max(max(X)); 199 | info.sGS_iter = sGS.iter; 200 | info.sGS_time = sGS.time; 201 | info.totalNT = sum(runhist.innerNT); 202 | info.totalCG = sum(runhist.innerCG); 203 | if (printminoryes) 204 | if ~isempty(msg); fprintf('\n %s',msg); end 205 | fprintf('\n--------------------------------------------------------------'); 206 | fprintf('------------------'); 207 | fprintf('\n number iter = %2.0d',iter); 208 | fprintf('\n time = %3.2f',ttime); 209 | %fprintf('\n time per iter = %5.4f',ttime/iter); 210 | fprintf('\n time of Phase I = %3.2f', sGS.time); 211 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 212 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 213 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 214 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 215 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 216 | fprintf('\n relerrQ = %3.2e', etaQ); 217 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 218 | info.minX,info.maxX); 219 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 220 | fprintf('\n--------------------------------------------------------------'); 221 | fprintf('------------------\n'); 222 | end 223 | %%********************************************************************** 224 | function normXn = compnormXn(X) 225 | 226 | d = eig(full(X)); 227 | normXn = norm(d(d<0)); 228 | %%********************************************************************** 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/qsdpnal_NCMP.m: -------------------------------------------------------------------------------- 1 | %%************************************************************************* 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Newton based ALM for solving NCM problems with 4 | %% Polyhderal constraints: 5 | %% (P) min {1/2||H o X||_F^2 + | A(X)=b, X \in K, X\in P} 6 | %% where K = psd cone, P is ployhedral set e.g., P = {X | L<= X <= U}. 7 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H o X = Y, X\in K, X\in P} 8 | %% 9 | %% (D') max -\delta_{P}^*(-Z) - 1/2 ||Xi||^2 + 10 | %% s.t. Z + H o Xi + S + A*y = C, 11 | %% S \in PSD. 12 | %%************************************************************************* 13 | %% QSDPNAL: 14 | %% Copyright (c) 2015 by 15 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 16 | %%************************************************************************* 17 | 18 | function [obj,Z,Xi,S,yE,X,runhist,info] = qsdpnal_NCMP(blk,H,A,b,C,options,X,Z,Xi,S,yE) 19 | %% General options 20 | rng('default'); 21 | maxiter = 5000; 22 | stoptol = 1e-6; 23 | printyes = 1; 24 | printminoryes=1; 25 | startfun = @SCB_NCMP; % Algorithm QSDPNAL-Phase I for initial point 26 | sigma0 = 1; 27 | sGS.iter = 0; 28 | sGS.time = 0; 29 | use_proximal = 1; 30 | restart = 1; 31 | %% options from users 32 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 33 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 34 | if isfield(options,'printyes'); printyes = options.printyes; end 35 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 36 | if isfield(options,'sigma'); sigma0 = options.sigma; end 37 | %% information for \cP 38 | nonnegative = 0; L = []; U = []; SignP = []; fV = []; 39 | if isfield(options,'upperbound'); U = options.upperbound; end 40 | if isfield(options,'lowerbound'); L = options.lowerbound; end 41 | if isfield(options,'SignP'); SignP = options.SignP; end 42 | if isfield(options,'fV'); fV = options.fV; end 43 | if isfield(options,'nonnegative'); nonnegative = options.nonnegative; end 44 | 45 | fprintf('\n'); 46 | fprintf('\n============================================================================================================'); 47 | fprintf('\n************************************************************************************************************'); 48 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 49 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 50 | fprintf('\n************************************************************************************************************'); 51 | fprintf('\n============================================================================================================'); 52 | fprintf('\n************************************************************************************************************'); 53 | fprintf('\n* Reference *'); 54 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 55 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 56 | fprintf('\n************************************************************************************************************'); 57 | fprintf('\n============================================================================================================'); 58 | fprintf('\n'); 59 | %% problem property 60 | existA = ~isempty(A); 61 | tstart = clock; 62 | n = blk{1,2}; 63 | Zero = sparse(n,n); 64 | Fnorm = @(X) mexFnorm(X); 65 | %% AEmap, AETmap, AImap, AITmap, Qmap 66 | if existA 67 | if isstruct(A) 68 | if isfield(A,'At'); At = A.At; end 69 | if isfield(A,'Amap'); Amap0 = A.Amap; end 70 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 71 | else 72 | At = A; 73 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 74 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 75 | end 76 | else 77 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 78 | end 79 | %% 80 | %% initial scaling 81 | %% 82 | Atorg = At; borg = b; Lorg = L; Uorg = U; fVorg = fV; 83 | Corg = C; Horg = H; 84 | normHorg = Fnorm(Horg); 85 | normCorg = 1 + Fnorm(Corg); 86 | normborg = 1 + norm(borg); 87 | %% 88 | if ~exist('X','var'); X = Zero; end 89 | if ~exist('yE','var'); yE = zeros(length(b),1); end 90 | if ~exist('S','var'); S = Zero; end 91 | if ~existA; yE = []; b = []; end 92 | if ~exist('Xi','var'); Xi = Zero; end 93 | if ~exist('Z','var'); Z = Zero; end 94 | %% 95 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 96 | sGS.op.stoptol = 6e-5; % tol of initial stage 97 | sGS.op.maxiter = 250; % maxiter of initial stage 98 | sGS.op.lowerbound = Lorg; sGS.op.SignP = SignP; 99 | sGS.op.upperbound = Uorg; sGS.op.fV = fVorg; 100 | sGS.op.nonnegative = nonnegative; 101 | sGS.op.phase2 = 1; 102 | fprintf('\n********************************************************'); 103 | fprintf('\n QSDPNAL Phase I '); 104 | fprintf('\n********************************************************'); 105 | [obj,Z,Xi,S,yE,X,runhist_sGS,info_sGS] = startfun(blk,Horg,A,borg,Corg,sGS.op,X,Z,Xi,S,yE); 106 | fprintf('\n -------------------------------------------------------'); 107 | sGS.Xi0 = Xi; sGS.S0 = S; sGS.Z0 = Z; 108 | sGS.yE0= yE; sGS.X0=X; 109 | nE = info_sGS.nE; nXi = info_sGS.nXi; 110 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 111 | sigma = info_sGS.sigma; 112 | normA = info_sGS.normA; DA = info_sGS.DA; 113 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 114 | b = info_sGS.b; 115 | C = info_sGS.C; 116 | sGS.iter = sGS.iter + info_sGS.iter; 117 | sGS.time = sGS.time + info_sGS.totaltime; 118 | %% 119 | X = X/bscale; yE = (normA.*yE)/Cscale; 120 | S = S/Cscale; HXi = Horg.*Xi/Cscale; 121 | Xi = Xi/sqrt(bscale*Cscale); Z=Z/Cscale; 122 | L = L/bscale; U = U/bscale; fV = fV/bscale; 123 | H = sqrt(bscale/Cscale)*Horg; 124 | objscale = bscale*Cscale; 125 | At = At*DA; 126 | %%------------------------------------------------------------------- 127 | %% end of intial stage 128 | %%------------------------------------------------------------------- 129 | %% start QSDPNAL-Phase II 130 | parmain.existA = existA; 131 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 132 | parmain.nE = nE; parmain.n = n; 133 | parmain.normA = normA; parmain.DA = DA; 134 | parmain.HXi = HXi; 135 | parmain.normHorg = normHorg; 136 | parmain.normborg = normborg; 137 | parmain.normCorg = normCorg; 138 | parmain.use_proximal = use_proximal; 139 | 140 | parmain.nonnegative = nonnegative; parmain.L = L; parmain.U = U; 141 | parmain.SignP = SignP; parmain.fV = fV; 142 | 143 | parmain.sigma = sigma; 144 | parmain.tstart= tstart; 145 | parmain.maxiter = maxiter; 146 | parmain.stoptol = stoptol; 147 | parmain.printyes = printyes; 148 | parmain.sGS = sGS; 149 | parmain.restart = restart; 150 | 151 | parmain.Lorg = Lorg; parmain.Uorg = Uorg; parmain.fVorg = fVorg; 152 | parmain.borg = borg; parmain.Corg = Corg; 153 | parmain.Horg = Horg; parmain.A = A; 154 | parmain.startfun = startfun; 155 | 156 | parmain.info_sGS = info_sGS; 157 | parmain.obj = obj; 158 | 159 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; 160 | % main solver QSDPNAL-Phase II with restart technique 161 | [X,Z,yE,S,Xi,info_main,runhist] = ... 162 | nal_NCMPmain(blk,H,At,Ainput,b,C,parmain,X,Z,yE,S,Xi); 163 | iter = info_main.iter; 164 | msg = info_main.msg; 165 | bscale = info_main.bscale; 166 | Cscale = info_main.Cscale; 167 | Ztmp = info_main.Ztmp; 168 | sGS = info_main.sGS; 169 | %%----------------------------------------------------------------- 170 | %% recover orignal variables 171 | %%----------------------------------------------------------------- 172 | if (iter == maxiter) 173 | msg = ' maximum iteration reached'; 174 | info.termcode = 3; 175 | end 176 | X = X*bscale; normX = norm(X,'fro'); 177 | HX = Horg.*X; 178 | yE = Cscale*(DA*yE); 179 | Z = Cscale*Z; normZ = norm(Z,'fro'); Ztmp = Ztmp*bscale; 180 | S = Cscale*S; normS = norm(S,'fro'); 181 | Xi = Xi*sqrt(bscale*Cscale); 182 | HXi = Horg.*Xi; 183 | AX = Amap0(X); AtyE = ATmap0(yE); 184 | if existA; bTyE = borg'*yE; end 185 | primobj = 0.5*Fnorm(HX)^2 + sum(sum(Corg.*X)); 186 | dualobj = bTyE + sum(sum(Z.*Ztmp)) - 0.5*Fnorm(Xi)^2; 187 | obj = [primobj,dualobj]; 188 | etaQ = Fnorm(Xi + Horg.*X)^2/(1+normHorg^2); 189 | if (true) 190 | etaSp = compnormXn(X) /(1+normX); 191 | etaSc = full(abs(sum(sum(X.*S)))) /(1+normX +normS); 192 | etaS = max(etaSp,etaSc); 193 | projPX = proj_LU_new(X,nonnegative,SignP,Lorg,Uorg,fVorg); 194 | etaZp = Fnorm(X-projPX)/(1 + normX); 195 | ZtmX = Ztmp - X; 196 | normZtmX = norm(ZtmX,'fro'); 197 | trZtmX = full(abs(sum(sum(ZtmX.*Z)))); 198 | etaZc = trZtmX/(1 + normZ + normZtmX); 199 | etaZ = max(etaZp,etaZc); 200 | end 201 | etab = norm(AX-borg)/normborg; 202 | primfeasorg = etab; 203 | dualfeasorg = norm(Z + S+AtyE+HXi-Corg,'fro')/normCorg; 204 | ttime = etime(clock,tstart); 205 | runhist.nE = nE; 206 | runhist.ns = n; 207 | runhist.iter = iter; 208 | runhist.totaltime = ttime; 209 | runhist.primobjorg = primobj; 210 | runhist.dualobjorg = dualobj; 211 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 212 | runhist.primfeasorg(iter) = primfeasorg; 213 | runhist.dualfeasorg(iter) = dualfeasorg; 214 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS]); 215 | info.nE = nE; 216 | info.ns = n; 217 | info.iter = iter; 218 | info.totaltime = ttime; 219 | info.primobjorg = primobj; 220 | info.dualobjorg = dualobj; 221 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 222 | info.etaZ = etaZ; 223 | info.etaS = etaS; 224 | info.etab = etab; 225 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 226 | info.etaQ = etaQ; 227 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 228 | info.minX = min(min(X)); 229 | info.maxX = max(max(X)); 230 | info.sGS_iter = sGS.iter; 231 | info.sGS_time = sGS.time; 232 | info.totalNT = sum(runhist.innerNT); 233 | info.totalCG = sum(runhist.innerCG); 234 | if (printminoryes) 235 | if ~isempty(msg); fprintf('\n %s',msg); end 236 | fprintf('\n--------------------------------------------------------------'); 237 | fprintf('------------------'); 238 | fprintf('\n number iter = %2.0d',iter); 239 | fprintf('\n time = %3.2f',ttime); 240 | %fprintf('\n time per iter = %5.4f',ttime/iter); 241 | fprintf('\n time of Phase I = %3.2f', sGS.time); 242 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 243 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 244 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 245 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 246 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 247 | fprintf('\n etaQ = %3.2e', etaQ); fprintf(' etaS = %3.2e', etaS); 248 | fprintf('\n etab = %3.2e', etab); fprintf(' etaZ = %3.2e', etaZ); 249 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 250 | info.minX,info.maxX); 251 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 252 | fprintf('\n--------------------------------------------------------------'); 253 | fprintf('------------------\n'); 254 | end 255 | %%********************************************************************** 256 | function normXn = compnormXn(X) 257 | 258 | d = eig(full(X)); 259 | normXn = norm(d(d<0)); 260 | %%********************************************************************** 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /QSDPNAL_main/NAL/qsdpnal_QAP.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% QSDPNAL: Phase II 3 | %% An inexact semismooth Netwon based ALM for solving the following QSDP problem 4 | %% QSDP-QAP problem 5 | %% D'): max -(\delta_{\cP}^*(-Z) + 1/2 - - ) 6 | %% s.t. Z + S - QW + AE^*yE + B^* yI = C, 7 | %% alpha(u - y_I) = 0, S \in PSD, u >= 0, W \in Range(Q) 8 | %% 9 | %% P): min 1/2 + , s.t., AE X = bE, B X >= d, X\in \cP 10 | %% P'): min 1/2 + , s.t., AE X = bE, B X -alpha v = b_I, X\in \cP, v>=0. 11 | %%************************************************************************* 12 | %% QSDPNAL: 13 | %% Copyright (c) 2015 by 14 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | %%************************************************************************* 16 | 17 | function [obj,Z,W,QW,S,yE,yI,X,runhist,info] = qsdpnal_QAP(blk,Q,A,b,C,B,d,options) 18 | %% General options 19 | rng('default'); 20 | maxiter = 5000; 21 | stoptol = 1e-6; 22 | printyes = 1; 23 | printminoryes=1; 24 | startfun = @SCB_qsdp; % Algorithm QSDPNAL-Phase I for initial point 25 | sigma0 = 1; 26 | sGS.iter = 0; 27 | sGS.time = 0; 28 | use_proximal = 1; 29 | restart = 1; 30 | %% information for \cP 31 | nonnegative = 0; L = []; U = []; SignP = []; fV = []; 32 | if isfield(options,'upperbound'); U = options.upperbound; end 33 | if isfield(options,'lowerbound'); L = options.lowerbound; end 34 | if isfield(options,'SignP'); SignP = options.SignP; end 35 | if isfield(options,'fV'); fV = options.fV; end 36 | if isfield(options,'nonnegative'); nonnegative = options.nonnegative; end 37 | 38 | fprintf('\n'); 39 | fprintf('\n============================================================================================================'); 40 | fprintf('\n************************************************************************************************************'); 41 | fprintf('\n* QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming *'); 42 | fprintf('\n* Authors: Xudong Li, Defeng Sun, and Kim-Chuan Toh *'); 43 | fprintf('\n************************************************************************************************************'); 44 | fprintf('\n============================================================================================================'); 45 | fprintf('\n************************************************************************************************************'); 46 | fprintf('\n* Reference *'); 47 | fprintf('\n* Xudong Li, Defeng Sun, and Kim-Chuan Toh, QSDPNAL: A two-phase augmented Lagrangian method for convex *'); 48 | fprintf('\n* quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. *'); 49 | fprintf('\n************************************************************************************************************'); 50 | fprintf('\n============================================================================================================'); 51 | fprintf('\n'); 52 | 53 | %% problem property 54 | existQ = ~isempty(Q); 55 | existA = ~isempty(A); 56 | existB = ~isempty(B); 57 | tstart = clock; 58 | n = blk{1,2}; 59 | nbar = n*(n+1)/2; 60 | Zero = sparse(n,n); 61 | Fnorm = @(X) mexFnorm(X); 62 | if nonnegative || ~isempty(L) || ~isempty(U) || ~isempty(fV) 63 | existZ = 1; 64 | else 65 | existZ = 0; 66 | end 67 | Qsolver = 'pcg'; %solve linear system corresponding to W by PCG 68 | %% AEmap, AETmap, AImap, AITmap, Qmap 69 | if existA 70 | if isstruct(A) 71 | if isfield(A,'At'); At = A.At; end 72 | if isfield(A,'Amap'); Amap0 = A.Amap; end 73 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 74 | else 75 | At = A; 76 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 77 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 78 | end 79 | else 80 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 81 | end 82 | if existB 83 | if isstruct(B) 84 | if isfield(B,'Bt'); Bt = B.Bt; end 85 | if isfield(B,'Bmap'); Bmap0 = B.Bmap; end 86 | if isfield(B,'BTmap'); BTmap0 = B.BTmap; end 87 | else 88 | Bt = B; 89 | Bmap0 = @(X) sdpnalAXfun(blk,Bt,X); 90 | BTmap0 = @(y) sdpnalAtyfun(blk,Bt,y); 91 | end 92 | else 93 | Bmap0 = @(X) []; BTmap0 = @(y) Zero; 94 | end 95 | if existQ 96 | Qmap0 = @(X) feval(Q.QXfun,X); 97 | else 98 | Qmap0 = @(X) sparse(n,n); 99 | end 100 | %% 101 | %% initial scaling 102 | %% 103 | Atorg = At; borg = b; 104 | Corg = C; Lorg = L; Uorg = U; fVorg = fV; 105 | normCorg = 1 + Fnorm(Corg); 106 | normborg = 1 + norm(borg); 107 | if existB; 108 | Btorg = Bt; dorg = d; 109 | normdorg = 1 + norm(dorg); 110 | else 111 | dorg = []; d = []; 112 | end 113 | %% 114 | %% generate initial point through QSDPNAL-Phase I (SCB_qsdp) 115 | sGS.iter = 0; 116 | sGS.time = 0; 117 | sGS.op.stoptol = stoptol; 118 | sGS.op.maxiter = 50000; 119 | sGS.op.lowerbound = Lorg; sGS.op.SignP = SignP; 120 | sGS.op.upperbound = Uorg; sGS.op.fV = fVorg; 121 | sGS.op.nonnegative = nonnegative; 122 | sGS.op.stopoption = 2; 123 | fprintf('\n********************************************************'); 124 | fprintf('\n QSDPNAL Phase I '); 125 | fprintf('\n********************************************************'); 126 | [obj,Z,W,QW,S,yE,yI,X,runhist_sGS,info_sGS] = startfun(blk,Q,A,borg,Corg,B,dorg,sGS.op); 127 | fprintf('\n -------------------------------------------------------'); 128 | sGS.Z0 = Z; sGS.W0 = W; sGS.QW0 = QW; sGS.S0 = S; 129 | sGS.yE0= yE; sGS.yI0=yI; sGS.X0=X; 130 | nE = info_sGS.nE; nI = info_sGS.nI; 131 | bscale = info_sGS.bscale; Cscale = info_sGS.Cscale; 132 | sigma = info_sGS.sigma; 133 | sGS.iter = sGS.iter + info_sGS.iter; 134 | sGS.time = sGS.time + info_sGS.totaltime; 135 | if existQ; 136 | Qmap = info_sGS.Qmap; parQ = info_sGS.parQ; 137 | normQorg = info_sGS.normQorg; 138 | else 139 | Qmap = Qmap0; 140 | end 141 | normA = info_sGS.normA; DA = info_sGS.DA; 142 | Amap = info_sGS.Amap; ATmap = info_sGS.ATmap; 143 | Bmap = info_sGS.Bmap; BTmap = info_sGS.BTmap; 144 | b = info_sGS.b; 145 | C = info_sGS.C; 146 | if existB; 147 | normB = info_sGS.normB; DB = info_sGS.DB; 148 | d = info_sGS.d; 149 | u = info_sGS.u; v = info_sGS.v; 150 | alpha = 1*info_sGS.alpha; 151 | yI = (normB.*yI)/Cscale; 152 | Bt = Bt*DB; 153 | end 154 | At = At*DA; 155 | %% 156 | X = X/bscale; yE = (normA.*yE)/Cscale; 157 | Z = Z/Cscale; S = S/Cscale; 158 | QW = QW/Cscale; W = W/bscale; 159 | objscale = bscale*Cscale; 160 | %%------------------------------------------------------------------- 161 | %% end of intial stage 162 | %%------------------------------------------------------------------- 163 | %% start QSDPNAL-Phase II 164 | parmain.existQ = existQ; parmain.existB = existB; parmain.existA = existA; 165 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 166 | 167 | parmain.Qsolver = Qsolver; 168 | parmain.DA = DA; 169 | parmain.nE = nE; parmain.nI = nI; parmain.n = n; 170 | 171 | parmain.nonnegative = nonnegative; parmain.L = L; parmain.U = U; 172 | parmain.SignP = SignP; parmain.fV = fV; 173 | 174 | parmain.normA = normA; 175 | parmain.normborg = normborg; 176 | parmain.normCorg = normCorg; 177 | parmain.normQorg = normQorg; 178 | 179 | parmain.sigma = sigma; 180 | 181 | parmain.tstart= tstart; 182 | parmain.maxiter = maxiter; 183 | parmain.stoptol = stoptol; 184 | parmain.printyes = printyes; 185 | parmain.sGS = sGS; 186 | parmain.use_proximal = use_proximal; 187 | parmain.restart = restart; 188 | 189 | if existB 190 | parmain.alpha = alpha; 191 | parmain.normB = normB; 192 | parmain.Bt = Bt; 193 | parmain.normB = normB; parmain.DB = DB; 194 | parmain.d = d; 195 | parmain.u = u; parmain.v = v; 196 | parmain.alpha = alpha; 197 | end 198 | 199 | parmain.info_sGS = info_sGS; 200 | parmain.obj = obj; 201 | 202 | parmain.parQ = parQ; 203 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.At = At; 204 | Binput.Bmap = Bmap; Binput.BTmap = BTmap; 205 | 206 | parmain.Lorg = Lorg; parmain.Uorg = Uorg; parmain.fVorg = fVorg; 207 | parmain.borg = borg; parmain.Corg = Corg; parmain.dorg = dorg; 208 | parmain.startfun = startfun; 209 | 210 | % main solver QSDPNAL-Phase II with restart technique 211 | [Z,Wvec,QW,S,yE,yI,X,info_main,runhist] = ... 212 | nal_qsdpQAPmain(blk,Q,Qmap,A,Ainput,B,Binput,b,C,d,parmain,Z,W,QW,S,yE,yI,X); 213 | iter = info_main.iter; 214 | msg = info_main.msg; 215 | Ztmp = info_main.Ztmp; 216 | bscale = info_main.bscale; 217 | Cscale = info_main.Cscale; 218 | sGS = info_main.sGS; 219 | %%----------------------------------------------------------------- 220 | %% recover orignal variables 221 | %%----------------------------------------------------------------- 222 | if (iter == maxiter) 223 | msg = ' maximum iteration reached'; 224 | info.termcode = 3; 225 | end 226 | X = X*bscale; normX = norm(X,'fro'); 227 | QX = Qmap0(X); 228 | yE = Cscale*(DA*yE); 229 | Z = Cscale*Z; normZ = norm(Z,'fro'); Ztmp = Ztmp*bscale; 230 | S = Cscale*S; normS = norm(S,'fro'); 231 | QW = Cscale*QW; Wvec = bscale*Wvec; 232 | if existQ; W = smat(blk,Wvec); else W = [];end; 233 | if existB; 234 | yI = Cscale*(DB*yI); 235 | BtyI = BTmap0(yI); 236 | normyI = norm(yI); 237 | RpI = dorg - Bmap0(X); 238 | dTyI = dorg'*yI; 239 | else 240 | dTyI = 0; BtyI = Zero; 241 | end 242 | AX = Amap0(X); AtyE = ATmap0(yE); 243 | if existA; bTyE = borg'*yE; end 244 | primobj = 0.5*sum(sum(X.*QX)) + sum(sum(Corg.*X)); 245 | if existQ; WQW = sum(sum(W.*QW)); else WQW = 0; end 246 | dualobj = bTyE + sum(sum(Z.*Ztmp)) - 0.5*WQW + dTyI; 247 | obj = [primobj,dualobj]; 248 | if ~isempty(L) 249 | minLX = min(min(X(SignP.L == 1))); 250 | end 251 | if ~isempty(U) 252 | maxUX = max(max(X(SignP.U == 3))); 253 | end 254 | if existQ 255 | etaQ = Fnorm(QX - QW)/normQorg; 256 | else 257 | etaQ = 0; 258 | end 259 | if (true) 260 | etaSp = compnormXn(X) /(1+normX); 261 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 262 | etaS = max(etaSp,etaSc); 263 | projPX = proj_LU_new(X,nonnegative,SignP,Lorg,Uorg,fVorg); 264 | etaZp = Fnorm(X-projPX)/(1 + normX); 265 | ZtmX = Ztmp - X; 266 | normZtmX = norm(ZtmX,'fro'); 267 | trZtmX = full(abs(sum(sum(ZtmX.*Z)))); 268 | etaZc = trZtmX/(1 + normZ + normZtmX); 269 | etaZ = max(etaZp,etaZc); 270 | if existB 271 | etayId = norm(min(yI,0))/(1+normyI); 272 | normRpI = norm(RpI); 273 | etayIp = norm(max(RpI,0))/(1+normRpI); 274 | etayIc = full(abs(yI'*RpI)/(1+normyI+normRpI)); 275 | etayI = max([etayId,etayIp,etayIc]); 276 | else 277 | etayI = 0; etayId = 0; etayIp = 0; etayIc = 0; 278 | end 279 | end 280 | primfeasorg = max(norm(AX-borg)/normborg,etayIp); 281 | dualfeasorg = max(norm(Z+S+AtyE+BtyI-QW-Corg,'fro')/normCorg,etayId); 282 | ttime = etime(clock,tstart); 283 | runhist.nE = nE; 284 | runhist.ns = n; 285 | runhist.nI = nI; 286 | runhist.iter = iter; 287 | runhist.totaltime = ttime; 288 | runhist.primobjorg = primobj; 289 | runhist.dualobjorg = dualobj; 290 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 291 | runhist.primfeasorg(iter) = primfeasorg; 292 | runhist.dualfeasorg(iter) = dualfeasorg; 293 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaZ,etayIc]); 294 | info.nE = nE; 295 | info.nI = nI; 296 | info.ns = n; 297 | info.iter = iter; 298 | info.totaltime = ttime; 299 | info.primobjorg = primobj; 300 | info.dualobjorg = dualobj; 301 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 302 | info.relerrS = etaS; 303 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 304 | info.relerrZ = etaZ; 305 | info.relerrQ = etaQ; 306 | info.etayI = etayI; 307 | info.etayI1 = etayId; 308 | info.etayI2 = etayIp; 309 | info.etayI3 = etayIc; 310 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ,etaZ,etayIc]); 311 | info.minX = min(min(X)); 312 | info.maxX = max(max(X)); 313 | info.sGS_iter = sGS.iter; 314 | info.sGS_time = sGS.time; 315 | info.totalNT = sum(runhist.innerNT); 316 | info.totalCG = sum(runhist.innerCG); 317 | if (printminoryes) 318 | if ~isempty(msg); fprintf('\n %s',msg); end 319 | fprintf('\n--------------------------------------------------------------'); 320 | fprintf('------------------'); 321 | fprintf('\n number iter = %2.0d',iter); 322 | fprintf('\n time = %3.2f',ttime); 323 | %fprintf('\n time per iter = %5.4f',ttime/iter); 324 | fprintf('\n time of Phase I = %3.2f', sGS.time); 325 | fprintf('\n iter of Phase I = %2.0d', sGS.iter); 326 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 327 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 328 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 329 | primfeasorg,dualfeasorg,info.relgaporg); 330 | fprintf('\n etaQ = %3.2e', etaQ); 331 | fprintf('\n etaZ = %3.2e', etaZ); 332 | fprintf('\n etaS = %3.2e', etaS); 333 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 334 | info.minX,info.maxX); 335 | fprintf('\n total innerNT steps = %3d, total innerCG = %3d', info.totalNT, info.totalCG); 336 | if ~isempty(L) 337 | fprintf('\n Lower bound for bounded part = %3.2e',minLX); 338 | end 339 | if ~isempty(U) 340 | fprintf('\n Upper bound for bounded part = %3.2e',maxUX); 341 | end 342 | fprintf('\n--------------------------------------------------------------'); 343 | fprintf('------------------\n'); 344 | end 345 | %%********************************************************************** 346 | function normXn = compnormXn(X) 347 | 348 | d = eig(full(X)); 349 | normXn = norm(d(d<0)); 350 | %%********************************************************************** 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | -------------------------------------------------------------------------------- /QSDPNAL_main/SCB/SCB_LS.m: -------------------------------------------------------------------------------- 1 | %%************************************************************************* 2 | %% QSDPNAL: Phase I 3 | %% An inexact SCB based semi-Proximal ADMM for solving Least Squres problems: 4 | %% (P) min {1/2||H(X)||_F^2 + | A(X)=b, X \in K} 5 | %% where K = psd cone 6 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H(X) = Y, X\in K} 7 | %% 8 | %% (D') max -1/2 ||Xi||^2 + 9 | %% s.t. H*(Xi) + S + A*y = C, 10 | %% S \in PSD. 11 | %%************************************************************************* 12 | %% QSDPNAL: 13 | %% Copyright (c) 2015 by 14 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | %%************************************************************************* 16 | 17 | function [obj,xi,S,yE,X,runhist,info] = SCB_LS(blk,H,A,b,C,options,X,xi,S,yE) 18 | %% For inexact criteria 19 | %rng('default'); 20 | rhsconst =0.09; 21 | feasiconst=0.9; 22 | tolconst =100; 23 | %% General options 24 | maxiter = 5000; 25 | stoptol = 1e-6; 26 | printyes = 1; 27 | printminoryes=1; 28 | scale_data = 1; 29 | rescale = 1; 30 | gamma = 1.618; %step length in SCB ADMM 31 | sigma = 1; 32 | gamma_reset_start = 200; 33 | sGS = 1; 34 | sig_fix = 0; 35 | stopoption = 0; 36 | phase2 = 0; 37 | 38 | % options for linear system solvers 39 | % for AEsolver: `pcg' and `sparse_chol' 40 | % for Hsovler only `pcg' 41 | AEsolver = 'sparse_chol';%'pcg';% 42 | Hsolver = 'pcg'; 43 | 44 | % options from users 45 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 46 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 47 | if isfield(options,'printyes'); printyes = options.printyes; end 48 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 49 | if isfield(options,'scale_data'); scale_data = options.scale_data; end 50 | if isfield(options,'rescale'); rescale = options.rescale; end 51 | if isfield(options,'sigma'); sigma = options.sigma; end 52 | if isfield(options,'gamma'); gamma = options.gamma; end 53 | if isfield(options,'stopoption'); stopoption = options.stopoption; end 54 | if isfield(options,'phase2'); phase2 = options.phase2; end 55 | %% solvers for AE 56 | if isfield(options,'AEsolver'); AEsolver = options.AEsolver; end 57 | if isfield(options,'sGS'); sGS = options.sGS; end 58 | %% problem property 59 | existA = ~isempty(A); 60 | existH = ~isempty(H); 61 | tstart = clock; 62 | n = blk{1,2}; 63 | nbar = n*(n+1)/2; 64 | Zero = sparse(n,n); 65 | Fnorm = @(X) mexFnorm(X); 66 | %% AEmap, AETmap, Qmap 67 | if existA 68 | if isstruct(A) 69 | if isfield(A,'At'); At = A.At; end 70 | if isfield(A,'Amap'); Amap0 = A.Amap; end 71 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 72 | else 73 | At = A; 74 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 75 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 76 | end 77 | else 78 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 79 | end 80 | if existH 81 | if isstruct(H) 82 | if isfield(H,'Ht'); Ht = H.Ht; end 83 | if isfield(H,'Hmap'); Hmap0 = H.Hmap; end 84 | if isfield(H,'HTmap'); HTmap0 = H.HTmap; end 85 | else 86 | Ht = H; 87 | Hmap0 = @(X) sdpnalAXfun(blk,Ht,X); 88 | HTmap0 = @(y) sdpnalAtyfun(blk,Ht,y); 89 | if false 90 | HHTmap0 = @(y) Hmap0(HTmap0(y)); 91 | eigsopt.issym = 1; 92 | sss = eigs(HHTmap0,size(Ht,2),1,'LM',eigsopt); 93 | fprintf('\n largest eig = %3.2e', sss); 94 | end 95 | end 96 | else 97 | Hmap0 = @(X) []; HTmap0 = @(y) Zero; 98 | end 99 | %%% 100 | if ~exist('X','var'); X = Zero; end 101 | if ~exist('yE','var'); yE = zeros(length(b),1); end 102 | if ~exist('S','var'); S = Zero; end 103 | if ~existA; yE = []; b = []; end 104 | if ~exist('xi','var'); xi = zeros(size(Ht,2),1); end 105 | %% 106 | %% initial scaling 107 | %% 108 | Atorg = At; borg = b; Htorg = Ht; 109 | Corg = C; 110 | normCorg = 1 + Fnorm(Corg); 111 | normborg = 1 + norm(borg); 112 | eigsopt.issym = 1; 113 | if existA 114 | nE = length(b); 115 | normA = sum(At.*At)'; 116 | normA = max(1,sqrt(normA)); 117 | DA = spdiags(1./normA,0,nE,nE); 118 | At = At*DA; 119 | b = DA*b; 120 | normAt = Fnorm(At); 121 | Amap = @(X) Amap0(X)./normA; 122 | ATmap = @(y) ATmap0(y./normA); 123 | AATmap = @(y) Amap(ATmap(y)); 124 | if strcmp(AEsolver,'sparse_chol') 125 | [LAAt,AAt] = mycholAAt(At,nE); 126 | dd = diag(AAt); 127 | if (Fnorm(AAt-speye(nE)) < 1e-12) 128 | if printyes; fprintf('\n AEAEt is identity '); end %% For BIQ, FAP and Theta(+) problems 129 | LAAt.isidentity = true; 130 | elseif (Fnorm(AAt-spdiags(dd,0,nE,nE)) < 1e-15*norm(dd)) 131 | fprintf('\n AAt is diagonal '); 132 | LAAt.isidentity = false; 133 | else 134 | LAAt.isidentity = false; 135 | end 136 | AEsolve = @(rhs) mylinsysolve(LAAt,rhs); 137 | if printyes; fprintf('\n AEAEt solved by chol decompostion'); end 138 | elseif strcmp(AEsolver,'pcg') 139 | AAt = At'*At; 140 | rr = min(6,nE); 141 | [VA,dA,flagA] = eigs(AATmap,nE,rr,'LA',eigsopt); 142 | dA = diag(dA); rr = sum(dA>0); 143 | pcgA = min(3,rr); 144 | parA.V = VA(:,1:pcgA); parA.Vt = parA.V'; 145 | parA.d = dA(1:pcgA); 146 | parA.precond = 2; 147 | if printyes; fprintf('\n using pcg to solve AEAEt'); end 148 | end 149 | else 150 | Amap = @(X) []; ATmap = @(y) Zero; 151 | normA = []; DA = []; nE = 0; 152 | end 153 | if (scale_data == 1) 154 | bscale = max(1,norm(b)); 155 | Cscale = max(1,Fnorm(C)); 156 | elseif scale_data == 0 157 | bscale = 1; 158 | Cscale = 1; 159 | end 160 | b = b/bscale; C = C/Cscale; 161 | X = X/bscale; 162 | yE = (normA.*yE)/Cscale; 163 | S = S/Cscale; 164 | objscale = bscale*Cscale; 165 | xi = xi/sqrt(objscale); 166 | 167 | if printyes 168 | fprintf('\n *******************************************************'); 169 | fprintf('******************************************'); 170 | fprintf('\n \t\t SCB_LS with beginning gamma = %6.3f', gamma); 171 | fprintf('\n ******************************************************'); 172 | fprintf('*******************************************\n'); 173 | if printminoryes 174 | fprintf('\n n = %3.0f, mE = %3.0f',n, nE); 175 | fprintf('\n scale_data = %2.0f', scale_data); 176 | fprintf('\n bscale = %3.2e, cscale = %3.2e', bscale, Cscale); 177 | fprintf('\n ---------------------------------------------------'); 178 | end 179 | fprintf('\n iter| pinforg dinforg relgaporg| pobj dobj |'); 180 | fprintf(' time | sigma |rankS, minspeed|gamma|'); 181 | end 182 | %%----------------------------------------------------------------- 183 | %% start main solver 184 | % parameters for main solver 185 | parmain.existH = existH; parmain.existA = existA; 186 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 187 | parmain.AEsolver = AEsolver; parmain.Hsolver = Hsolver; 188 | parmain.DA = DA; 189 | parmain.nE = nE; parmain.n = n; 190 | parmain.normA = normA; 191 | parmain.normAt = normAt; 192 | parmain.Htorg = Htorg; 193 | parmain.normborg = normborg; 194 | parmain.normCorg = normCorg; 195 | 196 | parmain.sigma = sigma; 197 | parmain.gamma = gamma; 198 | parmain.tstart= tstart; 199 | parmain.maxiter = maxiter; 200 | parmain.rescale = rescale; 201 | parmain.feasiconst = feasiconst; 202 | parmain.rhsconst = rhsconst; 203 | parmain.stoptol = stoptol; 204 | parmain.printyes = printyes; 205 | parmain.sGS = sGS; 206 | parmain.gamma_reset_start = gamma_reset_start; 207 | parmain.sig_fix = sig_fix; 208 | parmain.stopoption = stopoption; 209 | parmain.tolconst = tolconst; 210 | 211 | if strcmp(AEsolver,'pcg'); 212 | parmain.parA = parA; 213 | elseif strcmp(AEsolver,'sparse_chol'); 214 | parmain.AEsolve = AEsolve; 215 | end 216 | 217 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.AATmap = AATmap; 218 | 219 | % main file of SCB ADMM for solving Least Squre QSDP problems 220 | [X,yE,S,xi,info_main,runhist] = ... 221 | SCB_LSmain(Hmap0,HTmap0,Ainput,b,C,parmain,X,yE,S,xi); 222 | 223 | % information 224 | iter = info_main.iter; 225 | msg = info_main.msg; 226 | bscale = info_main.bscale; 227 | Cscale = info_main.Cscale; 228 | breakyes = info_main.breakyes; 229 | iterProj = info_main.iterProj; 230 | repeatyE = info_main.repeatyE; 231 | sigma = info_main.sigma; 232 | if phase2 233 | b = info_main.b; normb = info_main.normb; 234 | C = info_main.C; normC = info_main.normC; 235 | if existH&&strcmp(Hsolver,'pcg'); HHtxi = info_main.HHtxi; end 236 | end 237 | %%----------------------------------------------------------------- 238 | %% recover orignal variables 239 | %%----------------------------------------------------------------- 240 | if (iter == maxiter) 241 | msg = ' maximum iteration reached'; 242 | info.termcode = 3; 243 | end 244 | X = X*bscale; normX = norm(X,'fro'); 245 | HX = Hmap0(X); 246 | yE = Cscale*(DA*yE); 247 | S = Cscale*S; normS = norm(S,'fro'); 248 | xi = sqrt(bscale*Cscale)*xi; 249 | Htxi = HTmap0(xi); 250 | if existA; bTyE = borg'*yE; end 251 | AX = Amap0(X); AtyE = ATmap0(yE); 252 | primobj = 0.5*norm(HX)^2 + sum(sum(Corg.*X)); 253 | dualobj = bTyE - 0.5*norm(xi)^2; 254 | obj = [primobj,dualobj]; 255 | etaQ = Fnorm(xi+HX)/(1+Fnorm(Htorg)); 256 | if (true) 257 | etaSp = compnormXn(X) /(1+normX); 258 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 259 | etaS = max(etaSp,etaSc); 260 | end 261 | etab = norm(AX-borg)/normborg; 262 | primfeasorg = max(etab); 263 | dualfeasorg = max(norm(Htxi+S+AtyE-Corg,'fro')/normCorg); 264 | ttime = etime(clock,tstart); 265 | runhist.nE = nE; 266 | runhist.ns = n; 267 | runhist.iter = iter; 268 | runhist.totaltime = ttime; 269 | runhist.primobjorg = primobj; 270 | runhist.dualobjorg = dualobj; 271 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 272 | runhist.primfeasorg(iter) = primfeasorg; 273 | runhist.dualfeasorg(iter) = dualfeasorg; 274 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 275 | info.nE = nE; 276 | info.ns = n; 277 | info.iter = iter; 278 | info.totaltime = ttime; 279 | info.primobjorg = primobj; 280 | info.dualobjorg = dualobj; 281 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 282 | info.etaS = etaS; 283 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 284 | info.etaQ = etaQ; 285 | info.etab = etab; 286 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 287 | info.minX = min(min(X)); 288 | info.maxX = max(max(X)); 289 | info.psqmrA1 = sum(runhist.psqmrA1); 290 | info.psqmrA2 = sum(runhist.psqmrA2); 291 | info.breakyes = breakyes; 292 | %% added for Phase II 293 | if phase2 294 | info.Amap = Amap; info.ATmap = ATmap; 295 | info.bscale = bscale; info.Cscale = Cscale; 296 | info.sigma = sigma; 297 | info.AAt = AAt; 298 | if exist('At','var'); info.At = At; end 299 | info.normA = normA; info.DA = DA; info.normAt = normAt; 300 | info.b = b; info.normb = normb; info.C = C; info.normC = normC; 301 | if existH&&strcmp(Hsolver,'pcg'); info.HHtxi = HHtxi; end 302 | end 303 | if (printminoryes) 304 | if ~isempty(msg); fprintf('\n %s',msg); end 305 | fprintf('\n--------------------------------------------------------------'); 306 | fprintf('------------------'); 307 | fprintf('\n number iter = %2.0d',iter); 308 | fprintf('\n number of iterProj = %2.0f',iterProj); 309 | fprintf('\n number iter = %2.0d \t repeaty= %d ',... 310 | iter,repeatyE); 311 | if existA && strcmp(AEsolver,'pcg') 312 | fprintf('\n number of PSQMRiterA for 1st system = %2.0f',info.psqmrA1); 313 | fprintf('\n number of PSQMRiterA for 2nd system = %2.0f',info.psqmrA2); 314 | end 315 | fprintf('\n time = %3.2f',ttime); 316 | fprintf('\n time per iter = %5.4f',ttime/iter); 317 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 318 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 319 | fprintf('\n primfeas = %3.2e, dualfeas = %3.2e, relgap = %3.2e',... 320 | runhist.primfeas(end),runhist.dualfeas(end),runhist.relgap(end)); 321 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 322 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 323 | fprintf('\n etaQ = %3.2e', etaQ); fprintf(' etaS = %3.2e', etaS); 324 | fprintf('\n etab = %3.2e', etab); 325 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 326 | info.minX,info.maxX); 327 | fprintf('\n sigma = %3.1e',sigma*bscale/Cscale); 328 | fprintf('\n--------------------------------------------------------------'); 329 | fprintf('------------------\n'); 330 | end 331 | %%********************************************************************** 332 | %% solve A*q = r. 333 | %%********************************************************************** 334 | function q = mylinsysolve(L,r) 335 | 336 | if (L.isidentity) 337 | q = r; 338 | else 339 | if strcmp(L.matfct_options,'chol') 340 | q(L.perm,1) = mextriang(L.R, mextriang(L.R,r(L.perm),2) ,1); 341 | elseif strcmp(L.matfct_options,'spcholmatlab') 342 | q(L.perm,1) = mexbwsolve(L.Rt,mexfwsolve(L.R,r(L.perm,1))); 343 | end 344 | end 345 | %%********************************************************************** 346 | 347 | %%********************************************************************** 348 | function normXn = compnormXn(X) 349 | 350 | d = eig(full(X)); 351 | normXn = norm(d(d<0)); 352 | %%********************************************************************** 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | -------------------------------------------------------------------------------- /QSDPNAL_main/SCB/SCB_LSI.m: -------------------------------------------------------------------------------- 1 | %%************************************************************************* 2 | %% QSDPNAL: Phase I 3 | %% An inexact SCB based semi-Proximal ADMM for solving Least Squres problems: 4 | %% (P) min {1/2||H(X)||_F^2 + | A(X)=b, B(X)>=d, X \in K} 5 | %% where K = psd cone 6 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H(X) = Y, B(X) - alpha*v =d, X\in K, v>=0} 7 | %% 8 | %% (D') max -1/2 ||Xi||^2 + + 9 | %% s.t. H^*(Xi) + S + A^*yE + B^*yI= C, 10 | %% alpha*(u - yI) = 0, 11 | %% S \in PSD, u>=0 12 | %%************************************************************************* 13 | %% QSDPNAL: 14 | %% Copyright (c) 2015 by 15 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 16 | %%************************************************************************* 17 | 18 | function [obj,xi,S,yE,yI,X,runhist,info] = SCB_LSI(blk,H,A,b,B,d,C,options,X,xi,S,yE,yI) 19 | %% For inexact criteria 20 | rng('default'); 21 | rhsconst =0.09; 22 | feasiconst=0.9; 23 | tolconst =100; 24 | %% General options 25 | maxiter = 5000; 26 | stoptol = 1e-6; 27 | printyes = 1; 28 | printminoryes=1; 29 | scale_data = 1; 30 | rescale = 1; 31 | gamma = 1.618; %step length in SCB ADMM 32 | sigma = 1; 33 | gamma_reset_start = 200; 34 | sGS = 1; 35 | sig_fix = 0; 36 | stopoption = 0; 37 | phase2 = 0; 38 | 39 | % options for linear system solvers 40 | % for AEsolver: `pcg' and `sparse_chol' 41 | % for Hsolver and AIsolver only `pcg' 42 | AEsolver = 'sparse_chol';%'pcg';% 43 | AIsolver = 'pcg'; 44 | Hsolver = 'pcg'; 45 | 46 | % options from users 47 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 48 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 49 | if isfield(options,'printyes'); printyes = options.printyes; end 50 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 51 | if isfield(options,'scale_data'); scale_data = options.scale_data; end 52 | if isfield(options,'rescale'); rescale = options.rescale; end 53 | if isfield(options,'sigma'); sigma = options.sigma; end 54 | if isfield(options,'gamma'); gamma = options.gamma; end 55 | if isfield(options,'stopoption'); stopoption = options.stopoption; end 56 | if isfield(options,'phase2'); phase2 = options.phase2; end 57 | %% solvers for AE, AI 58 | if isfield(options,'AEsolver'); AEsolver = options.AEsolver; end 59 | if isfield(options,'AIsolver'); AIsolver = options.AIsolver; end 60 | if isfield(options,'sGS'); sGS = options.sGS; end 61 | %% problem property 62 | existA = ~isempty(A); 63 | existH = ~isempty(H); 64 | existB = ~isempty(B); 65 | tstart = clock; 66 | n = blk{1,2}; 67 | nbar = n*(n+1)/2; 68 | Zero = sparse(n,n); 69 | Fnorm = @(X) mexFnorm(X); 70 | %% AEmap, AETmap, Bmap, BTmap, Hmap 71 | if existA 72 | if isstruct(A) 73 | if isfield(A,'At'); At = A.At; end 74 | if isfield(A,'Amap'); Amap0 = A.Amap; end 75 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 76 | else 77 | At = A; 78 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 79 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 80 | end 81 | else 82 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 83 | end 84 | if existB 85 | if isstruct(B) 86 | if isfield(B,'Bt'); Bt = B.Bt; end 87 | if isfield(B,'Bmap'); Bmap0 = B.Bmap; end 88 | if isfield(B,'BTmap'); BTmap0 = B.BTmap; end 89 | else 90 | Bt = B; 91 | Bmap0 = @(X) sdpnalAXfun(blk,Bt,X); 92 | BTmap0 = @(y) sdpnalAtyfun(blk,Bt,y); 93 | end 94 | else 95 | Bmap0 = @(X) []; BTmap0 = @(y) Zero; 96 | end 97 | if existH 98 | if isstruct(H) 99 | if isfield(H,'Ht'); Ht = H.Ht; end 100 | if isfield(H,'Hmap'); Hmap0 = H.Hmap; end 101 | if isfield(H,'HTmap'); HTmap0 = H.HTmap; end 102 | else 103 | Ht = H; 104 | Hmap0 = @(X) sdpnalAXfun(blk,Ht,X); 105 | HTmap0 = @(y) sdpnalAtyfun(blk,Ht,y); 106 | end 107 | else 108 | Hmap0 = @(X) []; HTmap0 = @(y) Zero; 109 | end 110 | %%% 111 | if ~exist('X','var'); X = Zero; end 112 | if ~exist('yE','var'); yE = zeros(length(b),1); end 113 | if ~exist('yI','var'); yI = zeros(length(d),1); end 114 | if ~exist('S','var'); S = Zero; end 115 | if ~existA; yE = []; b = []; end 116 | if ~exist('xi','var'); xi = zeros(size(Ht,2),1); end 117 | %% 118 | %% initial scaling 119 | %% 120 | Atorg = At; borg = b; Htorg = Ht; 121 | if existB 122 | Btorg = Bt; dorg = d; 123 | normdorg = 1 + norm(dorg); 124 | else 125 | dorg = 0; 126 | end 127 | Corg = C; 128 | normCorg = 1 + Fnorm(Corg); 129 | normborg = 1 + norm(borg); 130 | eigsopt.issym = 1; 131 | if existA 132 | nE = length(b); 133 | normA = sum(At.*At)'; 134 | normA = max(1,sqrt(normA)); 135 | DA = spdiags(1./normA,0,nE,nE); 136 | At = At*DA; 137 | b = DA*b; 138 | normAt = Fnorm(At); 139 | Amap = @(X) Amap0(X)./normA; 140 | ATmap = @(y) ATmap0(y./normA); 141 | AATmap = @(y) Amap(ATmap(y)); 142 | if strcmp(AEsolver,'sparse_chol') 143 | [LAAt,AAt] = mycholAAt(At,nE); 144 | dd = diag(AAt); 145 | if (Fnorm(AAt-speye(nE)) < 1e-12) 146 | if printyes; fprintf('\n AEAEt is identity '); end %% For BIQ, FAP and Theta(+) problems 147 | LAAt.isidentity = true; 148 | elseif (Fnorm(AAt-spdiags(dd,0,nE,nE)) < 1e-15*norm(dd)) 149 | fprintf('\n AAt is diagonal '); 150 | LAAt.isidentity = false; 151 | else 152 | LAAt.isidentity = false; 153 | end 154 | AEsolve = @(rhs) mylinsysolve(LAAt,rhs); 155 | if printyes; fprintf('\n AEAEt solved by chol decompostion'); end 156 | elseif strcmp(AEsolver,'pcg') 157 | rr = min(6,nE); 158 | [VA,dA,flagA] = eigs(AATmap,nE,rr,'LA',eigsopt); 159 | dA = diag(dA); rr = sum(dA>0); 160 | pcgA = min(3,rr); 161 | parA.V = VA(:,1:pcgA); parA.Vt = parA.V'; 162 | parA.d = dA(1:pcgA); 163 | parA.precond = 2; 164 | if printyes; fprintf('\n using pcg to solve AEAEt'); end 165 | end 166 | else 167 | Amap = @(X) []; ATmap = @(y) Zero; AATmap = @(y) []; 168 | normA = []; DA = []; nE = 0; 169 | end 170 | if existB 171 | nI = length(d); 172 | normB = sum(Bt.*Bt)'; 173 | normB = max(1,sqrt(normB)); 174 | DB = spdiags(1./normB,0,nI,nI); 175 | Bt = Bt*DB; 176 | d = DB*d; 177 | normBt = Fnorm(Bt); 178 | Bmap = @(X) Bmap0(X)./normB; 179 | BTmap = @(y) BTmap0(y./normB); 180 | BBTmap = @(y) Bmap(BTmap(y)); 181 | rr = min(6,nI); 182 | [VB,dB,flagB] = eigs(BBTmap,nI,rr,'LA',eigsopt); 183 | dB = diag(dB); rr = sum(dB>0); 184 | if rr>0; alpha = max(dB)^(0.25)/2; else alpha = 1; end 185 | if isfield(options,'alpha'); alpha = options.alpha; end 186 | if strcmp(AIsolver,'pcg') 187 | pcgB = min(3,rr); 188 | parB.V = VB(:,1:pcgB); parB.Vt = parB.V'; 189 | parB.d = dB(1:pcgB)+alpha^2; 190 | parB.precond = 2; 191 | parB.alpha = alpha; 192 | if printyes; fprintf('\n using pcg to solve AIAIt'); end 193 | end 194 | else 195 | Bmap = @(X) []; BTmap = @(y) Zero; BBTmap = @(y) []; 196 | normB = []; DB = []; nI = 0; 197 | end 198 | if (scale_data == 1) 199 | if existB; bscale = max(1,norm([b;d])); else; bscale = max(1,norm(b)); end 200 | Cscale = max(1,Fnorm(C)); 201 | elseif scale_data == 0 202 | bscale = 1; 203 | Cscale = 1; 204 | end 205 | if existH 206 | Hmap = @(X) Hmap0(X)*sqrt(bscale/Cscale); 207 | HTmap = @(y) HTmap0(y)*sqrt(bscale/Cscale); 208 | HHTmap = @(y) Hmap(HTmap(y)); 209 | end 210 | b = b/bscale; C = C/Cscale; d = d/bscale; 211 | X = X/bscale; 212 | yE = (normA.*yE)/Cscale; yI = (normB.*yI)/Cscale; 213 | S = S/Cscale; 214 | objscale = bscale*Cscale; 215 | xi = xi/sqrt(objscale); 216 | 217 | if printyes 218 | fprintf('\n *******************************************************'); 219 | fprintf('******************************************'); 220 | fprintf('\n \t\t SCB_LSI with beginning gamma = %6.3f', gamma); 221 | fprintf('\n ******************************************************'); 222 | fprintf('*******************************************\n'); 223 | if printminoryes 224 | fprintf('\n n = %3.0f, mE = %3.0f, mI = %3.0f',n, nE, nI); 225 | fprintf('\n scale_data = %2.0f', scale_data); 226 | fprintf('\n bscale = %3.2e, cscale = %3.2e', bscale, Cscale); 227 | if existB; fprintf('\n inequality alpha = %3.2e', alpha); end 228 | fprintf('\n ---------------------------------------------------'); 229 | end 230 | fprintf('\n iter| pinforg dinforg relgaporg| pobj dobj |'); 231 | fprintf(' time | sigma |rankS, minspeed|gamma|'); 232 | end 233 | %%----------------------------------------------------------------- 234 | %% start main solver 235 | % parameters for main solver 236 | parmain.existH = existH; parmain.existB = existB; parmain.existA = existA; 237 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 238 | parmain.AEsolver = AEsolver; parmain.AIsolver = AIsolver; parmain.Hsolver = Hsolver; 239 | parmain.DA = DA; parmain.DB = DB; 240 | parmain.nE = nE; parmain.nI = nI; parmain.n = n; 241 | parmain.normA = normA; parmain.normB = normB; 242 | parmain.normAt = normAt; 243 | parmain.normBt = normBt; 244 | parmain.Htorg = Htorg; 245 | parmain.normborg = normborg; 246 | parmain.normCorg = normCorg; 247 | 248 | parmain.sigma = sigma; 249 | parmain.alpha = alpha; 250 | parmain.gamma = gamma; 251 | parmain.tstart= tstart; 252 | parmain.maxiter = maxiter; 253 | parmain.rescale = rescale; 254 | parmain.feasiconst = feasiconst; 255 | parmain.rhsconst = rhsconst; 256 | parmain.stoptol = stoptol; 257 | parmain.printyes = printyes; 258 | parmain.sGS = sGS; 259 | parmain.gamma_reset_start = gamma_reset_start; 260 | parmain.sig_fix = sig_fix; 261 | parmain.stopoption = stopoption; 262 | parmain.tolconst = tolconst; 263 | 264 | 265 | if strcmp(AEsolver,'pcg'); 266 | parmain.parA = parA; 267 | elseif strcmp(AEsolver,'sparse_chol'); 268 | parmain.AEsolve = AEsolve; 269 | end 270 | if strcmp(AIsolver,'pcg'); parmain.parB = parB; end 271 | 272 | Hinput.Hmap = Hmap; Hinput.HTmap = HTmap; Hinput.HHTmap = HHTmap; 273 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.AATmap = AATmap; 274 | Binput.Bmap = Bmap; Binput.BTmap = BTmap; Binput.BBTmap = BBTmap; 275 | 276 | % main file of SCB ADMM for solving Least Squres QSDP problem 277 | % with inequality constraints 278 | [X,yE,yI,S,xi,info_main,runhist] = ... 279 | SCB_LSImain(Hinput,Ainput,Binput,b,C,d,parmain,X,yE,yI,S,xi); 280 | 281 | % information 282 | iter = info_main.iter; 283 | msg = info_main.msg; 284 | bscale = info_main.bscale; 285 | Cscale = info_main.Cscale; 286 | breakyes = info_main.breakyes; 287 | iterProj = info_main.iterProj; 288 | repeatyE = info_main.repeatyE; 289 | repeatyI = info_main.repeatyI; 290 | sigma = info_main.sigma; 291 | if phase2 292 | if existB 293 | u = info_main.u; v = info_main.v; 294 | d = info_main.d; %normd = info_main.normd; 295 | end 296 | b = info_main.b; normb = info_main.normb; 297 | C = info_main.C; normC = info_main.normC; 298 | if existH&&strcmp(Hsolver,'pcg'); HHtxi = info_main.HHtxi; end 299 | end 300 | %%----------------------------------------------------------------- 301 | %% recover orignal variables 302 | %%----------------------------------------------------------------- 303 | if (iter == maxiter) 304 | msg = ' maximum iteration reached'; 305 | info.termcode = 3; 306 | end 307 | X = X*bscale; normX = norm(X,'fro'); 308 | HX = Hmap0(X); 309 | yE = Cscale*(DA*yE); 310 | S = Cscale*S; normS = norm(S,'fro'); 311 | xi = sqrt(bscale*Cscale)*xi; 312 | Htxi = HTmap0(xi); 313 | if existB; 314 | yI = Cscale*(DB*yI); 315 | BtyI = BTmap0(yI); 316 | normyI = norm(yI); 317 | RpI = dorg - Bmap0(X); 318 | dTyI = dorg'*yI; 319 | end 320 | if existA; bTyE = borg'*yE; end 321 | AX = Amap0(X); AtyE = ATmap0(yE); 322 | primobj = full(0.5*norm(HX)^2 + sum(sum(Corg.*X))); 323 | dualobj = full(dTyI + bTyE - 0.5*norm(xi)^2); 324 | obj = [primobj,dualobj]; 325 | etaQ = Fnorm(xi+HX)/(1+Fnorm(Htorg)); 326 | if (true) 327 | etaSp = compnormXn(X) /(1+normX); 328 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 329 | etaS = max(etaSp,etaSc); 330 | end 331 | if existB 332 | etayId = norm(min(yI,0))/(1+normyI); 333 | normRpI = norm(RpI); 334 | etayIp = norm(max(RpI,0))/(1+normRpI); 335 | etayIc = full(abs(yI'*RpI)/(1+normyI+normRpI)); 336 | etayI = max([etayId,etayIp,etayIc]); 337 | else 338 | etayI = 0; etayId = 0; etayIp = 0; etayIc = 0; 339 | end 340 | etab = norm(AX-borg)/normborg; 341 | primfeasorg = max(etab,etayIp); 342 | dualfeasorg = max(norm(Htxi+S+AtyE+BtyI-Corg,'fro')/normCorg,etayId); 343 | ttime = etime(clock,tstart); 344 | runhist.nE = nE; 345 | runhist.ns = n; 346 | runhist.nI = nI; 347 | runhist.iter = iter; 348 | runhist.totaltime = ttime; 349 | runhist.primobjorg = primobj; 350 | runhist.dualobjorg = dualobj; 351 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 352 | runhist.primfeasorg(iter) = primfeasorg; 353 | runhist.dualfeasorg(iter) = dualfeasorg; 354 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 355 | info.nE = nE; 356 | info.ns = n; 357 | info.nI = nI; 358 | info.iter = iter; 359 | info.totaltime = ttime; 360 | info.primobjorg = primobj; 361 | info.dualobjorg = dualobj; 362 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 363 | info.etaS = etaS; 364 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 365 | info.etaQ = etaQ; 366 | info.etab = etab; 367 | info.etayI = etayI; 368 | info.etayId = etayId; 369 | info.etayIp = etayIp; 370 | info.etayIc = etayIc; 371 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ,etayIc]); 372 | info.minX = min(min(X)); 373 | info.maxX = max(max(X)); 374 | info.psqmrA1 = sum(runhist.psqmrA1); 375 | info.psqmrA2 = sum(runhist.psqmrA2); 376 | info.psqmrB1 = sum(runhist.psqmrB1); 377 | info.psqmrB2 = sum(runhist.psqmrB2); 378 | info.breakyes = breakyes; 379 | %% added for Phase II 380 | if phase2 381 | info.Amap = Amap; info.ATmap = ATmap; 382 | info.bscale = bscale; info.Cscale = Cscale; 383 | info.sigma = sigma; 384 | info.AAt = AAt; 385 | info.AEsolve = AEsolve; 386 | if exist('At','var'); info.At = At; end 387 | info.normA = normA; info.DA = DA; info.normAt = normAt; 388 | info.b = b; info.normb = normb; info.C = C; info.normC = normC; 389 | if existB; 390 | info.d = d; info.u = u; info.v = v; info.DB = DB; 391 | %info.normd = normd; 392 | info.normB = normB; info.parB = parB; 393 | info.normBt = normBt; 394 | info.alpha = alpha; 395 | info.Bmap = Bmap; info.BTmap = BTmap; 396 | end 397 | if existH&&strcmp(Hsolver,'pcg'); info.HHtxi = HHtxi; end 398 | end 399 | if (printminoryes) 400 | if ~isempty(msg); fprintf('\n %s',msg); end 401 | fprintf('\n--------------------------------------------------------------'); 402 | fprintf('------------------'); 403 | fprintf('\n number iter = %2.0d',iter); 404 | fprintf('\n number of iterProj = %2.0f',iterProj); 405 | fprintf('\n number iter = %2.0d \t repeaty= %d \t repeatyI = %d',... 406 | iter,repeatyE, repeatyI); 407 | if existA && strcmp(AEsolver,'pcg') 408 | fprintf('\n number of PSQMRiterA for 1st system = %2.0f',info.psqmrA1); 409 | fprintf('\n number of PSQMRiterA for 2nd system = %2.0f',info.psqmrA2); 410 | end 411 | if existB 412 | fprintf('\n number of PSQMRiterB for 1st system = %2.0f',info.psqmrB1); 413 | fprintf('\n number of PSQMRiterB for 2nd system = %2.0f',info.psqmrB2); 414 | end 415 | fprintf('\n time = %3.2f',ttime); 416 | fprintf('\n time per iter = %5.4f',ttime/iter); 417 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 418 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 419 | fprintf('\n primfeas = %3.2e, dualfeas = %3.2e, relgap = %3.2e',... 420 | runhist.primfeas(end),runhist.dualfeas(end),runhist.relgap(end)); 421 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 422 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 423 | fprintf('\n etaQ = %3.2e', etaQ); fprintf(' etaS = %3.2e', etaS); 424 | fprintf('\n etab = %3.2e', etab); 425 | if existB 426 | fprintf('\n [etayI, etayIp, etayId, etayIc] = [%3.2e %3.2e %3.2e %3.2e]',... 427 | etayI,etayIp,etayId,etayIc); 428 | end 429 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 430 | info.minX,info.maxX); 431 | fprintf('\n sigma = %3.1e',sigma); 432 | fprintf('\n--------------------------------------------------------------'); 433 | fprintf('------------------\n'); 434 | end 435 | %%********************************************************************** 436 | %% solve A*q = r. 437 | %%********************************************************************** 438 | function q = mylinsysolve(L,r) 439 | 440 | if (L.isidentity) 441 | q = r; 442 | else 443 | if strcmp(L.matfct_options,'chol') 444 | q(L.perm,1) = mextriang(L.R, mextriang(L.R,r(L.perm),2) ,1); 445 | elseif strcmp(L.matfct_options,'spcholmatlab') 446 | q(L.perm,1) = mexbwsolve(L.Rt,mexfwsolve(L.R,r(L.perm,1))); 447 | end 448 | end 449 | %%********************************************************************** 450 | %%********************************************************************** 451 | function normXn = compnormXn(X) 452 | 453 | d = eig(full(X)); 454 | normXn = norm(d(d<0)); 455 | %%********************************************************************** 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | -------------------------------------------------------------------------------- /QSDPNAL_main/SCB/SCB_NCM.m: -------------------------------------------------------------------------------- 1 | %%************************************************************************* 2 | %% QSDPNAL: Phase I 3 | %% An inexact SCB based semi-Proximal ADMM for solving NCM problems: 4 | %% (P) min {1/2||H o X||_F^2 + | A(X)=b, X \in K} 5 | %% where K = psd cone 6 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H o X = Y, X\in K} 7 | %% 8 | %% (D') max -1/2 ||Xi||^2 + 9 | %% s.t. H o Xi + S + A*y = C, 10 | %% S \in PSD. 11 | %%************************************************************************* 12 | %% QSDPNAL: 13 | %% Copyright (c) 2015 by 14 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 15 | %%************************************************************************* 16 | 17 | function [obj,Xi,S,yE,X,runhist,info] = SCB_NCM(blk,H,A,b,C,options,X,Xi,S,yE) 18 | %% For inexact criteria 19 | rng('default'); 20 | rhsconst =0.09; 21 | feasiconst=0.9; 22 | tolconst =100; 23 | %% General options 24 | maxiter = 5000; 25 | stoptol = 1e-6; 26 | printyes = 1; 27 | printminoryes=1; 28 | scale_data = 1; 29 | rescale = 1; 30 | gamma = 1.618; %step length in SCB ADMM 31 | sigma = 1; 32 | gamma_reset_start = 200; 33 | sGS = 1; 34 | sig_fix = 0; 35 | stopoption = 0; 36 | phase2 = 0; 37 | 38 | % options for linear system solvers 39 | % for AEsolver: `pcg' and `sparse_chol' 40 | AEsolver = 'sparse_chol';%'pcg';% 41 | 42 | % options from users 43 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 44 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 45 | if isfield(options,'printyes'); printyes = options.printyes; end 46 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 47 | if isfield(options,'scale_data'); scale_data = options.scale_data; end 48 | if isfield(options,'rescale'); rescale = options.rescale; end 49 | if isfield(options,'sigma'); sigma = options.sigma; end 50 | if isfield(options,'gamma'); gamma = options.gamma; end 51 | if isfield(options,'stopoption'); stopoption = options.stopoption; end 52 | if isfield(options,'phase2'); phase2 = options.phase2; end 53 | %% solvers for AE 54 | if isfield(options,'AEsolver'); AEsolver = options.AEsolver; end 55 | if isfield(options,'sGS'); sGS = options.sGS; end 56 | %% problem property 57 | existA = ~isempty(A); 58 | tstart = clock; 59 | n = blk{1,2}; 60 | nbar = n*(n+1)/2; 61 | Zero = sparse(n,n); 62 | Fnorm = @(X) mexFnorm(X); 63 | %% AEmap, AETmap 64 | if existA 65 | if isstruct(A) 66 | if isfield(A,'At'); At = A.At; end 67 | if isfield(A,'Amap'); Amap0 = A.Amap; end 68 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 69 | else 70 | At = A; 71 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 72 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 73 | end 74 | else 75 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 76 | end 77 | %%% 78 | if ~exist('X','var'); X = Zero; end 79 | if ~exist('yE','var'); yE = zeros(length(b),1); end 80 | if ~exist('S','var'); S = Zero; end 81 | if ~existA; yE = []; b = []; end 82 | if ~exist('Xi','var'); Xi = Zero; end 83 | %% 84 | %% initial scaling 85 | %% 86 | Atorg = At; borg = b; Horg = H; 87 | Corg = C; 88 | normCorg = 1 + Fnorm(Corg); 89 | normborg = 1 + norm(borg); 90 | eigsopt.issym = 1; 91 | if existA 92 | nE = length(b); 93 | normA = sum(At.*At)'; 94 | normA = max(1,sqrt(normA)); 95 | DA = spdiags(1./normA,0,nE,nE); 96 | At = At*DA; 97 | b = DA*b; 98 | normAt = Fnorm(At); 99 | Amap = @(X) Amap0(X)./normA; 100 | ATmap = @(y) ATmap0(y./normA); 101 | AATmap = @(y) Amap(ATmap(y)); 102 | if strcmp(AEsolver,'sparse_chol') 103 | [LAAt,AAt] = mycholAAt(At,nE); 104 | dd = diag(AAt); 105 | if (Fnorm(AAt-speye(nE)) < 1e-12) 106 | if printyes; fprintf('\n AEAEt is identity '); end %% For BIQ, FAP and Theta(+) problems 107 | LAAt.isidentity = true; 108 | elseif (Fnorm(AAt-spdiags(dd,0,nE,nE)) < 1e-15*norm(dd)) 109 | fprintf('\n AAt is diagonal '); 110 | LAAt.isidentity = false; 111 | else 112 | LAAt.isidentity = false; 113 | end 114 | AEsolve = @(rhs) mylinsysolve(LAAt,rhs); 115 | if printyes; fprintf('\n AEAEt solved by chol decompostion'); end 116 | elseif strcmp(AEsolver,'pcg') 117 | rr = min(6,nE); 118 | [VA,dA,flagA] = eigs(AATmap,nE,rr,'LA',eigsopt); 119 | dA = diag(dA); rr = sum(dA>0); 120 | pcgA = min(3,rr); 121 | parA.V = VA(:,1:pcgA); parA.Vt = parA.V'; 122 | parA.d = dA(1:pcgA); 123 | parA.precond = 2; 124 | if printyes; fprintf('\n using pcg to solve AEAEt'); end 125 | end 126 | else 127 | Amap = @(X) []; ATmap = @(y) Zero; 128 | normA = []; DA = []; nE = 0; 129 | end 130 | 131 | if (scale_data == 1) 132 | bscale = max(1,norm(b)); 133 | Cscale = max(1,Fnorm(C)); 134 | elseif scale_data == 0 135 | bscale = 1; 136 | Cscale = 1; 137 | end 138 | b = b/bscale; C = C/Cscale; 139 | X = X/bscale; 140 | yE = (normA.*yE)/Cscale; 141 | S = S/Cscale; 142 | objscale = bscale*Cscale; 143 | Xi = Xi/sqrt(objscale); 144 | 145 | if printyes 146 | fprintf('\n *******************************************************'); 147 | fprintf('******************************************'); 148 | fprintf('\n \t\t SCB_NCM with beginning gamma = %6.3f', gamma); 149 | fprintf('\n ******************************************************'); 150 | fprintf('*******************************************\n'); 151 | if printminoryes 152 | fprintf('\n n = %3.0f, mE = %3.0f',n, nE); 153 | fprintf('\n scale_data = %2.0f', scale_data); 154 | fprintf('\n bscale = %3.2e, cscale = %3.2e', bscale, Cscale); 155 | fprintf('\n ---------------------------------------------------'); 156 | end 157 | fprintf('\n iter| pinforg dinforg relgaporg| pobj dobj |'); 158 | fprintf(' time | sigma |rankS, minspeed|gamma|'); 159 | end 160 | 161 | 162 | %%----------------------------------------------------------------- 163 | %% start main solver 164 | % parameters for main solver 165 | parmain.existA = existA; 166 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 167 | parmain.AEsolver = AEsolver; 168 | parmain.DA = DA; 169 | parmain.nE = nE; parmain.n = n; 170 | parmain.normA = normA; 171 | parmain.normAt = normAt; 172 | parmain.normborg = normborg; 173 | parmain.normCorg = normCorg; 174 | 175 | parmain.sigma = sigma; 176 | parmain.gamma = gamma; 177 | parmain.tstart= tstart; 178 | parmain.maxiter = maxiter; 179 | parmain.rescale = rescale; 180 | parmain.feasiconst = feasiconst; 181 | parmain.rhsconst = rhsconst; 182 | parmain.stoptol = stoptol; 183 | parmain.printyes = printyes; 184 | parmain.sGS = sGS; 185 | parmain.gamma_reset_start = gamma_reset_start; 186 | parmain.sig_fix = sig_fix; 187 | parmain.stopoption = stopoption; 188 | parmain.tolconst = tolconst; 189 | 190 | if strcmp(AEsolver,'pcg'); 191 | parmain.parA = parA; 192 | elseif strcmp(AEsolver,'sparse_chol'); 193 | parmain.AEsolve = AEsolve; 194 | end 195 | 196 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.AATmap = AATmap; 197 | 198 | % main file of SCB ADMM for solving NCM problem 199 | [X,yE,S,Xi,info_main,runhist] = ... 200 | SCB_NCMmain(Horg,Ainput,b,C,parmain,X,yE,S,Xi); 201 | 202 | % information 203 | iter = info_main.iter; 204 | msg = info_main.msg; 205 | bscale = info_main.bscale; 206 | Cscale = info_main.Cscale; 207 | breakyes = info_main.breakyes; 208 | iterProj = info_main.iterProj; 209 | repeatyE = info_main.repeatyE; 210 | sigma = info_main.sigma; 211 | if phase2 212 | b = info_main.b; normb = info_main.normb; 213 | C = info_main.C; normC = info_main.normC; 214 | H = info_main.H; 215 | end 216 | %%----------------------------------------------------------------- 217 | %% recover orignal variables 218 | %%----------------------------------------------------------------- 219 | if (iter == maxiter) 220 | msg = ' maximum iteration reached'; 221 | info.termcode = 3; 222 | end 223 | X = X*bscale; normX = norm(X,'fro'); 224 | HX = Horg.*X; 225 | yE = Cscale*(DA*yE); 226 | S = Cscale*S; normS = norm(S,'fro'); 227 | Xi = sqrt(bscale*Cscale)*Xi; 228 | HXi = Horg.*Xi; 229 | if existA; bTyE = borg'*yE; end 230 | AX = Amap0(X); AtyE = ATmap0(yE); 231 | primobj = 0.5*Fnorm(HX)^2 + sum(sum(Corg.*X)); 232 | dualobj = bTyE - 0.5*Fnorm(Xi)^2; 233 | obj = [primobj,dualobj]; 234 | etaQ = Fnorm(Xi+HX)/(1+Fnorm(Horg)); 235 | if (true) 236 | etaSp = compnormXn(X) /(1+normX); 237 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 238 | etaS = max(etaSp,etaSc); 239 | end 240 | etab = norm(AX-borg)/normborg; 241 | primfeasorg = max(etab); 242 | dualfeasorg = max(norm(HXi+S+AtyE-Corg,'fro')/normCorg); 243 | ttime = etime(clock,tstart); 244 | runhist.nE = nE; 245 | runhist.ns = n; 246 | runhist.iter = iter; 247 | runhist.totaltime = ttime; 248 | runhist.primobjorg = primobj; 249 | runhist.dualobjorg = dualobj; 250 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 251 | runhist.primfeasorg(iter) = primfeasorg; 252 | runhist.dualfeasorg(iter) = dualfeasorg; 253 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 254 | info.nE = nE; 255 | info.ns = n; 256 | info.iter = iter; 257 | info.totaltime = ttime; 258 | info.primobjorg = primobj; 259 | info.dualobjorg = dualobj; 260 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 261 | info.etaS = etaS; 262 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 263 | info.etaQ = etaQ; 264 | info.etab = etab; 265 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 266 | info.minX = min(min(X)); 267 | info.maxX = max(max(X)); 268 | info.psqmrA1 = sum(runhist.psqmrA1); 269 | info.psqmrA2 = sum(runhist.psqmrA2); 270 | info.breakyes = breakyes; 271 | %% added for Phase II 272 | if phase2 273 | info.nXi = nbar; 274 | info.Amap = Amap; info.ATmap = ATmap; 275 | info.bscale = bscale; info.Cscale = Cscale; 276 | info.sigma = sigma; 277 | info.AAt = AAt; 278 | info.AEsolve = AEsolve; 279 | if exist('At','var'); info.At = At; end 280 | info.normA = normA; info.DA = DA; info.normAt = normAt; 281 | info.b = b; info.normb = normb; info.C = C; info.normC = normC; 282 | info.H = H; 283 | end 284 | if (printminoryes) 285 | if ~isempty(msg); fprintf('\n %s',msg); end 286 | fprintf('\n--------------------------------------------------------------'); 287 | fprintf('------------------'); 288 | fprintf('\n number iter = %2.0d',iter); 289 | fprintf('\n number of iterProj = %2.0f',iterProj); 290 | fprintf('\n number iter = %2.0d \t repeaty= %d ',... 291 | iter,repeatyE); 292 | if existA && strcmp(AEsolver,'pcg') 293 | fprintf('\n number of PSQMRiterA for 1st system = %2.0f',info.psqmrA1); 294 | fprintf('\n number of PSQMRiterA for 2nd system = %2.0f',info.psqmrA2); 295 | end 296 | fprintf('\n time = %3.2f',ttime); 297 | if iter >0; fprintf('\n time per iter = %5.4f',ttime/iter); end 298 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 299 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 300 | %fprintf('\n primfeas = %3.2e, dualfeas = %3.2e, relgap = %3.2e',... 301 | % runhist.primfeas(end),runhist.dualfeas(end),runhist.relgap(end)); 302 | if iter >0; 303 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 304 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 305 | fprintf('\n etaQ = %3.2e', etaQ); fprintf(' etaS = %3.2e', etaS); 306 | fprintf('\n etab = %3.2e', etab); 307 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 308 | info.minX,info.maxX); 309 | fprintf('\n sigma = %3.1e',sigma); 310 | end 311 | fprintf('\n--------------------------------------------------------------'); 312 | fprintf('------------------\n'); 313 | end 314 | %%********************************************************************** 315 | %% solve A*q = r. 316 | %%********************************************************************** 317 | function q = mylinsysolve(L,r) 318 | 319 | if (L.isidentity) 320 | q = r; 321 | else 322 | if strcmp(L.matfct_options,'chol') 323 | q(L.perm,1) = mextriang(L.R, mextriang(L.R,r(L.perm),2) ,1); 324 | elseif strcmp(L.matfct_options,'spcholmatlab') 325 | q(L.perm,1) = mexbwsolve(L.Rt,mexfwsolve(L.R,r(L.perm,1))); 326 | end 327 | end 328 | %%********************************************************************** 329 | %%********************************************************************** 330 | function normXn = compnormXn(X) 331 | 332 | d = eig(full(X)); 333 | normXn = norm(d(d<0)); 334 | %%********************************************************************** 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | -------------------------------------------------------------------------------- /QSDPNAL_main/SCB/SCB_NCMP.m: -------------------------------------------------------------------------------- 1 | %%************************************************************************* 2 | %% QSDPNAL: Phase I 3 | %% An inexact SCB based semi-Proximal ADMM for solving NCM problems with 4 | %% Polyhderal constraints: 5 | %% (P) min {1/2||H o X||_F^2 + | A(X)=b, X \in K, X\in P} 6 | %% where K = psd cone, P is ployhedral set e.g., P = {X | L<= X <= U}. 7 | %% (P') min {1/2 ||Y||_F^2 + | A(X) = b, H o X = Y, X\in K, X\in P} 8 | %% 9 | %% (D') max -\delta_{P}^*(-Z) - 1/2 ||Xi||^2 + 10 | %% s.t. Z + H o Xi + S + A*y = C, 11 | %% S \in PSD. 12 | %%************************************************************************* 13 | %% QSDPNAL: 14 | %% Copyright (c) 2015 by 15 | %% Xudong Li, Defeng Sun, and Kim-Chuan Toh 16 | %%************************************************************************* 17 | 18 | function [obj,Z,Xi,S,yE,X,runhist,info] = SCB_NCMP(blk,H,A,b,C,options,X,Z,Xi,S,yE) 19 | %% For inexact criteria 20 | rng('default'); 21 | rhsconst =0.09; 22 | feasiconst=0.9; 23 | tolconst =100; 24 | %% General options 25 | maxiter = 5000; 26 | stoptol = 1e-6; 27 | printyes = 1; 28 | printminoryes=1; 29 | scale_data = 1; 30 | rescale = 1; 31 | gamma = 1.618; %step length in SCB ADMM 32 | sigma = 1; 33 | gamma_reset_start = 200; 34 | sGS = 1; 35 | sig_fix = 0; 36 | stopoption = 0; 37 | phase2 = 0; 38 | % options for linear system solvers 39 | % for AEsolver: `pcg' and `sparse_chol' 40 | AEsolver = 'sparse_chol';%'pcg';% 41 | 42 | % options from users 43 | if isfield(options,'maxiter'); maxiter = options.maxiter; end 44 | if isfield(options,'stoptol'); stoptol = options.stoptol; end 45 | if isfield(options,'printyes'); printyes = options.printyes; end 46 | if isfield(options,'printminoryes'); printminoryes = options.printminoryes; end 47 | if isfield(options,'scale_data'); scale_data = options.scale_data; end 48 | if isfield(options,'rescale'); rescale = options.rescale; end 49 | if isfield(options,'sigma'); sigma = options.sigma; end 50 | if isfield(options,'gamma'); gamma = options.gamma; end 51 | if isfield(options,'stopoption'); stopoption = options.stopoption; end 52 | if isfield(options,'phase2'); phase2 = options.phase2; end 53 | %% solvers for AE 54 | if isfield(options,'AEsolver'); AEsolver = options.AEsolver; end 55 | if isfield(options,'sGS'); sGS = options.sGS; end 56 | %% information for \cP 57 | nonnegative = 0; L = []; U = []; SignP = []; fV = []; 58 | if isfield(options,'upperbound'); U = options.upperbound; end 59 | if isfield(options,'lowerbound'); L = options.lowerbound; end 60 | if isfield(options,'SignP'); SignP = options.SignP; end 61 | if isfield(options,'fV'); fV = options.fV; end 62 | if isfield(options,'nonnegative'); nonnegative = options.nonnegative; end 63 | %% problem property 64 | existA = ~isempty(A); 65 | tstart = clock; 66 | n = blk{1,2}; 67 | nbar = n*(n+1)/2; 68 | Zero = sparse(n,n); 69 | Fnorm = @(X) mexFnorm(X); 70 | %% AEmap, AETmap 71 | if existA 72 | if isstruct(A) 73 | if isfield(A,'At'); At = A.At; end 74 | if isfield(A,'Amap'); Amap0 = A.Amap; end 75 | if isfield(A,'ATmap'); ATmap0 = A.ATmap; end 76 | else 77 | At = A; 78 | Amap0 = @(X) sdpnalAXfun(blk,At,X); 79 | ATmap0 = @(y) sdpnalAtyfun(blk,At,y); 80 | end 81 | else 82 | Amap0 = @(X) []; ATmap0 = @(y) Zero; 83 | end 84 | %%% 85 | if ~exist('X','var'); X = Zero; end 86 | if ~exist('yE','var'); yE = zeros(length(b),1); end 87 | if ~exist('S','var'); S = Zero; end 88 | if ~existA; yE = []; b = []; end 89 | if ~exist('Xi','var'); Xi = Zero; end 90 | if ~exist('Z','var'); Z = Zero; end 91 | %% 92 | %% initial scaling 93 | %% 94 | Atorg = At; borg = b; Horg = H; 95 | Corg = C; Lorg = L; Uorg = U; fVorg = fV; 96 | normCorg = 1 + Fnorm(Corg); 97 | normborg = 1 + norm(borg); 98 | eigsopt.issym = 1; 99 | if existA 100 | nE = length(b); 101 | normA = sum(At.*At)'; 102 | normA = max(1,sqrt(normA)); 103 | DA = spdiags(1./normA,0,nE,nE); 104 | At = At*DA; 105 | b = DA*b; 106 | normAt = Fnorm(At); 107 | Amap = @(X) Amap0(X)./normA; 108 | ATmap = @(y) ATmap0(y./normA); 109 | AATmap = @(y) Amap(ATmap(y)); 110 | if strcmp(AEsolver,'sparse_chol') 111 | [LAAt,AAt] = mycholAAt(At,nE); 112 | dd = diag(AAt); 113 | if (Fnorm(AAt-speye(nE)) < 1e-12) 114 | if printyes; fprintf('\n AEAEt is identity '); end %% For BIQ, FAP and Theta(+) problems 115 | LAAt.isidentity = true; 116 | elseif (Fnorm(AAt-spdiags(dd,0,nE,nE)) < 1e-15*norm(dd)) 117 | fprintf('\n AAt is diagonal '); 118 | LAAt.isidentity = false; 119 | else 120 | LAAt.isidentity = false; 121 | end 122 | AEsolve = @(rhs) mylinsysolve(LAAt,rhs); 123 | if printyes; fprintf('\n AEAEt solved by chol decompostion'); end 124 | elseif strcmp(AEsolver,'pcg') 125 | rr = min(6,nE); 126 | [VA,dA,flagA] = eigs(AATmap,nE,rr,'LA',eigsopt); 127 | dA = diag(dA); rr = sum(dA>0); 128 | pcgA = min(3,rr); 129 | parA.V = VA(:,1:pcgA); parA.Vt = parA.V'; 130 | parA.d = dA(1:pcgA); 131 | parA.precond = 2; 132 | if printyes; fprintf('\n using pcg to solve AEAEt'); end 133 | end 134 | else 135 | Amap = @(X) []; ATmap = @(y) Zero; 136 | normA = []; DA = []; nE = 0; 137 | end 138 | 139 | if (scale_data == 1) 140 | bscale = max(1,norm(b)); 141 | Cscale = max(1,Fnorm(C)); 142 | elseif scale_data == 0 143 | bscale = 1; 144 | Cscale = 1; 145 | end 146 | b = b/bscale; C = C/Cscale; 147 | X = X/bscale; Z = Z/Cscale; 148 | L = L/bscale; U = U/bscale; fV = fV/bscale; 149 | yE = (normA.*yE)/Cscale; 150 | S = S/Cscale; 151 | objscale = bscale*Cscale; 152 | Xi = Xi/sqrt(objscale); 153 | 154 | if printyes 155 | fprintf('\n *******************************************************'); 156 | fprintf('******************************************'); 157 | fprintf('\n \t\t SCB_NCMP with beginning gamma = %6.3f', gamma); 158 | fprintf('\n ******************************************************'); 159 | fprintf('*******************************************\n'); 160 | if printminoryes 161 | fprintf('\n n = %3.0f, mE = %3.0f',n, nE); 162 | fprintf('\n scale_data = %2.0f', scale_data); 163 | fprintf('\n bscale = %3.2e, cscale = %3.2e', bscale, Cscale); 164 | fprintf('\n ---------------------------------------------------'); 165 | end 166 | fprintf('\n iter| pinforg dinforg relgaporg| pobj dobj |'); 167 | fprintf(' time | sigma |rankS, minspeed|gamma|'); 168 | end 169 | %%------------------------------------------------------------------- 170 | %% start main solver 171 | % parameters for main solver 172 | parmain.existA = existA; 173 | parmain.bscale = bscale; parmain.Cscale = Cscale; parmain.objscale = objscale; 174 | parmain.AEsolver = AEsolver; 175 | parmain.DA = DA; 176 | parmain.nE = nE; parmain.n = n; 177 | 178 | parmain.nonnegative = nonnegative; parmain.L = L; parmain.U = U; 179 | parmain.SignP = SignP; parmain.fV = fV; 180 | 181 | parmain.normA = normA; 182 | parmain.normAt = normAt; 183 | parmain.normborg = normborg; 184 | parmain.normCorg = normCorg; 185 | 186 | parmain.sigma = sigma; 187 | parmain.gamma = gamma; 188 | parmain.tstart= tstart; 189 | parmain.maxiter = maxiter; 190 | parmain.rescale = rescale; 191 | parmain.feasiconst = feasiconst; 192 | parmain.rhsconst = rhsconst; 193 | parmain.stoptol = stoptol; 194 | parmain.printyes = printyes; 195 | parmain.sGS = sGS; 196 | parmain.gamma_reset_start = gamma_reset_start; 197 | parmain.sig_fix = sig_fix; 198 | parmain.stopoption = stopoption; 199 | parmain.tolconst = tolconst; 200 | 201 | if strcmp(AEsolver,'pcg'); 202 | parmain.parA = parA; 203 | elseif strcmp(AEsolver,'sparse_chol'); 204 | parmain.AEsolve = AEsolve; 205 | end 206 | 207 | Ainput.Amap = Amap; Ainput.ATmap = ATmap; Ainput.AATmap = AATmap; 208 | % main file of SCB ADMM for solving NCM problem with \cP 209 | [X,Z,yE,S,Xi,info_main,runhist] = ... 210 | SCB_NCMPmain(Horg,Ainput,b,C,parmain,X,Z,yE,S,Xi); 211 | 212 | % information 213 | iter = info_main.iter; 214 | msg = info_main.msg; 215 | bscale = info_main.bscale; 216 | Cscale = info_main.Cscale; 217 | breakyes = info_main.breakyes; 218 | iterProj = info_main.iterProj; 219 | repeatyE = info_main.repeatyE; 220 | repeatQ = info_main.repeatQ; 221 | sigma = info_main.sigma; 222 | Ztmp = info_main.Ztmp; 223 | if phase2 224 | b = info_main.b; normb = info_main.normb; 225 | C = info_main.C; normC = info_main.normC; 226 | H = info_main.H; 227 | end 228 | %%----------------------------------------------------------------- 229 | %% recover orignal variables 230 | %%----------------------------------------------------------------- 231 | if (iter == maxiter) 232 | msg = ' maximum iteration reached'; 233 | info.termcode = 3; 234 | end 235 | X = X*bscale; normX = norm(X,'fro'); 236 | HX = Horg.*X; 237 | yE = Cscale*(DA*yE); 238 | Z = Cscale*Z; normZ = norm(Z,'fro'); Ztmp = Ztmp*bscale; 239 | S = Cscale*S; normS = norm(S,'fro'); 240 | Xi = sqrt(bscale*Cscale)*Xi; 241 | HXi = Horg.*Xi; 242 | if existA; bTyE = borg'*yE; end 243 | AX = Amap0(X); AtyE = ATmap0(yE); 244 | primobj = 0.5*Fnorm(HX)^2 + sum(sum(Corg.*X)); 245 | dualobj = sum(sum(Z.*Ztmp)) + bTyE - 0.5*Fnorm(Xi)^2; 246 | obj = [primobj,dualobj]; 247 | etaQ = Fnorm(Horg.*(Xi+HX))/(1+Fnorm(Horg)^2); 248 | if (true) 249 | etaSp = compnormXn(X) /(1+normX); 250 | etaSc = full(abs(sum(sum(X.*S))) /(1+normX +normS)); 251 | etaS = max(etaSp,etaSc); 252 | projPX = proj_LU_new(X,nonnegative,SignP,Lorg,Uorg,fVorg); 253 | etaZp = Fnorm(X-projPX)/(1 + normX); 254 | ZtmX = Ztmp - X; 255 | normZtmX = norm(ZtmX,'fro'); 256 | trZtmX = full(abs(sum(sum(ZtmX.*Z)))); 257 | etaZc = trZtmX/(1 + normZ + normZtmX); 258 | etaZ = max(etaZp,etaZc); 259 | end 260 | etab = norm(AX-borg)/normborg; 261 | primfeasorg = max(etab); 262 | dualfeasorg = max(norm(Z+HXi+S+AtyE-Corg,'fro')/normCorg); 263 | ttime = etime(clock,tstart); 264 | runhist.nE = nE; 265 | runhist.ns = n; 266 | runhist.iter = iter; 267 | runhist.totaltime = ttime; 268 | runhist.primobjorg = primobj; 269 | runhist.dualobjorg = dualobj; 270 | runhist.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 271 | runhist.primfeasorg(iter) = primfeasorg; 272 | runhist.dualfeasorg(iter) = dualfeasorg; 273 | runhist.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 274 | info.nE = nE; 275 | info.ns = n; 276 | info.iter = iter; 277 | info.totaltime = ttime; 278 | info.primobjorg = primobj; 279 | info.dualobjorg = dualobj; 280 | info.relgaporg = (primobj-dualobj)/(1+abs(primobj)+abs(dualobj)); 281 | info.etaZ = etaZ; 282 | info.etaS = etaS; 283 | info.primfeasorg = primfeasorg; info.dualfeasorg = dualfeasorg; 284 | info.etaQ = etaQ; 285 | info.etab = etab; 286 | info.relerr = max([dualfeasorg,primfeasorg,etaS,etaQ]); 287 | info.minX = min(min(X)); 288 | info.maxX = max(max(X)); 289 | info.psqmrA1 = sum(runhist.psqmrA1); 290 | info.psqmrA2 = sum(runhist.psqmrA2); 291 | %% added for Phase II 292 | if phase2 293 | info.nXi = nbar; 294 | info.Amap = Amap; info.ATmap = ATmap; 295 | info.bscale = bscale; info.Cscale = Cscale; 296 | info.sigma = sigma; 297 | info.AAt = AAt; 298 | info.AEsolve = AEsolve; 299 | if exist('At','var'); info.At = At; end 300 | info.normA = normA; info.DA = DA; info.normAt = normAt; 301 | info.b = b; info.normb = normb; info.C = C; info.normC = normC; 302 | info.H = H; info.Ztmp = Ztmp; 303 | info.breakyes = breakyes; 304 | end 305 | if (printminoryes) 306 | if ~isempty(msg); fprintf('\n %s',msg); end 307 | fprintf('\n--------------------------------------------------------------'); 308 | fprintf('------------------'); 309 | fprintf('\n number iter = %2.0d',iter); 310 | fprintf('\n number of iterProj = %2.0f',iterProj); 311 | fprintf('\n number iter = %2.0d \t repeaty= %d ',... 312 | iter,repeatyE); 313 | fprintf('\t repeatQ= %d ',... 314 | iter,repeatQ); 315 | if existA && strcmp(AEsolver,'pcg') 316 | fprintf('\n number of PSQMRiterA for 1st system = %2.0f',info.psqmrA1); 317 | fprintf('\n number of PSQMRiterA for 2nd system = %2.0f',info.psqmrA2); 318 | end 319 | fprintf('\n time = %3.2f',ttime); 320 | fprintf('\n time per iter = %5.4f',ttime/iter); 321 | fprintf('\n primobj = %9.8e',runhist.primobjorg); 322 | fprintf('\n dualobj = %9.8e',runhist.dualobjorg); 323 | fprintf('\n primfeas = %3.2e, dualfeas = %3.2e, relgap = %3.2e',... 324 | runhist.primfeas(end),runhist.dualfeas(end),runhist.relgap(end)); 325 | fprintf('\n primfeasorg = %3.2e, dualfeasorg = %3.2e, relgaporg = %3.2e',... 326 | runhist.primfeasorg(end),runhist.dualfeasorg(end),runhist.relgaporg(end)); 327 | fprintf('\n etaQ = %3.2e', etaQ); fprintf(' etaS = %3.2e', etaS); 328 | fprintf('\n etab = %3.2e', etab); fprintf(' etaZ = %3.2e', etaZ); 329 | fprintf('\n min(X) = %3.2e, max(X) = %3.2e',... 330 | info.minX,info.maxX); 331 | fprintf('\n sigma = %3.1e',sigma); 332 | fprintf('\n--------------------------------------------------------------'); 333 | fprintf('------------------\n'); 334 | end 335 | %%********************************************************************** 336 | %% solve A*q = r. 337 | %%********************************************************************** 338 | function q = mylinsysolve(L,r) 339 | 340 | if (L.isidentity) 341 | q = r; 342 | else 343 | if strcmp(L.matfct_options,'chol') 344 | q(L.perm,1) = mextriang(L.R, mextriang(L.R,r(L.perm),2) ,1); 345 | elseif strcmp(L.matfct_options,'spcholmatlab') 346 | q(L.perm,1) = mexbwsolve(L.Rt,mexfwsolve(L.R,r(L.perm,1))); 347 | end 348 | end 349 | %%********************************************************************** 350 | 351 | %%********************************************************************** 352 | function normXn = compnormXn(X) 353 | 354 | d = eig(full(X)); 355 | normXn = norm(d(d<0)); 356 | %%********************************************************************** 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | -------------------------------------------------------------------------------- /QSDPNAL_main/submain/Nalmain.p/nal_LSImain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/Nalmain.p/nal_LSImain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/Nalmain.p/nal_LSmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/Nalmain.p/nal_LSmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/Nalmain.p/nal_NCMPmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/Nalmain.p/nal_NCMPmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/Nalmain.p/nal_NCMmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/Nalmain.p/nal_NCMmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/Nalmain.p/nal_qsdpBIQmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/Nalmain.p/nal_qsdpBIQmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/Nalmain.p/nal_qsdpQAPmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/Nalmain.p/nal_qsdpQAPmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SCBmain.p/SCB_LSImain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SCBmain.p/SCB_LSImain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SCBmain.p/SCB_LSmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SCBmain.p/SCB_LSmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SCBmain.p/SCB_NCMPmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SCBmain.p/SCB_NCMPmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SCBmain.p/SCB_NCMmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SCBmain.p/SCB_NCMmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SCBmain.p/SCB_qsdpmain.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SCBmain.p/SCB_qsdpmain.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SNCG.p/ssncgABtest.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SNCG.p/ssncgABtest.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SNCG.p/ssncgLS1.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SNCG.p/ssncgLS1.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SNCG.p/ssncgLSI1.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SNCG.p/ssncgLSI1.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SNCG.p/ssncgNCM2.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SNCG.p/ssncgNCM2.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SNCG.p/ssncgNCM3.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SNCG.p/ssncgNCM3.p -------------------------------------------------------------------------------- /QSDPNAL_main/submain/SNCG.p/ssncgQSDP.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/QSDPNAL_main/submain/SNCG.p/ssncgQSDP.p -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## QSDPNAL version 0.1 -- a MATLAB software for convex quadratic semidefinite programming 2 | 3 | ### [Xudong Li](http://lixudong.info), [Defeng Sun](https://www.polyu.edu.hk/ama/profile/dfsun/), [Kim-Chuan Toh](https://blog.nus.edu.sg/mattohkc/) 4 | 5 | This software is designed to solve convex quadratic SDP of the form: 6 | 7 | min 1/2 + subject to A(X)=b, B(X)>=d, L <= X <= U, X is PSD 8 | 9 | ### Citation 10 | 11 | - **Xudong Li, Defeng Sun, and Kim-Chuan Toh**, QSDPNAL: A two-phase augmented Lagrangian method for convex quadratic semidefinite programming, Mathematical Programming Computation, 10 (2018), pp. 703--743. 12 | 13 | ------------- 14 | 15 | - **Important note**: 16 | - The software is still under development. Thus it will invariably be buggy. We would appreciate your feedback and bugs’ report. 17 | - This is a research software. It is not intended nor designed to be a general purpose software at the moment. 18 | 19 | ----- 20 | 21 | ### Copyright 22 | This version of QSDPNAL is distributed under the **3-Clause BSD license**. For commercial applications that may be incompatible with this license, please contact the authors to discuss alternatives. 23 | 24 | ----------- 25 | 26 | ### Installation 27 | 28 | Welcome to QSDPNAL! Users can simply follow the steps below to install QSDPNAL within Matlab: 29 | 30 | - Firstly, clone the package via 31 | ```github 32 | git clone https://github.com/MatOpt/QSDPNAL.git 33 | ``` 34 | - Run Matlab in the directory QSDPNAL 35 | - In Matlab command window, type: 36 | ```matlab 37 | >> startup 38 | >> qsdpnaldemo 39 | ``` 40 | - By now, QSDPNAL is ready for you to use. 41 | - If you have issues with MEX files on macOS (“ “*.mexmaci64” cannot be opened because the developer cannot be verified. macOS cannot verify that this app is free from malware” or “Code signature not valid for use in process using Library Validation: library load disallowed by system policy”), open a Terminal, cd to the QSDPNAL directory and type: 42 | 43 | `find . -name "*.mexmaci64" -exec xattr -d com.apple.quarantine {} \;` 44 | 45 | - The **User's guide** is included in the [Appendix of our paper](https://link.springer.com/article/10.1007/s12532-018-0137-6). 46 | 47 | --------------- 48 | - Codes in the folder QSDPNAL_main\NAL are for Algorithm QSDPNAL (QSDPNAL-Phase II with QSDPNAL-Phase I to generate initial point) 49 | 50 | - Codes in the folder QSDPNAL_main\SCB are for Algorithm QSDPNAL-Phase I (SCB_ADMM: an SCB based inexact semi-proximal ADMM) 51 | 52 | - Codes in the folder QSDPNAL_main\submain\SNCG are used for solving subproblems (i.e., Algorithms SSNCG and ABCD) 53 | -------------------------------------------------------------------------------- /datafiles/2d250n10nf.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/datafiles/2d250n10nf.mat -------------------------------------------------------------------------------- /datafiles/3d250n10nf.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/datafiles/3d250n10nf.mat -------------------------------------------------------------------------------- /datafiles/ER.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/datafiles/ER.mat -------------------------------------------------------------------------------- /datafiles/Lymph.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/datafiles/Lymph.mat -------------------------------------------------------------------------------- /datafiles/chr15c.dat: -------------------------------------------------------------------------------- 1 | 15 2 | 3 | 0 12 86 0 0 0 0 0 0 0 0 0 0 0 0 4 | 12 0 0 68 0 0 0 0 0 0 0 0 0 0 0 5 | 86 0 0 0 69 0 0 0 0 0 0 0 0 0 0 6 | 0 68 0 0 0 34 0 0 0 0 0 0 0 0 0 7 | 0 0 69 0 0 0 35 0 0 0 0 0 0 0 0 8 | 0 0 0 34 0 0 0 19 0 0 0 0 0 0 0 9 | 0 0 0 0 35 0 0 0 2 0 0 0 0 0 0 10 | 0 0 0 0 0 19 0 0 0 21 0 0 0 0 0 11 | 0 0 0 0 0 0 2 0 0 0 88 0 0 0 0 12 | 0 0 0 0 0 0 0 21 0 0 0 79 0 0 0 13 | 0 0 0 0 0 0 0 0 88 0 0 0 3 0 0 14 | 0 0 0 0 0 0 0 0 0 79 0 0 0 40 0 15 | 0 0 0 0 0 0 0 0 0 0 3 0 0 0 77 16 | 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 17 | 0 0 0 0 0 0 0 0 0 0 0 0 77 0 0 18 | 19 | 0 84 81 10 40 39 5 83 10 78 88 74 88 16 21 20 | 84 0 39 67 62 38 3 16 43 47 70 97 4 17 34 21 | 81 39 0 53 12 50 98 94 4 16 24 17 20 38 60 22 | 10 67 53 0 43 90 84 60 50 43 46 80 53 20 1 23 | 40 62 12 43 0 86 18 1 28 14 58 34 2 3 55 24 | 39 38 50 90 86 0 58 92 90 62 99 93 64 50 83 25 | 5 3 98 84 18 58 0 53 93 69 98 27 19 50 86 26 | 83 16 94 60 1 92 53 0 30 35 39 55 25 12 41 27 | 10 43 4 50 28 90 93 30 0 16 10 96 7 11 52 28 | 78 47 16 43 14 62 69 35 16 0 28 13 97 63 91 29 | 88 70 24 46 58 99 98 39 10 28 0 94 91 44 62 30 | 74 97 17 80 34 93 27 55 96 13 94 0 48 36 11 31 | 88 4 20 53 2 64 19 25 7 97 91 48 0 69 80 32 | 16 17 38 20 3 50 50 12 11 63 44 36 69 0 41 33 | 21 34 60 1 55 83 86 41 52 91 62 11 80 41 0 34 | 35 | 36 | -------------------------------------------------------------------------------- /datafiles/divergentGH.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/datafiles/divergentGH.mat -------------------------------------------------------------------------------- /mexfun/mexFnorm.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexFnorm.mexa64 -------------------------------------------------------------------------------- /mexfun/mexFnorm.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexFnorm.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexFnorm.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexFnorm.mexw64 -------------------------------------------------------------------------------- /mexfun/mexbwsolve.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexbwsolve.mexa64 -------------------------------------------------------------------------------- /mexfun/mexbwsolve.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexbwsolve.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexbwsolve.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexbwsolve.mexw64 -------------------------------------------------------------------------------- /mexfun/mexeig.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexeig.mexa64 -------------------------------------------------------------------------------- /mexfun/mexeig.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexeig.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexeig.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexeig.mexw64 -------------------------------------------------------------------------------- /mexfun/mexeigPartial.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexeigPartial.mexa64 -------------------------------------------------------------------------------- /mexfun/mexeigPartial.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexeigPartial.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexeigPartial.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexeigPartial.mexw64 -------------------------------------------------------------------------------- /mexfun/mexfwsolve.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexfwsolve.mexa64 -------------------------------------------------------------------------------- /mexfun/mexfwsolve.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexfwsolve.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexfwsolve.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexfwsolve.mexw64 -------------------------------------------------------------------------------- /mexfun/mexmat.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexmat.mexa64 -------------------------------------------------------------------------------- /mexfun/mexmat.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexmat.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexmat.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexmat.mexw64 -------------------------------------------------------------------------------- /mexfun/mexnnz.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexnnz.mexa64 -------------------------------------------------------------------------------- /mexfun/mexnnz.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexnnz.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexnnz.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexnnz.mexw64 -------------------------------------------------------------------------------- /mexfun/mexsmat.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexsmat.mexa64 -------------------------------------------------------------------------------- /mexfun/mexsmat.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexsmat.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexsmat.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexsmat.mexw64 -------------------------------------------------------------------------------- /mexfun/mexsvec.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexsvec.mexa64 -------------------------------------------------------------------------------- /mexfun/mexsvec.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexsvec.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mexsvec.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mexsvec.mexw64 -------------------------------------------------------------------------------- /mexfun/mextriang.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mextriang.mexa64 -------------------------------------------------------------------------------- /mexfun/mextriang.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mextriang.mexmaci64 -------------------------------------------------------------------------------- /mexfun/mextriang.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/mexfun/mextriang.mexw64 -------------------------------------------------------------------------------- /qsdpdemo.m: -------------------------------------------------------------------------------- 1 | %% demo for QSDPNAL for solving QSDP-BIQ, QSDP-QAP, LS, LSI, NCM and NCMP problems 2 | 3 | clear all 4 | startup 5 | 6 | BIQ = 1; 7 | QAP = 1; 8 | LS = 1; 9 | LSI = 1; 10 | NCM = 1; 11 | NCMP= 1; 12 | 13 | %% Solve QSDP-BIQ 14 | %% P): min 1/2 + , s.t., AE X = bE, B X >= d, X >= 0, X \in K 15 | %% where K = psd cone 16 | if BIQ 17 | G = biqread(['be250.2.sparse']); 18 | [blk,AEt,C,bE,AIt,bI] = biq_sqsdp(G,3); 19 | Q.QXfun = @(X) randQXfun(X,blk{1,2}); 20 | options.nonnegative = 1; 21 | fprintf('\n #######################################'); 22 | fprintf('\n ****************** %s ************','be250.2'); 23 | fprintf('\n #######################################'); 24 | [obj,Z,W,QW,S,yE,yI,X,runhist,info] = ... 25 | qsdpnal(blk,Q,AEt,bE,C,AIt,bI,options); 26 | %[obj,Z,W,QW,S,yE,yI,X,runhist,info] = qsdpnal_BIQ(blk,Q,AEt,bE,C,AIt,bI,options); 27 | clear blk Q AEt bE C AIt bI options 28 | clear obj Z W QW S yE yI X runhist info 29 | end 30 | 31 | %% Solve QSDP-QAP 32 | %% P): min 1/2 + , s.t., AE X = bE, B X >= d, X >= 0, X \in K 33 | %% where K = psd cone 34 | if QAP 35 | [AA,BB] = qapread(['chr15c.dat']); 36 | [blk,AEt,C,bE] = qapAW(AA,BB,2); 37 | AEt = AEt{1}; C = C{1}; 38 | AIt = []; bI = []; 39 | options.nonnegative = 1; 40 | Q.QXfun = @(X) randQXfun(X,blk{1,2}); 41 | fprintf('\n ######################################'); 42 | fprintf('\n ****************** %s ************','chr15c'); 43 | fprintf('\n ######################################'); 44 | [obj,Z,W,QW,S,yE,yI,X,runhist,info] = qsdpnal(blk,Q,AEt,bE,C,AIt,bI,options); 45 | %[obj,Z,W,QW,S,yE,yI,X,runhist,info] = qsdpnal_QAP(blk,Q,AEt,bE,C,AIt,bI,options); 46 | clear blk Q AEt bE C AIt bI options 47 | clear obj Z W QW S yE yI X runhist info 48 | end 49 | 50 | %% Solve least squares 51 | %% (P) min {1/2||H(X)||_F^2 + | A(X)=b , X \in K} 52 | %% where K = psd cone 53 | 54 | if LS 55 | load('2d250n10nf.mat'); 56 | Hinput = Bt; 57 | fprintf('\n ######################################'); 58 | fprintf('\n ****************** %s ************','2d250n10nf'); 59 | fprintf('\n ######################################'); 60 | options.Qsolver = 'pcg'; 61 | [obj,xi,S,yE,X,runhist,info] = ... 62 | LSnal(blk,Hinput,At,b,C,options); 63 | clear blk Hinput At b C options 64 | clear obj xi S yE X runhist info 65 | end 66 | 67 | %% Solve least squares with inequality constraints 68 | %% (P) min {1/2||H(X)||_F^2 + | A(X)=b, B(X)>=d, X \in K} 69 | %% where K = psd cone 70 | 71 | if LSI 72 | load('3d250n10nf.mat'); 73 | Hinput = Bt; 74 | fprintf('\n ######################################'); 75 | fprintf('\n ****************** %s ************','3d250n10nf'); 76 | fprintf('\n ######################################'); 77 | options.Qsolver = 'pcg'; 78 | [obj,xi,S,yE,yI,X,runhist,info] = ... 79 | LSnalI(blk,Hinput,At,b,AIt,bI,C,options); 80 | clear blk Hinput At b AIt bI C options 81 | clear obj xi S yE yI X runhist info 82 | end 83 | 84 | %% Solve the NCM problem 85 | %% (P) min {1/2||H o X||_F^2 + | A(X)=b, X \in K} 86 | %% where K = psd cone 87 | 88 | if NCM 89 | options = []; 90 | load divergentGH.mat; 91 | tmp0 = ones(110,110); 92 | H0 = kron(tmp0,H); 93 | alpha = 0.1; 94 | load('Lymph.mat','S'); 95 | n = length(S); 96 | H = H0([1:n],[1:n]); 97 | H = (H+H')/2; 98 | G = S([1:n],[1:n]); 99 | clear S; 100 | E = 2*rand(n)-1; 101 | E = triu(E) + triu(E,1)'; 102 | E = 0.5*(E + E'); 103 | G = (1-alpha)*G + alpha*E; 104 | G = 0.5*(G+G'); 105 | G = G - diag(diag(G)) + eye(n); 106 | Hscale = sqrt(norm(H.*H.*G,'fro')); 107 | H = H/(Hscale); 108 | H2 = H.*H; 109 | type = 1; 110 | [blk,At,~,b,~,~] = NCM_Hnorm(G,H,type); 111 | C = zeros(blk{1,2}); 112 | C = C - H2.*G; 113 | X0 = G; 114 | fprintf('\n #######################################'); 115 | fprintf('\n ****************** %s ************','Lymph'); 116 | fprintf('\n #######################################'); 117 | 118 | [obj,Xi,S,yE,X,runhist,info] = qsdpnal_NCM(blk,H,At,b,C,options,X0); 119 | clear blk H At b C options X0 120 | clear obj Xi S yE X runhist info 121 | end 122 | 123 | %% Solve the NCM problem 124 | %% (P) min {1/2||H o X||_F^2 + | A(X)=b, X \in K, X\in P} 125 | %% where K = psd cone, P is ployhedral set e.g., P = {X | L<= X <= U}. 126 | if NCMP 127 | load divergentGH.mat; 128 | tmp0 = ones(110,110); 129 | H0 = kron(tmp0,H); 130 | alpha = 0.05; 131 | load('ER.mat','S'); 132 | n = length(S); 133 | H = H0([1:n],[1:n]); 134 | H = (H+H')/2; 135 | G = S([1:n],[1:n]); 136 | clear S; 137 | E = 2*rand(n)-1; 138 | E = triu(E) + triu(E,1)'; 139 | E = 0.5*(E + E'); 140 | G = (1-alpha)*G + alpha*E; 141 | G = 0.5*(G+G'); 142 | G = G - diag(diag(G)) + eye(n); 143 | Hscale = sqrt(norm(H.*H.*G,'fro')); 144 | H = H/(Hscale); 145 | H2 = H.*H; 146 | type = 1; 147 | [blk,At,~,b,~,~] = NCM_Hnorm(G,H,type); 148 | C = zeros(blk{1,2}); 149 | C = C - H2.*G; 150 | options.lowerbound = -.5; % Lower bound indices, i.e., X >= -0.5 151 | SignP.L = 1*ones(n); 152 | options.SignP = SignP; 153 | X0 = G; 154 | fprintf('\n #######################################'); 155 | fprintf('\n ****************** %s ************','ER'); 156 | fprintf('\n #######################################'); 157 | [obj,Z,Xi,S,yE,X,runhist,info] = qsdpnal_NCMP(blk,H,At,b,C,options,X0); 158 | clear blk H At b C options X0 159 | clear obj Z Xi S yE X runhist info 160 | end 161 | 162 | 163 | -------------------------------------------------------------------------------- /solvers.p/bicgQAB.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/bicgQAB.p -------------------------------------------------------------------------------- /solvers.p/diagABPi.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/diagABPi.p -------------------------------------------------------------------------------- /solvers.p/diagAPi.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/diagAPi.p -------------------------------------------------------------------------------- /solvers.p/diagHABPi.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/diagHABPi.p -------------------------------------------------------------------------------- /solvers.p/diagapproxsym.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/diagapproxsym.p -------------------------------------------------------------------------------- /solvers.p/matvecA.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecA.p -------------------------------------------------------------------------------- /solvers.p/matvecAB.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecAB.p -------------------------------------------------------------------------------- /solvers.p/matvecHA.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecHA.p -------------------------------------------------------------------------------- /solvers.p/matvecHALS.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecHALS.p -------------------------------------------------------------------------------- /solvers.p/matvecLSHAB.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecLSHAB.p -------------------------------------------------------------------------------- /solvers.p/matvecLSyI.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecLSyI.p -------------------------------------------------------------------------------- /solvers.p/matvecQAB.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecQAB.p -------------------------------------------------------------------------------- /solvers.p/matvecxi.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecxi.p -------------------------------------------------------------------------------- /solvers.p/matvecyE.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecyE.p -------------------------------------------------------------------------------- /solvers.p/matvecyI.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/matvecyI.p -------------------------------------------------------------------------------- /solvers.p/mycholAAt.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/mycholAAt.p -------------------------------------------------------------------------------- /solvers.p/projSDP.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/projSDP.p -------------------------------------------------------------------------------- /solvers.p/proj_LU_new.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/proj_LU_new.p -------------------------------------------------------------------------------- /solvers.p/projectSDP2.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/projectSDP2.p -------------------------------------------------------------------------------- /solvers.p/psqmrAB.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/psqmrAB.p -------------------------------------------------------------------------------- /solvers.p/psqmrLSHAB.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/psqmrLSHAB.p -------------------------------------------------------------------------------- /solvers.p/psqmrQW.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/psqmrQW.p -------------------------------------------------------------------------------- /solvers.p/psqmry.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/psqmry.p -------------------------------------------------------------------------------- /solvers.p/sdpnalAXfun.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/sdpnalAXfun.p -------------------------------------------------------------------------------- /solvers.p/sdpnalAtyfun.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/sdpnalAtyfun.p -------------------------------------------------------------------------------- /solvers.p/smat.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/smat.p -------------------------------------------------------------------------------- /solvers.p/svec.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatOpt/QSDPNAL/c28ffad19cd6bd2ac25c86eda4a009b88e2f2adf/solvers.p/svec.p -------------------------------------------------------------------------------- /startup.m: -------------------------------------------------------------------------------- 1 | %% 2 | Home = pwd; 3 | addpath(genpath(Home)); 4 | %% 5 | %% 6 | set(0,'defaultaxesfontsize',14); 7 | set(0,'defaultlinemarkersize',6); 8 | set(0,'defaulttextfontsize',14); 9 | %%************************************************************************* 10 | -------------------------------------------------------------------------------- /util/NCM_Hnorm.m: -------------------------------------------------------------------------------- 1 | %%***************************************************** 2 | %% NCM: nearest correlation matrix 3 | %% type1 : diag(X) = e 4 | %% type2 : Xe = e 5 | %% type3 : diag(X) = e, Xe = e 6 | %% 7 | %% W = a nonnegative weight matrix. 8 | %%***************************************************** 9 | 10 | function [blk,At,C,b,L,U] = NCM_Hnorm(G,H,type) 11 | 12 | n = length(G); 13 | HG = H.*G; 14 | normHG = norm(HG,'fro'); 15 | 16 | C = randn(n); 17 | C = C*normHG^2/norm(C,'fro'); 18 | C = (C+C')/2; 19 | 20 | blk{1,1} = 's'; blk{1,2} = n; 21 | 22 | Acelltmp = cell(1,2*n); JJ = [1:n]'; 23 | for k = 1:n; 24 | Acelltmp{k} = spconvert([k,k,1;n,n,0]); 25 | II = k*ones(n,1); 26 | tmp = spconvert([II, JJ, ones(n,1); n, n, 0]); 27 | tmp = 0.5*(tmp + tmp'); 28 | tmp(k,k) = 1; 29 | Acelltmp{k+n} = tmp; 30 | end 31 | if type == 1 32 | Acell = Acelltmp(1,1:n); 33 | b = ones(n,1); 34 | elseif type == 2 35 | Acell = Acelltmp(1,n+1:2*n); 36 | b = ones(n,1); 37 | elseif type == 3 38 | Acell = Acelltmp; 39 | b = ones(2*n,1); 40 | end 41 | 42 | Atmp = svec(blk(1,:),Acell,1); 43 | At = Atmp{1}; 44 | 45 | 46 | 47 | 48 | L = 0.7*min(min(G)); 49 | U = 1.2*max(max(G)); 50 | 51 | %%***************************************************** 52 | -------------------------------------------------------------------------------- /util/QXfun_corr.m: -------------------------------------------------------------------------------- 1 | 2 | function axb=QXfun_corr(L1,D1,L2,D2,x) 3 | 4 | ax=D1*x+L1'*(L1*x); 5 | axb=ax*D2+(ax*(L2'))*L2; 6 | axb=(axb+axb')/2; 7 | 8 | end -------------------------------------------------------------------------------- /util/Qfun_stein.m: -------------------------------------------------------------------------------- 1 | %% function stein transformation 2 | %% Q(X) = X - AXA where A = D + L'*L; 3 | %%************************************************ 4 | 5 | function QX = Qfun_stein(L,D,X,A) 6 | if nargin > 3 7 | AX = A*X; 8 | QX = AX*A; 9 | else 10 | AX = D*X + L'*(L*X); 11 | AXA = AX*D + (AX*(L'))*L; 12 | QX = AXA; 13 | QX = 0.5*(QX + QX'); 14 | end 15 | -------------------------------------------------------------------------------- /util/biq_sqsdp.m: -------------------------------------------------------------------------------- 1 | %%****************************************************** 2 | %% biq: generate SDP data for binary quadratic 3 | %% programming 4 | %% 5 | %% X = [Y,y; y', 1]; 6 | %%****************************************************** 7 | 8 | function [blk,A,C,b,B,d] = biq_sqsdp(Q,options) 9 | 10 | if (nargin == 1); options = 0; end; 11 | if isempty(Q) 12 | blk = []; C = []; b = []; 13 | A =[]; B = []; d = []; 14 | return; 15 | end 16 | if norm(Q-Q','fro') 17 | Q = 0.5*(Q + Q'); 18 | end 19 | B =[]; d=[]; 20 | n = size(Q,1); 21 | blk{1,1} = 's'; blk{1,2} = n+1; 22 | %% 23 | %% 24 | %% 25 | C = [Q,sparse(n,1); sparse(1,n+1)]; 26 | %% 27 | %% diag(Y) = y; 28 | %% 29 | 30 | n1 = n+1; 31 | Acell = cell(1,n1); 32 | for k = 1:n 33 | Acell{k} = spconvert([k,k,1;k,n1,-0.5; n1,k,-0.5;n1,n1,0]); 34 | end 35 | Acell{n1} = spconvert([n1,n1,1]); 36 | At = svec(blk,Acell,1); 37 | b = [zeros(n,1); 1]; 38 | At = At{1}; 39 | A.At = At; 40 | A.Amap = @(X) diag(X) - [X(1:end-1,end);0]; 41 | A.ATmap = @(y) ATmap(y); 42 | % n1 = n+1; 43 | % Acell = cell(1,n); 44 | % for k = 1:n 45 | % Acell{k} = spconvert([k,k,1;k,n1,-0.5; n1,k,-0.5;n1,n1,0]); 46 | % end 47 | % At = svec(blk,Acell,1); 48 | % 49 | % b = zeros(n,1); 50 | % 51 | % At = At{1}; 52 | % A.At = At; 53 | % A.Amap = @(X) diag(X(1:end-1,1:end-1)) - X(1:end-1,end); 54 | % %A.Amap = @(X) diag(X{1}) - [X{1}(1:end-1,end);0]; 55 | % A.ATmap = @(y) ATmap(y); 56 | %% alpha = 1; 57 | % projop.idx = n1^2; 58 | % projop.v = 1; 59 | % SignP = zeros(n1); 60 | % idx2 = n1^2; 61 | % SignP(idx2) = 2; 62 | % fV = 1; 63 | % L = []; 64 | % U = []; 65 | % nonnegative = 1; 66 | %% 67 | % %% add the constraint >= (e'*y)^2 68 | % %% 69 | % if (options == 1) %% Not useful. 70 | % e = ones(n,1); 71 | % tmp{1,1} = [sparse(n,n), 0.5*e; 0.5*e', 0]; 72 | % tmp{1,2} = [ones(n,n), zeros(n,1); zeros(1,n), 0]; 73 | % tmp{1,3} = sparse(n+1,n+1); 74 | % Atmp = svec(blk(1,:),tmp,1); 75 | % At{1} = [At{1}, Atmp{1}]; 76 | % b = [b; 0;0;1]; 77 | % C{2,1} = zeros(3,1); 78 | % blk{2,1} = 'q'; blk{2,2} = 3; 79 | % At{2,1} = [sparse(n1,3); 0,0,-1; -1,-1,0; 1,-1,0]'; 80 | % end 81 | % %% 82 | % %% add the constraint Y_{ij} <= y_i,Y_{ij} <= y_j, Y_{ij} >= y_i + y_j - 1 to form standard SDP 83 | % %% 84 | % if (options == 2) 85 | % idx1 = [1:5:n]; 86 | % idx2 = [2:5:n]; 87 | % len1 = length(idx1); 88 | % len2 = length(idx2); 89 | % m2 = len1*len2; 90 | % Acell = cell(1,m2); 91 | % AAcell = cell(1,m2); 92 | % num = 0; 93 | % for i = idx1 94 | % for j = idx2 95 | % if j ~= i 96 | % Acell{num+1} = spconvert([i,j,-0.5;j,i,-0.5;i,n1,0.5;n1,i,0.5;n1,n1,0]); %% -Y_{ij} + y_i >= 0 97 | % AAcell{num+1} = spconvert([i,j,0.5;j,i,0.5;i,n1,-0.5;n1,i,-0.5;j,n1,-0.5;n1,j,-0.5;n1,n1,0]); %% Y_{ij} - y_i - y_j >= - 1 98 | % num = num+1; 99 | % end 100 | % end 101 | % end 102 | % m2 = num; 103 | % Acell = Acell(1:m2); 104 | % AAcell = AAcell(1:m2); 105 | % Atmp1 = svec(blk,Acell,1); 106 | % Atmp2 = svec(blk,AAcell,1); 107 | % At{1} = [At{1}, Atmp1{1}, Atmp2{1}]; 108 | % b = [b; zeros(m2,1); ones(m2,1)]; 109 | % C{2,1} = zeros(m2*2,1); 110 | % blk{2,1} = 'l'; blk{2,2} = m2*2; 111 | % At{2,1} = [sparse(m2*2,n1) speye(m2*2)]; 112 | % end 113 | %%****************************************************** 114 | %% add the constraint -Y_{ij} + y_i >= 0, -Y_{ij} + y_j >= 0, Y_{ij} - y_i - y_j >= - 1 115 | %%---- and Y_{ij}+Y{ik}+Y{jk}-y_i-y_j-y_k >= -1 116 | %% 117 | if (options == 3) 118 | idx1 = [1:1:n]; 119 | idx2 = [1:1:n]; 120 | idx3 = []; 121 | len1 = length(idx1); 122 | len2 = length(idx2); 123 | len3 = length(idx3); 124 | m2 = len1*len2; 125 | m3 = m2*len3; 126 | Acell = cell(1,m2); 127 | A1cell = cell(1,m2); 128 | AAcell = cell(1,m2); 129 | A3cell = cell(1,m3); 130 | num = 0; 131 | num1 = 0; 132 | for i = idx1 133 | for j = idx2 134 | if i < j 135 | Acell{num+1} = spconvert([i,j,-0.5;j,i,-0.5;i,n1,0.5;n1,i,0.5;n1,n1,0]); %% -Y_{ij} + y_i >= 0 136 | A1cell{num+1} = spconvert([i,j,-0.5;j,i,-0.5;j,n1,0.5;n1,j,0.5;n1,n1,0]); %% -Y_{ij} + y_j >= 0 137 | AAcell{num+1} = spconvert([i,j,0.5;j,i,0.5;i,n1,-0.5;n1,i,-0.5;j,n1,-0.5;n1,j,-0.5;n1,n1,0]); %% Y_{ij} - y_i - y_j >= - 1 138 | num = num+1; 139 | end 140 | for k = idx3 141 | if j ~= i && k ~= i && k ~= j 142 | A3cell{num1+1} = spconvert... 143 | ([i,j,1;i,k,1;j,k,1;i,n1,-0.5;n1,i,-0.5;j,n1,-0.5;n1,j,-0.5;k,n1,-0.5;n1,k,-0.5;n1,n1,0]); 144 | num1 = num1+1; 145 | end 146 | end 147 | end 148 | end 149 | m2 = num; 150 | Acell = Acell(1:m2); 151 | A1cell = A1cell(1:m2); 152 | AAcell = AAcell(1:m2); 153 | A3cell = A3cell(1:num1); 154 | Atmp1 = svec(blk,Acell,1); 155 | A1tmp1 = svec(blk,A1cell,1); 156 | Atmp2 = svec(blk,AAcell,1); 157 | Atmp3 = svec(blk,A3cell,1); 158 | Bt = [Atmp1{1}, A1tmp1{1}, Atmp2{1}]; 159 | d = [zeros(m2*2,1); -ones(m2,1);]; 160 | B = Bt; 161 | % B.Bt = Bt; 162 | % B.Bmap = @(X) (mexsvec(blk,X)'*Bt)'; 163 | % B.BTmap = @(y) {mexsmat(blk,Bt*y)}; 164 | end 165 | end 166 | 167 | function Aty = ATmap(y) 168 | m = length(y); 169 | Aty = sparse([1:m],[1:m],y,m,m); 170 | Aty(m,1:m-1) = -0.5*y(1:m-1)'; 171 | Aty(1:m-1,m) = -0.5*y(1:m-1); 172 | Aty = (Aty + Aty')*0.5; 173 | %Aty = {Aty}; 174 | end 175 | 176 | 177 | %%****************************************************** 178 | 179 | 180 | -------------------------------------------------------------------------------- /util/biq_sqsdp_new.m: -------------------------------------------------------------------------------- 1 | %%****************************************************** 2 | %% biq: generate SDP data for binary quadratic 3 | %% programming 4 | %% 5 | %% X = [Y,y; y', 1]; 6 | %%****************************************************** 7 | 8 | function [blk,A,C,b,B,d,SignP,fV,U,L,nonnegative] = biq_sqsdp_new(Q,options) 9 | 10 | if (nargin == 1); options = 0; end; 11 | if isempty(Q) 12 | blk = []; C = []; b = []; 13 | A =[]; B = []; d = []; 14 | return; 15 | end 16 | if norm(Q-Q','fro') 17 | Q = 0.5*(Q + Q'); 18 | end 19 | SignP = []; fV = []; U = []; L = []; B =[]; d=[]; 20 | nonnegative = 1; 21 | n = size(Q,1); 22 | blk{1,1} = 's'; blk{1,2} = n+1; 23 | %% 24 | %% 25 | %% 26 | C = [Q,sparse(n,1); sparse(1,n+1)]; 27 | %% 28 | %% diag(Y) = y; 29 | %% 30 | 31 | n1 = n+1; 32 | Acell = cell(1,n1); 33 | for k = 1:n 34 | Acell{k} = spconvert([k,k,1;k,n1,-0.5; n1,k,-0.5;n1,n1,0]); 35 | end 36 | Acell{n1} = spconvert([n1,n1,1]); 37 | At = svec(blk,Acell,1); 38 | b = [zeros(n,1); 1]; 39 | At = At{1}; 40 | A.At = At; 41 | A.Amap = @(X) diag(X) - [X(1:end-1,end);0]; 42 | A.ATmap = @(y) ATmap(y); 43 | % n1 = n+1; 44 | % Acell = cell(1,n); 45 | % for k = 1:n 46 | % Acell{k} = spconvert([k,k,1;k,n1,-0.5; n1,k,-0.5;n1,n1,0]); 47 | % end 48 | % At = svec(blk,Acell,1); 49 | % 50 | % b = zeros(n,1); 51 | % 52 | % At = At{1}; 53 | % A.At = At; 54 | % A.Amap = @(X) diag(X(1:end-1,1:end-1)) - X(1:end-1,end); 55 | % %A.Amap = @(X) diag(X{1}) - [X{1}(1:end-1,end);0]; 56 | % A.ATmap = @(y) ATmap(y); 57 | %% alpha = 1; 58 | % projop.idx = n1^2; 59 | % projop.v = 1; 60 | % SignP = zeros(n1); 61 | % idx2 = n1^2; 62 | % SignP(idx2) = 2; 63 | % fV = 1; 64 | % L = []; 65 | % U = []; 66 | % nonnegative = 1; 67 | %% 68 | % %% add the constraint >= (e'*y)^2 69 | % %% 70 | % if (options == 1) %% Not useful. 71 | % e = ones(n,1); 72 | % tmp{1,1} = [sparse(n,n), 0.5*e; 0.5*e', 0]; 73 | % tmp{1,2} = [ones(n,n), zeros(n,1); zeros(1,n), 0]; 74 | % tmp{1,3} = sparse(n+1,n+1); 75 | % Atmp = svec(blk(1,:),tmp,1); 76 | % At{1} = [At{1}, Atmp{1}]; 77 | % b = [b; 0;0;1]; 78 | % C{2,1} = zeros(3,1); 79 | % blk{2,1} = 'q'; blk{2,2} = 3; 80 | % At{2,1} = [sparse(n1,3); 0,0,-1; -1,-1,0; 1,-1,0]'; 81 | % end 82 | % %% 83 | % %% add the constraint Y_{ij} <= y_i,Y_{ij} <= y_j, Y_{ij} >= y_i + y_j - 1 to form standard SDP 84 | % %% 85 | % if (options == 2) 86 | % idx1 = [1:5:n]; 87 | % idx2 = [2:5:n]; 88 | % len1 = length(idx1); 89 | % len2 = length(idx2); 90 | % m2 = len1*len2; 91 | % Acell = cell(1,m2); 92 | % AAcell = cell(1,m2); 93 | % num = 0; 94 | % for i = idx1 95 | % for j = idx2 96 | % if j ~= i 97 | % Acell{num+1} = spconvert([i,j,-0.5;j,i,-0.5;i,n1,0.5;n1,i,0.5;n1,n1,0]); %% -Y_{ij} + y_i >= 0 98 | % AAcell{num+1} = spconvert([i,j,0.5;j,i,0.5;i,n1,-0.5;n1,i,-0.5;j,n1,-0.5;n1,j,-0.5;n1,n1,0]); %% Y_{ij} - y_i - y_j >= - 1 99 | % num = num+1; 100 | % end 101 | % end 102 | % end 103 | % m2 = num; 104 | % Acell = Acell(1:m2); 105 | % AAcell = AAcell(1:m2); 106 | % Atmp1 = svec(blk,Acell,1); 107 | % Atmp2 = svec(blk,AAcell,1); 108 | % At{1} = [At{1}, Atmp1{1}, Atmp2{1}]; 109 | % b = [b; zeros(m2,1); ones(m2,1)]; 110 | % C{2,1} = zeros(m2*2,1); 111 | % blk{2,1} = 'l'; blk{2,2} = m2*2; 112 | % At{2,1} = [sparse(m2*2,n1) speye(m2*2)]; 113 | % end 114 | %%****************************************************** 115 | %% add the constraint -Y_{ij} + y_i >= 0, -Y_{ij} + y_j >= 0, Y_{ij} - y_i - y_j >= - 1 116 | %%---- and Y_{ij}+Y{ik}+Y{jk}-y_i-y_j-y_k >= -1 117 | %% 118 | if (options == 3) 119 | idx1 = [1:1:n]; 120 | idx2 = [1:1:n]; 121 | idx3 = []; 122 | len1 = length(idx1); 123 | len2 = length(idx2); 124 | len3 = length(idx3); 125 | m2 = len1*len2; 126 | m3 = m2*len3; 127 | Acell = cell(1,m2); 128 | A1cell = cell(1,m2); 129 | AAcell = cell(1,m2); 130 | A3cell = cell(1,m3); 131 | num = 0; 132 | num1 = 0; 133 | for i = idx1 134 | for j = idx2 135 | if i < j 136 | Acell{num+1} = spconvert([i,j,-0.5;j,i,-0.5;i,n1,0.5;n1,i,0.5;n1,n1,0]); %% -Y_{ij} + y_i >= 0 137 | A1cell{num+1} = spconvert([i,j,-0.5;j,i,-0.5;j,n1,0.5;n1,j,0.5;n1,n1,0]); %% -Y_{ij} + y_j >= 0 138 | AAcell{num+1} = spconvert([i,j,0.5;j,i,0.5;i,n1,-0.5;n1,i,-0.5;j,n1,-0.5;n1,j,-0.5;n1,n1,0]); %% Y_{ij} - y_i - y_j >= - 1 139 | num = num+1; 140 | end 141 | for k = idx3 142 | if j ~= i && k ~= i && k ~= j 143 | A3cell{num1+1} = spconvert... 144 | ([i,j,1;i,k,1;j,k,1;i,n1,-0.5;n1,i,-0.5;j,n1,-0.5;n1,j,-0.5;k,n1,-0.5;n1,k,-0.5;n1,n1,0]); 145 | num1 = num1+1; 146 | end 147 | end 148 | end 149 | end 150 | m2 = num; 151 | Acell = Acell(1:m2); 152 | A1cell = A1cell(1:m2); 153 | AAcell = AAcell(1:m2); 154 | A3cell = A3cell(1:num1); 155 | Atmp1 = svec(blk,Acell,1); 156 | A1tmp1 = svec(blk,A1cell,1); 157 | Atmp2 = svec(blk,AAcell,1); 158 | Atmp3 = svec(blk,A3cell,1); 159 | Bt = [Atmp1{1}, A1tmp1{1}, Atmp2{1}]; 160 | d = [zeros(m2*2,1); -ones(m2,1);]; 161 | B = Bt; 162 | % B.Bt = Bt; 163 | % B.Bmap = @(X) (mexsvec(blk,X)'*Bt)'; 164 | % B.BTmap = @(y) {mexsmat(blk,Bt*y)}; 165 | end 166 | end 167 | 168 | function Aty = ATmap(y) 169 | m = length(y); 170 | Aty = sparse([1:m],[1:m],y,m,m); 171 | Aty(m,1:m-1) = -0.5*y(1:m-1)'; 172 | Aty(1:m-1,m) = -0.5*y(1:m-1); 173 | Aty = (Aty + Aty')*0.5; 174 | %Aty = {Aty}; 175 | end 176 | 177 | 178 | %%****************************************************** 179 | 180 | 181 | -------------------------------------------------------------------------------- /util/biqread.m: -------------------------------------------------------------------------------- 1 | %%******************************************************** 2 | %% 3 | %% [Q] = biqread('~/SDPdata/BIQ/be100.1.sparse'); 4 | %% 5 | %%******************************************************** 6 | 7 | function [Q] = biqread(fname); 8 | 9 | fid = fopen(fname,'r'); 10 | if (fid == -1); error('file cannot be opened'); end 11 | 12 | [datavec,count] = fscanf(fid,'%c'); 13 | fclose(fid); 14 | linefeeds = findstr(datavec,char(10)); 15 | datavec(linefeeds) = blanks(length(linefeeds)); 16 | datavec = sscanf(datavec,'%f'); 17 | 18 | n = datavec(1); nz = datavec(2); 19 | tmp = datavec(3:end); 20 | ii = tmp(1:3:end-2); 21 | jj = tmp(2:3:end-1); 22 | vv = tmp(3:3:end); 23 | Q = spconvert([ii,jj,vv;n,n,0]); 24 | Q = triu(Q,1) + triu(Q,1)' + spdiags(diag(Q),0,n,n); 25 | %%******************************************************** 26 | -------------------------------------------------------------------------------- /util/qapAW.m: -------------------------------------------------------------------------------- 1 | %%****************************************************** 2 | %% qapAW: generate SDP data for the problem QAP-AW1 in 3 | %% the paper by Povh and Rendl. 4 | %% 5 | %% SDPNAL: 6 | %% Copyright (c) 2008 by 7 | %% Xinyuan Zhao, Defeng Sun, and Kim-Chuan Toh 8 | %%****************************************************** 9 | 10 | function [blk,Ft,CC,bb,Ascale,Bscale] = qapAW(A,B,options) 11 | 12 | n = size(A,1); 13 | if (size(B,1)~= n); 14 | error('A and B must have the same size'); 15 | end 16 | if (nargin == 2); options = 2; end 17 | 18 | n2 = n*n; 19 | blk{1,1} = 's'; blk{1,2} = n2; 20 | %% 21 | %% 22 | %% 23 | Ascale = max(1,norm(A,'fro')); 24 | Bscale = max(1,norm(B,'fro')); 25 | A = A/Ascale; B = B/Bscale; 26 | CC{1} = kron(B,A); 27 | if norm(A-A','fro') | norm(B-B','fro') 28 | CC{1} = 0.5*(CC{1} + CC{1}'); 29 | end 30 | %% 31 | %% sum_i Y^{ii} = I_n 32 | %% create n*(n+1)/2 constraints 33 | %% 34 | pp = [0:n:n*(n-1)]'; vv = (1/sqrt(2))*ones(n,1); 35 | Fcell = cell(1,n*(n+1)/2); 36 | count = 0; 37 | for j = 1:n 38 | for i = 1:j 39 | row = pp + i; col = pp + j; 40 | if (i==j) 41 | Fcell{count+1} = spconvert([row,col,ones(n,1); n2,n2, 0]); 42 | else 43 | Fcell{count+1} = spconvert([row,col,vv; n2,n2, 0]); 44 | end 45 | count = count+1; 46 | end 47 | end 48 | Ft = svec(blk,Fcell,1); 49 | bb = svec(blk,speye(n,n)); 50 | %% 51 | %% = delta_{ij} for j=1:n, i=1:j. 52 | %% 53 | pp = [1:n]'; vv = ones(n,1)/2; 54 | count = 0; 55 | btmp = zeros(n*(n+1)/2,1); 56 | for j = 1:n 57 | for i = 1:j 58 | row = pp + (i-1)*n; col = pp + (j-1)*n; 59 | if (i==j) 60 | Fcell{count+1} = spconvert([row,col,ones(n,1); n2,n2, 0]); 61 | btmp(count+1) = 1; 62 | count = count+1; 63 | elseif (i < j) 64 | Fcell{count+1} = spconvert([row,col,vv; n2,n2, 0]); 65 | btmp(count+1) = 0; 66 | count = count+1; 67 | end 68 | end 69 | end 70 | if (options == 1) 71 | %% 72 | %% add = n2 73 | %% 74 | idx = [1:n*(n+1)/2-1]; 75 | alpha = n2; 76 | ee = svec(blk,ones(n2,n2),1); 77 | Ftmp = svec(blk,Fcell(idx),1); 78 | Ft{1} = [Ft{1}, Ftmp{1}, ee/alpha]; 79 | bb = [bb; btmp(idx); n2/alpha]; 80 | else 81 | %% 82 | %% add = 1 for j=1:n, i=1:j. 83 | %% 84 | Fcell2 = cell(1,n*(n+1)/2); 85 | alpha = sqrt(n); 86 | btmp2 = ones(n*(n+1)/2,1)/alpha; 87 | rr = [1:n]'*ones(1,n); rr = rr(:); 88 | cc = ones(n,1)*[1:n]; cc = cc(:); 89 | vv = ones(n2,1)/(2*alpha); 90 | ee = ones(n2,1)/alpha; 91 | count = 0; 92 | for j = 1:n 93 | for i = 1:j 94 | row = rr + (i-1)*n; col = cc + (j-1)*n; 95 | if (i==j) 96 | Fcell2{count+1} = spconvert([row,col,ee;n2,n2,0]); 97 | count = count+1; 98 | elseif (i < j) 99 | Fcell2{count+1} = spconvert([row,col,vv;n2,n2,0]); 100 | count = count+1; 101 | end 102 | end 103 | end 104 | idx = [1:n*(n+1)/2-1]; 105 | Ftmp = svec(blk,Fcell(idx),1); Ftmp2 = svec(blk,Fcell2(idx),1); 106 | Ft{1} = [Ft{1}, Ftmp{1}, Ftmp2{1}]; 107 | bb = [bb; btmp(idx); btmp2(idx)]; 108 | end 109 | %%****************************************************** 110 | -------------------------------------------------------------------------------- /util/qapAW2.m: -------------------------------------------------------------------------------- 1 | %%****************************************************** 2 | %% qapAW: generate SDP data for the problem QAP-AW1 in 3 | %% the paper by Povh and Rendl. 4 | %% 5 | %% [Y_{11} ... Y_{1n} x1] 6 | %% X = [ : ... : : ] 7 | %% [Y_{n1} ... Y_{nn} xn] 8 | %% [ x1' ... xn' 1] 9 | %%****************************************************** 10 | 11 | function [blk,Ft,CC,bb] = qapAW(A,B,options) 12 | 13 | n = size(A,1); 14 | if (size(B,1)~= n); 15 | error('A and B must have the same size'); 16 | end 17 | if (nargin == 2); options = 2; end 18 | 19 | n2 = n*n + 1; 20 | blk{1,1} = 's'; blk{1,2} = n2; 21 | %% 22 | %% 23 | %% 24 | CC{1} = kron(B,A); 25 | if norm(A-A','fro') | norm(B-B','fro') 26 | CC{1} = 0.5*(CC{1} + CC{1}'); 27 | end 28 | CC{1} = [CC{1}, zeros(n*n,1); zeros(1,n*n), 0]; 29 | %% 30 | %% sum_i Y^{ii} = I_n 31 | %% create n*(n+1)/2 constraints 32 | %% 33 | pp = [0:n:n*(n-1)]'; vv = (1/sqrt(2))*ones(n,1); 34 | Fcell = cell(1,n*(n+1)/2); 35 | count = 0; 36 | for j = 1:n 37 | for i = 1:j 38 | row = pp + i; col = pp + j; 39 | if (i==j) 40 | Fcell{count+1} = spconvert([row,col,ones(n,1); n2,n2, 0]); 41 | else 42 | Fcell{count+1} = spconvert([row,col,vv; n2,n2, 0]); 43 | end 44 | count = count+1; 45 | end 46 | end 47 | Ft = svec(blk,Fcell,1); 48 | bb = svec(blk,speye(n,n)); 49 | %% 50 | %% = delta_{ij} for j=1:n, i=1:j. 51 | %% 52 | pp = [1:n]'; vv = ones(n,1)/2; 53 | count = 0; 54 | btmp = zeros(n*(n+1)/2,1); 55 | for j = 1:n 56 | for i = 1:j 57 | row = pp + (i-1)*n; col = pp + (j-1)*n; 58 | if (i==j) 59 | Fcell{count+1} = spconvert([row,col,ones(n,1); n2,n2, 0]); 60 | btmp(count+1) = 1; 61 | count = count+1; 62 | elseif (i < j) 63 | Fcell{count+1} = spconvert([row,col,vv; n2,n2, 0]); 64 | btmp(count+1) = 0; 65 | count = count+1; 66 | end 67 | end 68 | end 69 | %% 70 | %% add = 1 for j=1:n, i=1:j. 71 | %% 72 | Fcell2 = cell(1,n*(n+1)/2); 73 | alpha = sqrt(n); 74 | btmp2 = ones(n*(n+1)/2,1)/alpha; 75 | rr = [1:n]'*ones(1,n); rr = rr(:); 76 | cc = ones(n,1)*[1:n]; cc = cc(:); 77 | vv = ones(n*n,1)/(2*alpha); 78 | ee = ones(n*n,1)/alpha; 79 | count = 0; 80 | for j = 1:n 81 | for i = 1:j 82 | row = rr + (i-1)*n; col = cc + (j-1)*n; 83 | if (i==j) 84 | Fcell2{count+1} = spconvert([row,col,ee;n2,n2,0]); 85 | count = count+1; 86 | elseif (i < j) 87 | Fcell2{count+1} = spconvert([row,col,vv;n2,n2,0]); 88 | count = count+1; 89 | end 90 | end 91 | end 92 | idx = [1:n*(n+1)/2-1]; 93 | Ftmp = svec(blk,Fcell(idx),1); Ftmp2 = svec(blk,Fcell2(idx),1); 94 | Ft{1} = [Ft{1}, Ftmp{1}, Ftmp2{1}]; 95 | bb = [bb; btmp(idx); btmp2(idx)]; 96 | %% 97 | %% add diag(Y_{ii}) = xi for i=1:n 98 | %% Y_{n2,n2} = 1; 99 | %% 100 | Fcell = cell(1,n2); 101 | for k = 1:n*n 102 | Fcell{k} = spconvert([k,k,1; k,n2,-0.5; n2,k,-0.5; n2,n2,0]); 103 | end 104 | Fcell{n2} = spconvert([n2,n2,1]); 105 | Ftmp = svec(blk,Fcell,1); 106 | Ft{1} = [Ft{1}, Ftmp{1}]; 107 | bb = [bb; zeros(n*n,1); 1]; 108 | %% 109 | %% add e'*xi = 1 for i= 1:n 110 | %% 111 | pp = [1:n]'; vv = 0.5*ones(n,1); 112 | Fcell = cell(1,n); 113 | for k = 1:n 114 | col = n2*ones(n,1); row = (k-1)*n + pp; 115 | Fcell{k} = spconvert([row,col,vv; col,row,vv; n2,n2,0]); 116 | end 117 | Ftmp = svec(blk,Fcell,1); 118 | Ft{1} = [Ft{1}, Ftmp{1}]; 119 | bb = [bb; ones(n,1)]; 120 | %%****************************************************** 121 | -------------------------------------------------------------------------------- /util/qapread.m: -------------------------------------------------------------------------------- 1 | %%******************************************************** 2 | %% 3 | %% [A,B] = qapread('~/ZXY/PAL/QAP/qapdata/nug12.dat'); 4 | %% 5 | %% SDPNAL: 6 | %% Copyright (c) 2008 by 7 | %% Xinyuan Zhao, Defeng Sun, and Kim-Chuan Toh 8 | %%******************************************************** 9 | 10 | function [A,B] = qapread(fname); 11 | 12 | fid = fopen(fname,'r'); 13 | if (fid == -1); error('file cannot be opened'); end 14 | 15 | [datavec,count] = fscanf(fid,'%c'); 16 | fclose('all'); 17 | linefeeds = findstr(datavec,char(10)); 18 | datavec(linefeeds) = blanks(length(linefeeds)); 19 | datavec = sscanf(datavec,'%f'); 20 | 21 | n = datavec(1); n2 = n*n; 22 | aa = datavec(2:n2+1); 23 | bb = datavec(n2+2:2*n2+1); 24 | 25 | A = reshape(aa,n,n); 26 | B = reshape(bb,n,n); 27 | %%******************************************************** 28 | -------------------------------------------------------------------------------- /util/qmapfuncorr.m: -------------------------------------------------------------------------------- 1 | function axb=qmapfuncorr(L1,D1,L2,D2,x,const) 2 | ax=D1*x+L1'*(L1*x); 3 | axb=ax*D2+(ax*(L2'))*L2; 4 | axb=(axb+axb')/(2*const); 5 | end -------------------------------------------------------------------------------- /util/randQXfun.m: -------------------------------------------------------------------------------- 1 | function QX = randQXfun(X,n) 2 | 3 | rng('default'); 4 | r = min(n,5); 5 | Atmp = randn(n,r); 6 | A = Atmp*Atmp'; 7 | A = A/norm(A,'fro'); 8 | Btmp = randn(n,r); 9 | B = Btmp*Btmp'; 10 | B = B/norm(B,'fro'); 11 | QX = (0.5/sqrt(n))*(A*X*B + B*X*A); 12 | 13 | -------------------------------------------------------------------------------- /util/read_sdpa.m: -------------------------------------------------------------------------------- 1 | %%******************************************************************* 2 | %% Read in a problem in SDPA sparse format. 3 | %% 4 | %% [blk,At,C,b] = read_sdpa(fname) 5 | %% 6 | %% Input: fname = name of the file containing SDP data in 7 | %% SDPA foramt. 8 | %% Important: the data is assumed to contain only 9 | %% semidefinite and linear blocks. 10 | %% 11 | %% SDPNAL: 12 | %% Copyright (c) 2008 by 13 | %% Xinyuan Zhao, Defeng Sun, and Kim-Chuan Toh 14 | %%****************************************************************** 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | %% 2EBD-HPE: 17 | %% Modified by C.Ortiz 18 | %% Last Modified: 6/15/2012 19 | 20 | function [blk,At,C,b] = read_sdpa(fname); 21 | 22 | %% 23 | %% Open the file for input 24 | %% 25 | compressed = 0; 26 | if exist(fname) 27 | fid = fopen(fname,'r'); 28 | elseif exist([fname,'.Z']); 29 | compressed = 1; 30 | unix(['uncompress ',fname,'.Z']); 31 | fid = fopen(fname,'r'); 32 | elseif exist([fname,'.gz']); 33 | compressed = 2; 34 | unix(['gunzip ',fname,'.gz']); 35 | fid = fopen(fname,'r'); 36 | else 37 | fprintf(['*** Problem "',fname,'" not found, please specify the correct path or problem name. \n']); 38 | blk = []; At = []; C = []; b = []; 39 | return; 40 | end 41 | %% 42 | %% Clean up special characters and comments from the file 43 | %% 44 | [datavec,count] = fscanf(fid,'%c'); 45 | linefeeds = findstr(datavec,char(10)); 46 | comment_chars = '*"='; 47 | cumidx = []; 48 | for i=1:length(comment_chars) 49 | idx = findstr(datavec,comment_chars(i)); 50 | cumidx = [cumidx,idx]; 51 | end 52 | for j=length(cumidx):-1:1 53 | if (cumidx(j)==1) || (strcmp(datavec(cumidx(j)-1),char(10))) 54 | datavec(cumidx(j):linefeeds(min(find(cumidx(j) size(blksize,2); blksize = blksize'; end 82 | %% 83 | %% Get input b. 84 | %% 85 | idxstrt = 2+numblk; 86 | b = datavec(idxstrt+[1:m]); 87 | idxstrt = idxstrt+m; 88 | b = -b; 89 | %% 90 | %% Construct blk 91 | %% 92 | deblksize = 80; 93 | spblkidxtmp = find( (blksize>1) & (blksize < deblksize) ); 94 | spblkidxtmp = sort(spblkidxtmp); 95 | deblkidx = find( (blksize<=1) | (blksize >= deblksize) ); 96 | denumblk = length(deblkidx); 97 | linblkidx = zeros(1,denumblk); 98 | for p = 1:denumblk 99 | n = blksize(deblkidx(p)); 100 | if (n > 1); 101 | blk{p,1} = 's'; blk{p,2} = n; 102 | n2 = n*(n+1)/2; 103 | At{p,1} = sparse(n2,m); 104 | C{p,1} = sparse(n,n); 105 | else 106 | linblkidx(p) = p; 107 | blk{p,1} = 'l'; blk{p,2} = abs(n); 108 | At{p,1} = sparse(abs(n),m); 109 | C{p,1} = sparse(abs(n),1); 110 | end 111 | end 112 | if ~isempty(spblkidxtmp) 113 | maxnumblk = 200; 114 | spnumblk = ceil(length(spblkidxtmp)/maxnumblk); 115 | for q = 1:spnumblk 116 | if (q < spnumblk) 117 | spblkidxall{q} = spblkidxtmp([(q-1)*maxnumblk+1: q*maxnumblk]); 118 | else 119 | spblkidxall{q} = spblkidxtmp([(q-1)*maxnumblk+1: length(spblkidxtmp)]); 120 | end 121 | tmp = blksize(spblkidxall{q}); 122 | blk{denumblk+q,1} = 's'; 123 | blk{denumblk+q,2} = tmp; 124 | n2 = sum(tmp.*(tmp+1))/2; 125 | At{denumblk+q,1} = sparse(n2,m); 126 | C{denumblk+q,1} = sparse(sum(tmp),sum(tmp)); 127 | end 128 | else 129 | spnumblk = 0; 130 | end 131 | linblkidx(denumblk+[1:spnumblk]) = zeros(1,spnumblk); 132 | %% 133 | %% Construct single blocks of A,C 134 | %% 135 | len = length(datavec); 136 | Y = reshape(datavec(idxstrt+1:len),5,(len-idxstrt)/5)'; 137 | clear datavec; 138 | Y = sortrows(Y,[1 2]); 139 | matidx = [0; find(diff(Y(:,1)) ~= 0); size(Y,1)]; 140 | %% 141 | for k = 1:length(matidx)-1 142 | idx = [matidx(k)+1 : matidx(k+1)]; 143 | Ytmp = Y(idx,1:5); 144 | matno = Ytmp(1,1); 145 | Ytmp2 = Ytmp(:,2); 146 | for p = 1:denumblk 147 | n = blksize(deblkidx(p)); 148 | idx = find(Ytmp2 == deblkidx(p)); 149 | ii = Ytmp(idx,3); jj = Ytmp(idx,4); vv =Ytmp(idx,5); 150 | len = length(idx); 151 | if (n > 1) 152 | idxtmp = find(ii > jj); 153 | if ~isempty(idxtmp); 154 | tmp = jj(idxtmp); 155 | jj(idxtmp) = ii(idxtmp); ii(idxtmp) = tmp; 156 | end 157 | tmp = -sparse(ii,jj,vv,n,n); 158 | tmp = tmp + triu(tmp,1)'; 159 | else 160 | tmp = -sparse(ii,ones(len,1),vv,abs(n),1); 161 | end 162 | if (matno == 0) 163 | C{p,1} = tmp; 164 | else 165 | if (n > 1) 166 | At{p,1}(:,matno) = svec(blk(p,:),tmp,1); 167 | else 168 | At{p,1}(:,matno) = tmp; 169 | end 170 | end 171 | end 172 | end 173 | %% 174 | %% Construct big sparse block of A,C 175 | %% 176 | if (spnumblk > 0) 177 | Y1 = Y(:,1); 178 | diffY1 = find(diff([-1; Y1; inf])); 179 | for kk = 1:length(diffY1)-1 180 | idx = [diffY1(kk) : diffY1(kk+1)-1]; 181 | matno = Y1(diffY1(kk)); 182 | Ytmp = Y(idx,1:5); 183 | Ytmp2 = Ytmp(:,2); 184 | maxYtmp2 = Ytmp2(length(Ytmp2)); 185 | minYtmp2 = Ytmp2(1); 186 | diffYtmp2 = Ytmp2(find(diff([-1; Ytmp2]))); 187 | for q = 1:spnumblk 188 | spblkidx = spblkidxall{q}; 189 | maxspblkidx = spblkidx(length(spblkidx)); 190 | minspblkidx = spblkidx(1); 191 | count = 0; 192 | if (minYtmp2 <= maxspblkidx) & (maxYtmp2 >= minspblkidx) 193 | tmpblksize = blksize(spblkidx); 194 | n = sum(tmpblksize); 195 | cumspblksize = [0 cumsum(tmpblksize)]; 196 | n2 = sum(tmpblksize.*(tmpblksize+1))/2; 197 | idx = zeros(n2,1); offset = zeros(n2,1); 198 | for t = [1:length(diffYtmp2)] 199 | p = find(spblkidx == diffYtmp2(t)); 200 | if ~isempty(p) 201 | idxtmp = find(Ytmp2 == spblkidx(p)); 202 | len = length(idxtmp); 203 | idx(count+[1:len]) = idxtmp; 204 | offset(count+[1:len]) = cumspblksize(p); 205 | count = count + len; 206 | end 207 | end 208 | idx = idx(1:count); offset = offset(1:count); 209 | ii = Ytmp(idx,3)+offset; jj = Ytmp(idx,4)+offset; vv = Ytmp(idx,5); 210 | idxtmp = find(ii > jj); 211 | if ~isempty(idxtmp); 212 | tmp = jj(idxtmp); 213 | jj(idxtmp) = ii(idxtmp); ii(idxtmp) = tmp; 214 | end 215 | idxeq = find(ii==jj); 216 | tmp = spconvert([ii jj -vv; jj ii -vv; n n 0]) ... 217 | + spconvert([ii(idxeq) jj(idxeq) vv(idxeq); n n 0]); 218 | if (matno == 0) 219 | C{denumblk+q,1} = tmp; 220 | else 221 | At{denumblk+q,1}(:,matno) = svec(blk(denumblk+q,:),tmp,1); 222 | end 223 | end 224 | end 225 | end 226 | end 227 | %% 228 | %% put all linear blocks together as a single linear block 229 | %% 230 | idx = find(linblkidx); 231 | if (length(idx) > 1) 232 | sdpidx = find(linblkidx==0); 233 | blktmp = 0; Atmp = []; Ctmp = []; 234 | for k = 1:length(idx) 235 | tmp = linblkidx(idx(k)); 236 | blktmp = blktmp+blk{tmp,2}; 237 | Atmp = [Atmp; At{tmp}]; 238 | Ctmp = [Ctmp; C{tmp}]; 239 | end 240 | At = At(sdpidx); C = C(sdpidx); blk = blk(sdpidx,:); 241 | len = length(sdpidx); 242 | blk(2:len+1,:) = blk; 243 | blk{1,1} = 'l'; blk{1,2} = blktmp; 244 | At(2:len+1,1) = At; C(2:len+1,1) = C; 245 | At{1,1} = Atmp; C{1,1} = Ctmp; 246 | end 247 | %%****************************************************************** 248 | 249 | -------------------------------------------------------------------------------- /util/read_sedumi.m: -------------------------------------------------------------------------------- 1 | %%******************************************************************* 2 | %% Read in a problem in SeDuMi format. 3 | %% 4 | %% [blk,A,C,b,perm] = read_sedumi(fname,b,c,K) 5 | %% 6 | %% Input: fname.mat = name of the file containing SDP data in 7 | %% SeDuMi format. 8 | %% 9 | %% Important note: Sedumi's notation for free variables "K.f" 10 | %% is coded in SDPT3 as blk{p,1} = 'u', where 11 | %% "u" is used for unrestricted variables. 12 | %% 13 | %% SDPNAL: 14 | %% Copyright (c) 2008 by 15 | %% Xinyuan Zhao, Defeng Sun, and Kim-Chuan Toh 16 | %%****************************************************************** 17 | 18 | function [blk,Avec,C,b,perm] = read_sedumi(fname,b,c,K,smallblkdim); 19 | 20 | if (nargin < 5) 21 | smallblkdim = 30; 22 | end 23 | 24 | A = 0; 25 | At = 0; 26 | if isstr(fname) 27 | %% 28 | %% load the matlab file containing At, c, b, and K 29 | %% 30 | K.f = []; K.l = []; K.q = []; 31 | compressed = 0; 32 | if exist([fname,'.mat.gz']); 33 | compressed = 1; 34 | unix(['gunzip ', fname,'.mat.gz']); 35 | elseif exist([fname,'.gz']); 36 | compressed = 2; 37 | unix(['gunzip ', fname,'.gz']); 38 | elseif exist([fname,'.mat.Z']); 39 | compressed = 3; 40 | unix(['uncompress ', fname,'.mat.Z']); 41 | elseif exist([fname,'.Z']); 42 | compressed = 4; 43 | unix(['uncompress ', fname,'.Z']); 44 | end 45 | if exist([fname,'.mat']) | exist(fname) 46 | eval(['load ', fname]); 47 | else 48 | fprintf('*** Problem not found, please specify the correct path or problem. \n'); 49 | blk = []; Avec = []; C = []; b = []; 50 | return; 51 | end 52 | if (compressed == 1) 53 | unix(['gzip ', fname,'.mat']); 54 | elseif (compressed == 2) 55 | unix(['gzip ', fname]); 56 | elseif (compressed == 3) 57 | unix(['compress ', fname,'.mat']); 58 | elseif (compressed == 4) 59 | unix(['compress ', fname]); 60 | end 61 | elseif (nargin < 4) 62 | error('read_sedumi: need 4 input '); 63 | else 64 | A = fname; 65 | end 66 | %% 67 | if exist('c','var') 68 | if (size(c,1) == 1), c = c'; end; 69 | end 70 | if exist('C','var') 71 | c = C; 72 | if (size(c,1) == 1), c = c'; end; 73 | end 74 | if (size(b,1) == 1), b = b'; end; 75 | if (norm(A,'fro') > 0) & (size(A,2) == length(b)); At = A; end 76 | %% 77 | if (norm(At,'fro')==0), At = A'; end; 78 | [nn,mm] = size(At); if (max(size(c)) == 1); c = c*ones(nn,1); end; 79 | if ~isfield(K,'f'); K.f = 0; end 80 | if ~isfield(K,'l'); K.l = 0; end 81 | if ~isfield(K,'q'); K.q = 0; end 82 | if ~isfield(K,'s'); K.s = 0; end 83 | if (K.f == 0) | isempty(K.f); K.f = 0; end; 84 | if (K.l == 0) | isempty(K.l); K.l = 0; end; 85 | if (sum(K.q) == 0) | isempty(K.q); K.q = 0; end 86 | if (sum(K.s) == 0) | isempty(K.s); K.s = 0; end 87 | %% 88 | %% 89 | %% 90 | m = length(b); 91 | rowidx = 0; idxblk = 0; 92 | if ~(K.f == 0) 93 | len = K.f; 94 | idxblk = idxblk + 1; 95 | blk{idxblk,1} = 'u'; blk{idxblk,2} = K.f; 96 | Atmp = At(rowidx+[1:len],:); 97 | Avec{idxblk,1} = Atmp; 98 | C{idxblk,1} = c(rowidx+[1:len]); 99 | perm{idxblk} = []; 100 | rowidx = rowidx + len; 101 | end 102 | if ~(K.l == 0) 103 | len = K.l; 104 | idxblk = idxblk + 1; 105 | blk{idxblk,1} = 'l'; blk{idxblk,2} = K.l; 106 | Atmp = At(rowidx+[1:len],:); 107 | Avec{idxblk,1} = Atmp; 108 | C{idxblk,1} = c(rowidx+[1:len]); 109 | perm{idxblk} = []; 110 | rowidx = rowidx + len; 111 | end 112 | if ~(K.q == 0) 113 | len = sum(K.q); 114 | idxblk = idxblk + 1; 115 | blk{idxblk,1} = 'q'; 116 | if size(K.q,1) <= size(K.q,2); 117 | blk{idxblk,2} = K.q; 118 | else 119 | blk{idxblk,2} = K.q'; 120 | end 121 | Atmp = At(rowidx+[1:len],:); 122 | Avec{idxblk,1} = Atmp; 123 | C{idxblk,1} = c(rowidx+[1:len]); 124 | perm{idxblk} = []; 125 | rowidx = rowidx + len; 126 | end 127 | if ~(K.s == 0) 128 | blksize = K.s; 129 | if (size(blksize,2) == 1); blksize = blksize'; end 130 | blknnz = [0, cumsum(blksize.*blksize)]; 131 | deblkidx = find(blksize > smallblkdim); 132 | if ~isempty(deblkidx) 133 | for p = 1:length(deblkidx) 134 | idxblk = idxblk + 1; 135 | n = blksize(deblkidx(p)); 136 | pblk{1,1} = 's'; pblk{1,2} = n; 137 | blk(idxblk,:) = pblk; 138 | Atmp = At(rowidx+blknnz(deblkidx(p))+[1:n*n],:); 139 | h = [1:n]'; e = ones(n,1); 140 | tmp = triu(h*e' + e*((h-1).*h/2)'); 141 | tmp = tmp(:); 142 | tmp2 = sqrt(2)*triu(ones(n),1) + speye(n,n); 143 | tmp2 = tmp2(:); 144 | symidx = find(tmp(:)); 145 | dd = tmp2(find(tmp2)); 146 | n2 = n*(n+1)/2; 147 | Avec{idxblk,1} = spdiags(dd,0,n2,n2)*Atmp(symidx,:); 148 | Ctmp = c(rowidx+blknnz(deblkidx(p))+[1:n*n]); 149 | Ctmp = mexmat(pblk,Ctmp,1); 150 | C{idxblk,1} = 0.5*(Ctmp+Ctmp'); 151 | perm{idxblk,1} = deblkidx(p); 152 | end 153 | end 154 | spblkidx = find(blksize <= smallblkdim); 155 | if ~isempty(spblkidx) 156 | cnt = 0; cnt2 = 0; 157 | spblksize = blksize(spblkidx); 158 | nn = sum(spblksize.*spblksize); 159 | nn2 = sum(spblksize.*(spblksize+1)/2); 160 | pos = zeros(nn,1); 161 | dd = zeros(nn2,1); 162 | symidx = zeros(nn2,1); 163 | for p = 1:length(spblkidx) 164 | n = blksize(spblkidx(p)); 165 | n2 = n*(n+1)/2; 166 | pos(cnt+[1:n*n]) = rowidx+blknnz(spblkidx(p))+[1:n*n]; 167 | h = [1:n]'; e = ones(n,1); 168 | tmp = triu(h*e' + e*((h-1).*h/2)'); 169 | tmp = tmp(:); 170 | tmp2 = sqrt(2)*triu(ones(n),1) + speye(n,n); 171 | tmp2 = tmp2(:); 172 | symidx(cnt2+[1:n2]) = cnt+find(tmp(:)); 173 | dd(cnt2+[1:n2]) = tmp2(find(tmp2)); 174 | cnt = cnt + n*n; 175 | cnt2 = cnt2 + n2; 176 | end 177 | idxblk = idxblk + 1; 178 | blk{idxblk,1} = 's'; blk{idxblk,2} = blksize(spblkidx); 179 | Atmp = At(pos,:); 180 | Avec{idxblk,1} = spdiags(dd,0,length(dd),length(dd))*Atmp(symidx,:); 181 | Ctmp = c(pos); 182 | Ctmp = mexmat(blk(idxblk,:),Ctmp,1); 183 | C{idxblk,1} = 0.5*(Ctmp+Ctmp'); 184 | perm{idxblk,1} = spblkidx; 185 | end 186 | end 187 | %% 188 | %%******************************************************************* 189 | --------------------------------------------------------------------------------