dynare/matlab/+gsa/Sampling_Function_2.m

194 lines
9.4 KiB
Matlab

function [Outmatrix, OutFact] = Sampling_Function_2(p, k, r, UB, LB, GroupMat)
%[Outmatrix, OutFact] = Sampling_Function_2(p, k, r, UB, LB, GroupMat)
% Inputs:
% k (1,1) := number of factors examined or number of groups examined.
% In case the groups are chosen the number of factors is stores in NumFact and
% sizea becomes the number of created groups.
% NumFact (1,1) := number of factors examined in the case when groups are chosen
% r (1,1) := sample size
% p (1,1) := number of intervals considered in [0, 1]
% UB(sizea,1) := Upper Bound for each factor
% LB(sizea,1) := Lower Bound for each factor
% GroupNumber(1,1) := Number of groups (eventually 0)
% GroupMat(NumFact,GroupNumber):= Matrix which describes the chosen groups. Each column represents a group and its elements
% are set to 1 in correspondence of the factors that belong to the fixed group. All
% the other elements are zero.
% Local Variables:
% sizeb (1,1) := sizea+1
% sizec (1,1) := 1
% randmult (sizea,1) := vector of random +1 and -1
% perm_e(1,sizea) := vector of sizea random permutated indeces
% fact(sizea) := vector containing the factor varied within each traj
% DDo(sizea,sizea) := D* in Morris, 1991
% A(sizeb,sizea) := Jk+1,k in Morris, 1991
% B(sizeb,sizea) := B in Morris, 1991
% Po(sizea,sizea) := P* in Morris, 1991
% Bo(sizeb,sizea) := B* in Morris, 1991
% Ao(sizeb,sizec) := Jk+1,1 in Morris, 1991
% xo(sizec,sizea) := x* in Morris, 1991 (starting point for the trajectory)
% In(sizeb,sizea) := for each loop orientation matrix. It corresponds to a trajectory
% of k step in the parameter space and it provides a single elementary
% effect per factor
% MyInt()
% Fact(sizea,1) := for each loop vector indicating which factor or group of factors has been changed
% in each step of the trajectory
% AuxMat(sizeb,sizea) := Delta*0.5*((2*B - A) * DD0 + A) in Morris, 1991. The AuxMat is used as in Morris design
% for single factor analysis, while it constitutes an intermediate step for the group analysis.
%
% Outputs:
% Outmatrix(sizeb*r, sizea) := for the entire sample size computed In(i,j) matrices
% OutFact(sizea*r,1) := for the entire sample size computed Fact(i,1) vectors
%
% Note: B0 is constructed as in Morris design when groups are not considered. When groups are considered the routine
% follows the following steps:
% 1- Creation of P0 and DD0 matrices defined in Morris for the groups. This means that the dimensions of these
% 2 matrices are (GroupNumber,GroupNumber).
% 2- Creation of AuxMat matrix with (GroupNumber+1,GroupNumber) elements.
% 3- Definition of GroupB0 starting from AuxMat, GroupMat and P0.
% 4- The final B0 for groups is obtained as [ones(sizeb,1)*x0' + GroupB0]. The P0 permutation is present in GroupB0
% and it's not necessary to permute the matrix (ones(sizeb,1)*x0') because it's already randomly created.
% Reference:
% A. Saltelli, K. Chan, E.M. Scott, "Sensitivity Analysis" on page 68 ss
%
% F. Campolongo, J. Cariboni, JRC - IPSC Ispra, Varese, IT
% Last Update: 15 November 2005 by J.Cariboni
%
% Written by Jessica Cariboni and Francesca Campolongo
% Joint Research Centre, The European Commission,
%
% Copyright © 2005 European Commission
% Copyright © 2012-2023 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
% Parameters and initialisation of the output matrix
sizea = k;
Delta = p/(2*p-2);
%Delta = 1/3
NumFact = sizea;
GroupNumber = size(GroupMat,2);
if GroupNumber ~= 0
sizea = size(GroupMat,2);
end
sizeb = sizea + 1;
Outmatrix = [];
OutFact = [];
% For each i generate a trajectory
for i=1:r
% Construct DD0 - OLD VERSION - it does not need communication toolbox
% RAND(N,M) is an NXM matrix with random entries, chosen from a uniform distribution on the interval (0.0,1.0).
% Note that DD0 tells if the factor have to be increased or ddecreased
% by Delta.
randmult = ones(k,1);
v = rand(k,1);
randmult (v < 0.5)=-1;
randmult = repmat(randmult,1,k);
DD0 = randmult .* eye(k);
% Construct DD0 - NEW VERSION - it needs communication toolbox
% randsrc(m) generates an m-by-m matrix, each of whose entries independently takes the value -1 with probability 1/2,
% and 1 with probability 1/2.
% DD0 = randsrc(NumFact) .* eye(NumFact);
% Construct B (lower triangular)
B = ones(sizeb,sizea);
for j = 1:sizea
B(1:j,j)=0;
end
% Construct A0, A
A0 = ones(sizeb,1);
A = ones(sizeb,NumFact);
% Construct the permutation matrix P0. In each column of P0 one randomly chosen element equals 1
% while all the others equal zero.
% P0 tells the order in which order factors are changed in each
% trajectory. P0 is created as it follows:
% 1) All the elements of P0 are set equal to zero ==> P0 = zeros (sizea, sizea);
% 2) The function randperm create a random permutation of integer 1:sizea, without repetitions ==> perm_e;
% 3) In each column of P0 the element indicated in perm_e is set equal to one.
% Note that P0 is then used reading it by rows.
P0 = zeros (sizea, sizea);
perm_e = randperm(sizea); % RANDPERM(n) is a random permutation of the integers from 1 to n.
for j = 1:sizea
P0(perm_e(j),j) = 1;
end
% When groups are present the random permutation is done only on B. The effect is the same since
% the added part (A0*x0') is completely random.
if GroupNumber ~= 0
B = B * (GroupMat*P0')';
end
% Compute AuxMat both for single factors and groups analysis. For Single factors analysis
% AuxMat is added to (A0*X0) and then permutated through P0. When groups are active AuxMat is
% used to build GroupB0. AuxMat is created considering DD0. If the element on DD0 diagonal
% is 1 then AuxMat will start with zero and add Delta. If the element on DD0 diagonal is -1
% then DD0 will start Delta and goes to zero.
AuxMat = Delta*0.5*((2*B - A) * DD0 + A);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% a --> Define the random vector x0 for the factors. Note that x0 takes value in the hypercube
% [0,...,1-Delta]*[0,...,1-Delta]*[0,...,1-Delta]*[0,...,1-Delta]
MyInt = repmat([0:(1/(p-1)):(1-Delta)],NumFact,1); % Construct all possible values of the factors
% OLD VERSION - it needs communication toolbox
% w = randint(NumFact,1,[1,size(MyInt,2)]);
% NEW VERSION - construct a version of random integers
% 1) create a vector of random integers
% 2) divide [0,1] into the needed steps
% 3) check in which interval the random numbers fall
% 4) generate the corresponding integer
v = repmat(rand(NumFact,1),1,size(MyInt,2)+1); % 1)
IntUsed = repmat(0:1/size(MyInt,2):1,NumFact,1); % 2)
DiffAuxVec = IntUsed - v; % 3)
w=NaN(1,size(DiffAuxVec,1));
for ii = 1:size(DiffAuxVec,1)
w(1,ii) = max(find(DiffAuxVec(ii,:)<0)); % 4)
end
x0 = MyInt(1,w)'; % Define x0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% b --> Compute the matrix B*, here indicated as B0. Each row in B0 is a
% trajectory for Morris Calculations. The dimension of B0 is (Numfactors+1,Numfactors)
if GroupNumber ~= 0
B0 = (A0*x0' + AuxMat);
else
B0 = (A0*x0' + AuxMat)*P0;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% c --> Compute values in the original intervals
% B0 has values x(i,j) in [0, 1/(p -1), 2/(p -1), ... , 1].
% To obtain values in the original intervals [LB, UB] we compute
% LB(j) + x(i,j)*(UB(j)-LB(j))
In = repmat(LB,1,sizeb)' + B0 .* repmat((UB-LB),1,sizeb)';
% Create the Factor vector. Each component of this vector indicate which factor or group of factor
% has been changed in each step of the trajectory.
Fact=NaN(1,sizea);
for j=1:sizea
Fact(1,j) = find(P0(j,:));
end
Fact(1,sizea+1) = 0;
Outmatrix = [Outmatrix; In];
OutFact = [OutFact; Fact'];
end