Matlab - 随机漫步与边界,矢量化

时间:2013-01-09 22:48:10

标签: matlab vectorization

假设我有一个跳跃大小的矢量J和一个初始起点X_0。我也有边界0,B(假设0

在下面的代码中,我在许多示例中执行此操作。为了“修复”离开边界的那些,我必须循环遍历样本以检查...(不要认为有一个矢量化的“查找”)

% X_init is a row vector describing initial resource values to use for
% each sample

% J is matrix where each col is a sequence of Jumps (columns = sample #)
% In this code the jumps are subtracted, but same thing

X_intvl = repmat(X_init,NumJumps,1) - cumsum(J);
X = [X_init; X_intvl];
for sample = 1:NumSamples
    k = find(or(X_intvl(:,sample) > B, X_intvl(:,sample) < 0),1);
    while(~isempty(k))
        change = X_intvl(k-1,sample) - X_intvl(k,sample);
        X_intvl(k:end,sample) = X_intvl(k:end,sample)+change;
        k = find(or(X_intvl(:,sample) > B, X_intvl(:,sample) < 0),1);
    end
end

2 个答案:

答案 0 :(得分:2)

有趣的问题(+1)。

我前面遇到了类似的问题,虽然稍微复杂,因为我的下限和上限取决于t。我从来没有制定出完全矢量化的解决方案。最后,我发现最快的解决方案是单循环,其中包含每个步骤的约束。根据您的情况调整代码会产生以下结果:

%# Set the parameters
LB = 0; %# Lower bound
UB = 5; %# Upper bound
T = 100; %# Number of observations
N = 3; %# Number of samples
X0 = (1/2) * (LB + UB); %# Arbitrary start point halfway between LB and UB

%# Generate the jumps
Jump = randn(N, T-1);

%# Build the constrained random walk
X = X0 * ones(N, T);
for t = 2:T
    X(:, t) = max(min(X(:, t-1) + Jump(:, t-1), UB), 0);
end
X = X';

我很想知道这种方法是否比你目前所做的更快。我怀疑这将是约束在多于一个或两个地方绑定的情况。我不能自己测试,因为你提供的代码不是一个“工作”的例子,即我不能只是将它复制并粘贴到Matlab中并运行它,因为它取决于几个变量的示例(或模拟)值没有提供。我尝试自己调整它,但是无法让它正常工作?

UPDATE:我只是改变了代码,以便对列进行索引,并在行上对样本编制索引,然后在最后一步中转置X。这将使例程更有效,因为Matlab按列分配数字数组的内存 - 因此,当在数组的列中执行操作时(而不是跨行),它会更快。请注意,您只会注意到大N的加速。

最后的想法:目前,JIT加速器非常擅长在Matlab中制作单循环(双循环仍然很慢)。因此,我个人认为每次尝试在Matlab中获得完全向量化的解决方案,即没有循环时,你应该权衡一下,找到一个聪明的解决方案所需的努力是否值得提高效率的微小进步通过一个易于获得的方法,利用单个循环。重要的是要记住,当TN很小时,完全向量化的解决方案有时而不是涉及单个循环的解决方案!

答案 1 :(得分:2)

我想提出另一种矢量化解决方案。

所以,首先我们应该设置参数并生成随机Jumpls。我使用了与 Colin T Bowers 相同的参数集:

% Set the parameters
LB = 0; % Lower bound
UB = 20; % Upper bound
T = 1000; % Number of observations
N = 3; % Number of samples
X0 = (1/2) * (UB + LB); % Arbitrary start point halfway between LB and UB

% Generate the jumps
Jump = randn(N, T-1);

但我更改了代码:

% Generate initial data without bounds
X = cumsum(Jump, 2);

% Apply bounds
Amplitude = UB - LB;
nsteps = ceil( max(abs(X(:))) / Amplitude - 0.5 );
for ii = 1:nsteps
    ind = abs(X) > (1/2) * Amplitude;
    X(ind) = Amplitude * sign(X(ind)) - X(ind);
end

% Shifting X
X = X0 + X;

因此,我使用cumsum function进行智能后处理,而不是for循环。

NB 此解决方案的效果明显慢于 Colin T Bowers 的紧密边界(Amplitude < 5),但是对于松散边界({ {1}})它运行得更快。