@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.