2

部分的に変化するブロック対角グリッドを生成するためのソリューションで、直感的な何かが欠けていると感じています。いずれにせよ、関数内のループを取り除きたいと思います(挑戦のために...)

与えられたパラメーターのタプル、間隔の数、およびパーセンテージ変動:

params = [100 0.5   1
           24   1 0.9];
nint   = 1; 
perc   = 0.1;

望ましい出力は次のようになります。

pspacegrid(params,perc,nint)
ans =
   90.0000    0.5000    1.0000
  100.0000    0.5000    1.0000
  110.0000    0.5000    1.0000
  100.0000    0.4500    1.0000
  100.0000    0.5000    1.0000
  100.0000    0.5500    1.0000
  100.0000    0.5000    0.9000
  100.0000    0.5000    1.0000
  100.0000    0.5000    1.1000
   21.6000    1.0000    0.9000
   24.0000    1.0000    0.9000
   26.4000    1.0000    0.9000
   24.0000    0.9000    0.9000
   24.0000    1.0000    0.9000
   24.0000    1.1000    0.9000
   24.0000    1.0000    0.8100
   24.0000    1.0000    0.9000
   24.0000    1.0000    0.9900

このマスクで表される値で変動が発生していることがわかります。

mask =
     1     0     0
     1     0     0
     1     0     0
     0     1     0
     0     1     0
     0     1     0
     0     0     1
     0     0     1
     0     0     1
     1     0     0
     1     0     0
     1     0     0
     0     1     0
     0     1     0
     0     1     0
     0     0     1
     0     0     1
     0     0     1

機能pspacegrid()は次のとおりです。

function out = pspacegrid(params, perc, nint)
% PSPACEGRID Generates a parameter space grid for sensitivity analysis

% Size and number of variation steps
sz     = size(params);
nsteps = nint*2+1;

% Preallocate output
out    = reshape(permute(repmat(params,[1,1,nsteps*sz(2)]),[3,1,2]),[],sz(2));

% Mask to index positions where to place interpolated 
[tmp{1:sz(2)}] = deal(true(nsteps,1));
mask           = repmat(logical(blkdiag(tmp{:})),sz(1),1);

zi = cell(sz(1),1);
% LOOP per each parameter tuple
for r = 1:sz(1)
    % Columns, rows, rows to interpolate and lower/upper parameter values
    x     = 1:sz(2);
    y     = [1; nint*2+1];
    yi    = (1:nint*2+1)';
    z     = [params(r,:)*(1-perc); params(r,:)*(1+perc)];
    % Interpolated parameters 
    zi{r} = interp2(x,y,z, x, yi);
end
out(mask) = cat(1,zi{:});
4

1 に答える 1

1

ループ前のコードを構築して、それを理解したと思います:

params = [100 0.5   1
           24   1 0.9];
nint   = 1; 
perc   = 0.1;

sz     = size(params);
nsteps = nint*2+1;

% Preallocate output
out    = reshape(permute(repmat(params,[1,1,nsteps*sz(2)]),[3,1,2]),[],sz(2));

%Map of the percentage moves
[tmp{1:sz(2)}] = deal(linspace(-perc,perc,nint*2+1)');
mask = repmat(blkdiag(tmp{:}),sz(1),1) + 1; %Add one so we can just multiply at the end

mask.*out

したがって、マスクを複製して作成したものを複製する代わりに、各要素が行うパーセンテージの動きを複製します。これは繰り返しパターンです。基本的な要素は次のように作成されます。

linspace(-perc,perc,nint*2+1)'

次に、全体に加算して行列1を掛けるだけです。out

次のようにテストしました。

me = mask.*out;
you = pspacegrid(params, perc, nint);

check = me - you < 0.0001;

mean(check(:))

入力をいじるとうまくいくようでした。ただし、関数でエラーが発生したため、に変更true(...)する必要がありましたones(...)。これはおそらく、Matlab ではなく Octave を使用してオンラインで実行しているためです。

于 2013-08-08T14:34:01.227 に答える