以下の最初の Matlab スクリプトを実行すると、エラーはまったく発生せず、コードは期待どおりの結果を生成しますが、matlabpool open と matlabpool close を取り出し、parfor ループを for ループに変更すると、次のエラーが発生します。
Running... ??? Error using ==> mldivide
Matrix is singular to working precision.
Error in ==> NSS_betas at 11
betas = G\data.y2.';
Error in ==> DElambda at 19
betas(:,ii) = NSS_betas(P1(:,ii),data); end
Error in ==> Individual_Lambdas at 46
beta{ii} = DElambda(de,dataList, @OF_NSS);
必要に応じて CRM_22_12.mat をお送りします。
parfor ループの代わりに通常の for ループを使用した場合にのみエラーが発生するのはなぜですか?
clear all, clc
load Euro_CRM_22_12.mat
matlabpool open
tic
warnState(1) = warning('error', 'MATLAB:singularMatrix');
warnState(2) = warning('error', 'MATLAB:illConditionedMatrix');
mats = 1:50;
mats2 = [2 5 10 30];
% RO: unloop these
de = struct(...
'min', [0;0],...
'max', [50;50],...
'd' , 2,...
'nP' , 500,...
'nG' , 600,...
'ww' , 0.1,...
'F' , 0.5,...
'CR' , 0.99,...
'R' , 0,...
'oneElementfromPm',1);
% RO: initialize beta
beta = cell(size(rates,1),1);
clc, fprintf('Running... ');
%for ii = 1:size(rates,1)
parfor ii = 1:size(rates,1)
% RO: use status indicator for things that take this long
%fprintf('\b\b\b\b\b\b\b%6.2f%%', ii/size(rates,1)*100);
dataList = struct(...
'yM' , rates(ii,:),...
'mats' , mats,...
'model', @NSS,...
'mats2', mats2,...
'y2' , rates(ii,mats2));
beta{ii} = DElambda(de,dataList, @OF_NSS);
end
toc
matlabpool close
%
function [output] = DElambda(de,data,OF)
% RO: also saves time
% warning off; %#ok
warning on verbose;
P1 = zeros(de.d,de.nP);
Pu = zeros(de.d,de.nP);
for ii = 1:de.d
P1(ii,:) = de.min(ii,1)+(de.max(ii,1)-de.min(ii,1))*rand(de.nP,1); end
P1(:,1:de.d) = diag(de.max);
P1(:,de.d+1:2*de.d) = diag(de.min);
% RO: pre allocate betas
betas = zeros(size(data.y2,2), de.nP);
for ii = 1:de.nP
betas(:,ii) = NSS_betas(P1(:,ii),data); end
Params = vertcat(betas,P1);
Fbv = NaN(de.nG,1);
% must pass OF as @OF
F = zeros(de.nP,1);
P = zeros(de.nP,1);
for ii = 1:de.nP
F(ii) = OF(Params(:,ii)',data);
P(ii) = pen(P1(:,ii),de,F(ii));
F(ii) = F(ii)+P(ii);
end
[Fbest indice] = min(F);
xbest = Params(:,indice);
Col = 1:de.nP;
% RO: pre allocate betasPu
betasPu = zeros(size(data.y2,2), de.nP);
% RO: if Fbest hasn't changed for 25 generations,
% it's not gonna anymore: break off
count = 0;
for g = 1:de.nG
P0 = P1;
rowS = randperm(de.nP).';
colS = randperm(4).';
% RO: replace circshift for JIT accelleration
% RS = circshift(rowS,colS(1));
% R1 = circshift(rowS,colS(2));
% R2 = circshift(rowS,colS(3));
% R3 = circshift(rowS,colS(4));
RS = rowS([end-colS(1)+1:end 1:end-colS(1)]);
R1 = rowS([end-colS(2)+1:end 1:end-colS(2)]);
R2 = rowS([end-colS(3)+1:end 1:end-colS(3)]);
R3 = rowS([end-colS(4)+1:end 1:end-colS(4)]);
% mutate
Pm = P0(:,R1) + de.F*(P0(:,R2)-P0(:,R3));
if de.R>0, Pm = Pm+de.r*randn(de.d,de.nP); end
% crossover
PmElements = rand(de.d,de.nP)<de.CR;
if de.oneElementfromPm
% RO: JIT...
%Row = unidrnd(de.d,1,de.nP);
Row = ceil(de.d .* rand(1,de.nP));
ExtraPmElements = sparse(Row,Col,1,de.d,de.nP);
PmElements = PmElements|ExtraPmElements;
end
P0_Elements = ~PmElements;
Pu(:,RS) = P0(:,RS).*P0_Elements+PmElements.*Pm;
% RO: inline NSS_betas, so that this loop can
% be compiled by the JIT
mats = data.mats2.';
yM = data.y2.';
nObs = size(data.y2,2);
one = ones(nObs,1);
% RO: version below is faster
% for ii = 1:de.nP
% %betasPu(:,ii) = NSS_betas(Pu(:,ii),data);
%
% lambda = Pu(:,ii);
% G = [one,...
% (1-exp(-mats/lambda(1)))./(mats/lambda(1)),...
% ((1-exp(-mats/lambda(1)))./(mats/lambda(1)) - exp(-mats/lambda(1))),...
% ((1-exp(-mats/lambda(2)))./(mats/lambda(2)) - exp(-mats/lambda(2)))];
%
% betasPu(:,ii) = G\yM;
%
% end
aux = bsxfun(@rdivide, mats, Pu(:).');
aux2 = exp(-aux);
aux3 = (1-aux2)./aux;
for ii = 1:2:2*de.nP
% betasPu(:,(ii+1)/2) =[...
% one,...
% aux3(:,ii),...
% aux3(:,ii) - aux2(:,ii),...
% aux3(:,ii+1) - aux2(:,ii+1)] \ yM;
G=[one, aux3(:,ii), aux3(:,ii) - aux2(:,ii),aux3(:,ii+1) - aux2(:,ii+1)];
try
betasPu(:,(ii+1)/2) =G\yM;
catch ME
CondPen(1,(ii+1)/2)=0;
end
end
ParamsPu = [betasPu;Pu];
flag = 0;
mats = data.mats;
yM = data.yM;
for ii = 1:de.nP
% RO: inline OF_NSS.m here for JIT accelleration
%Ftemp = OF(ParamsPu(:,ii).',data);
beta = ParamsPu(:,ii).';
%model = data.model;
yy = zeros(size(yM));
for jj = 1:size(beta,3)
% RO: inline for JIT accelleration
%y(ii,:) = model(beta(:,:,ii),mats);
betai = beta(:,:,jj);
gam1 = mats/betai(5);
gam2 = mats/betai(6);
aux1 = 1-exp(-gam1);
aux2 = 1-exp(-gam2);
% I have a feeling this is the same as G and therefore
% this can be done shorter and quicker...
% something like yy(jj,:) = sum(G,2)
yy(jj,:) = ...
betai(1) + ...
betai(2)*(aux1./gam1) + ...
betai(3)*(aux1./gam1+aux1-1) + ...
betai(4)*(aux2./gam2+aux2-1);
end
yy = yy-yM;
% RO: this whole loop can be replaced...
% ObjVal = 0;
% for i = 1:size(yM,1) %dim
% ObjVal = ObjVal+dot(aux(i,:)',aux(i,:)');
% %ObjVal = sum(ObjVal);
% end
% ObjVal
% RO ...by this one-liner
Ftemp = sum(yy(:).^2);
% RO: inline penalty here as well
Ptemp = 0;%pen(Pu(:,ii),de,F(ii));
Ftemp = Ftemp+Ptemp;%+CondPen(1,ii);
if Ftemp <= F(ii);
P1(:,ii) = Pu(:,ii);
F(ii) = Ftemp;
if Ftemp < Fbest
Fbest = Ftemp; xbest = ParamsPu(:,ii);
flag = 1;
count = 0;
end
else
P1(:,ii) = P0(:,ii);
end
end
if flag
Fbv(g) = Fbest; end
% RO: if Fbest hasn't changed for 25 generatios, break off
count = count + 1;
if count > 25, break; end
end
output.Fbest = Fbest;
output.xbest = xbest;
output.Fbv = Fbv;
end
% look to inline penalty later (i.e. incoporate into code
function penVal = pen(~,~,~)%pen(beta,pso,vF,data)
penVal = 0;
end
%
function [betas r r2] = NSS_betas(lambda,data)
mats = data.mats2.';
nObs = size(data.y2,2);
G = [ones(nObs,1),...
(1-exp(-mats/lambda(1)))./(mats/lambda(1)),...
((1-exp(-mats/lambda(1)))./(mats/lambda(1)) - exp(-mats/lambda(1))),...
((1-exp(-mats/lambda(2)))./(mats/lambda(2)) - exp(-mats/lambda(2)))];
betas = G\data.y2.';
% RO: output hardly ever needed, while rank()
% is very time consuming
if nargout > 1 && ~isnan(G)
r = rank(G);
r2 = rcond(G);
end
end