How to use arrayfun in CVX?


(Evan Hoo) #1

Suppose I have a variable X(400,400). The objective function is the sum of 160000 nuclear norms of 10*10 patches of X (using the built-in function norm_nuc).
When I use for-loop to generate such objective function using expression holder, it’ll take more than 1 hour. That’s quite slow! I’m considering to use arrayfun to accelerate this for-loop but error pop out:

Error using arrayfun
cvx output type is not currently implemented.

How am I going to do for quicker objective function preparation?

cvx_version

CVX: Software for Disciplined Convex Programming ©2014 CVX Research
Version 3.0beta, Build 1175 (1326ef2) Mon Nov 23 14:29:34 2015

Installation info:
Path: E:\SoftwarePackages\cvx
MATLAB version: 8.3 (R2014a)
OS: Windows 7 amd64 version 6.1
Java version: 1.7.0_11


(Michael C. Grant) #2

I doubt that arrayfun would speed up this model for you even if we did implement it. I’m afraid there’s no easy solution for you here, this is just a hard one for CVX to transform efficiently.


(Evan Hoo) #3

@mcg
I think I’ve found a solution for it. Here are the codes:

    global patchSize;
    patchSize=10;
    patchNum=(400-patchSize+1)^2;
    cxv_begin
    variable X(400,400)
    expressions nuc patches(patchSize^2,patchNum) blk

    pIndex=1;
    for j=1:patchSize
        for i=1:patchSize
             blk=X(i:end-patchSize+i,j:end-patchSize+j);
             patches(pIndex,:)=blk(:)'; 
             pIndex=pIndex+1;
        end
    end
    %The following type-converting process seems tedious, 
    %but it's the only way I've found after trying tons of ways
    cells_temp=num2cell(patches,1);
    nucs_temp=cellfun(@NucNorm,cells_temp,'UniformOutput',false);
    table_temp=cell2table(nucs_temp');
    cellarray_temp=table2array(table_temp);
    nuc=sum([cellarray_temp{1:end}]);

    minimize(....+nuc)
    subject to
         .........
    cvx_end

The self-defined function NucNorm is defined as:

function [ nuc ] = NucNorm( x )
    global patchSize
    cvxobj=norm_nuc(reshape(x,patchSize,patchSize));
    nuc{1}=cvxobj; %have to output a cell type, otherwise the cellfun would pop out error "cvx output type is not currently implemented."
end

Note: The following sentence within the square brackets[ ] is what I claimed before, and its not correct! I’m terribly sorry!
[The above codes accelerate the assignment of nuc greatly, from 2 hours to 2 minutes ! ]

Let me explain it. Sure the above codes can run without error in Matlab, but it doesn’t actually accelerate the generation of the objective function.
I’ve checked the implementation of norm_nuc function in CVX, it seems that, surprisingly,the nuclear norm is implemented as a CVX optimization problem itself!!

function cvx_optval = norm_nuc_aff( X ) %#ok
[ m, n ] = size( X ); %#ok
cvx_begin
variable W(m+n,m+n) hermitian_if(X) semidefinite
minimize(0.5*trace(W))
W(1:m,m+1:end) == X;
cvx_end

So even if I used cellfun to “accelerate” such process, the norm_nuc function is still called and the optimization problem above is also solved to produce each nuclear norm. Unless cellfun can automatically use parallel computing, it will NOT accelerate the process.

BUT, for one particular case, it really can accelerate. That is if not all of the 10*10 patches are needed! Let’s say if only 50% of all the patches is needed for the objective function, then instead of using for-loop like this:

for i=1:patchNum
    if( patch meets condition)
        nuc=nuc+norm_nuc(patch);
    end
end

you can use the codes in the beginning to reduce some for-loop time.


(Evan Hoo) #4

Hi Dr. Grant, I have another question about CVX.

I’m using the latest version of SCS slover, and its warnings are quite annoying, how may I suppress it, I have used “cvx_begin quiet” but it doesn’t work, the iterative information is gone but the warnings of SCS still exist.

WARN: A->p (column pointers) not strictly increasing, column 57125 empty
WARN: A->p (column pointers) not strictly increasing, column 57126 empty
WARN: A->p (column pointers) not strictly increasing, column 57127 empty
WARN: A->p (column pointers) not strictly increasing, column 57129 empty
WARN: A->p (column pointers) not strictly increasing, column 57130 empty


(Michael C. Grant) #5

Well done! I am sure this will be useful to others.

The issue you’re having with SCS is frankly SCS’s fault. I would suggest filing an issue with them.


(Mark L. Stone) #6

@evanhoo wrote “The above codes may accelerate the assignment of nuc slightly. I’ll test it…”

Have you retracted your original claim that 2 hours was reduced to 2 minutes?


(Evan Hoo) #7

Sorry for that, I have edited it again and explained it.


(Flying Bird) #8

Dear Michael:
I have a similar probelm with evanhoo,and I installed CVX3.0Beta and the SCS solver(version 2.0.2).But when I tried SCS with a very simple problem,it seems that there are some errors.My code is as follows:
% cvx_solver sdpt3;
% cvx_solver sedumi;
%cvx_solver mosek;
cvx_solver scs;
cvx_begin quiet sdp
cvx_precision best
variable a(2,2) hermitian %semidefinite
a==semidefinite(2);
minimize(real(a(1,1)))
subject to
trace(a)==1;
a(2,2)<=1;
cvx_end
disp(a)
the error messages are as follows:
WARN: A->p (column pointers) not strictly increasing, column 0 empty
NaN + NaNi NaN + NaNi
NaN + NaNi NaN + NaNi
the other 3 solvers(sdpt3,sdumi,mosek) all give out the right answer.Do you have some ideas about the different performances of the solvers and how to correct my code?Hope for your reply!Thank you.