Random generator seed for parallel simulation using fast restart

18 views (last 30 days)
I'm going to perform a monte carlo simulation by simulate a simulink model thousands of times. The model are built by blocks from SimEvent-toolbox and some standard blocks.
I use one simulink function block that are calling a MATLAB-function block. In here I try to simulate the break down of sensors during one year of service in the machine (which is the rest of the model).
MATLAB-function:
function [outputPort,log] = failureRate(time,lambda,nSensors)
persistent failed failedCount
if isempty(failed)
failed = false(1,nSensors);
failedCount = 0;
rng('shuffle')
end
% Failure rate function and random variable
failRate = @(t,lam) 1 - exp(-t*lam);
r = rand(1,nSensors);
nBroken = 0;
% Check if sensors break or not
if any(r < failRate(time,lambda))
tmp = failed;
failed = max(failed, r < failRate(time,lambda));
if failedCount < sum(failed)
failedCount = sum(failed);
nBroken = sum(failed - tmp);
end
end
if all(failed)
% All sensors broken
outputPort = 2;
log = [nBroken,time];
else
% Some sensors still working
outputPort = 1;
log = [0, time];
end
end
This function is called each time an entity enters a "Entity Server"-block, which will decide which path it will go (failed sensor path or not).
I can run this model using a normal for loop using fast restart but as soon as I try to use Fast restart for any parallel computing the randomization becomes repeated.
I've tried following:
for i = 1:n
simIn(i) = Simulink.SimulationInput('SensorFailure');
simIn(i) = simIn(i).setPreSimFcn(@(x) rng('shuffle'));
end
but it does not work when Fast restart is actiaved using the parsim command. Also I've tried with and without the "SetupFnc" option in parsim (and all different combinations of these three.
out = parsim(simIn,...
'ShowSimulationManager','off',...
'ShowProgress','on',...
'TransferBaseWorkspaceVariables','on',...
'UseFastRestart','on',...
'SetupFcn',@() rng(randi(9999999)),...
'StopOnError','on');
I also tried using parfor loop but as long as fast restart is active the randomization will be repeated.
parfor i = 1:n
rng('shuffle') %tried with shuffle and randi(10000)
out = sim('SensorFailure','FastRestart','on');
data{i} = out.sensorfailed(out.sensorfailed(:,1) > 0,2);
if mod(i,10) == 0
disp(i)
end
end
Since I'm looking to run thousands of simulation and problably things will need to be redone once the results are analyzed any gain in simulation time is worth some time to investigate!
I've tried using rng('shuffle') and rng(randi(100000)) for all possible situations since I've understood that "shuffle" is not optimal for parallel computing. I've also tried these commands in the simulink models callback (initializing and start callbacks)

Accepted Answer

Niklas Larsson
Niklas Larsson on 13 Sep 2021
After a while I managed to find a solution that solved my problem!
By adding one more input parameter to the matlab function and feeding that input with a constant value-block:
function [outputPort,log] = failureRate(time,lambda,nSensors,seed)
persistent failed failedCount
if isempty(failed)
failed = false(1,nSensors);
failedCount = 0;
rng(seed) % Initiate with seed from constant block outside of function.
end
% Failure rate function and random variable
failRate = @(t,lam) 1 - exp(-t*lam);
r = rand(1,nSensors);
nBroken = 0;
if any(r < failRate(time,lambda))
tmp = failed;
failed = max(failed, r < failRate(time,lambda));
log = [0,0];
if failedCount < sum(failed)
failedCount = sum(failed);
nBroken = sum(failed - tmp);
end
end
if all(failed)
% All sensors broken
outputPort = 2;
log = [nBroken,time];
else
% Still working
outputPort = 1;
log = [nBroken > 0, time];
end
end
Then for each simulation in the SimulationInput-object randomize the seed value as below:
seedBlockPath = 'SensorFailure/Subsystem/Simulink Function/Seed';
for i = 1:n
% Set random seed for each simulation
simIn(i) = Simulink.SimulationInput('SensorFailure');
r = randi(99999);
simIn(i) = simIn(i).setBlockParameter(seedBlockPath,'Value',num2str(r));
end
out = parsim(simIn,...
'ShowSimulationManager','off',...
'ShowProgress','on',...
'TransferBaseWorkspaceVariables','on',...
'UseFastRestart','on',...
'StopOnError','on');
  13 Comments
Paul
Paul on 24 Sep 2021
Upon further thought, I'd like to change my very important assumption to be that the function failureRate() is called once per time step. So the variable step discrete solver should work fine as long as
the function failureRate keeps track of (or gets an input that is) the dt on each call, and
the dt on every time step is small enough so that the model still achieves a good approximation to the exponential distribution.
Niklas Larsson
Niklas Larsson on 27 Sep 2021
I guess that would work too if, as you say, the dt inbetween the calls are small enought. For my case I dont think it is.
Either way, thank you very much for your time and expertise!

Sign in to comment.

More Answers (1)

Abdolkarim Mohammadi
Abdolkarim Mohammadi on 10 Sep 2021
Edited: Abdolkarim Mohammadi on 10 Sep 2021
I do not know the solution to your problem, but I just want to mention that I faced a problem with SimEvents and parsim() with fast restart a while ago in R2020a, and I wrote about it here.
They reported it as a bug report here.
But the problem persists in R2021a. Maybe your problem relates to this bug.
  1 Comment
Edric Ellis
Edric Ellis on 13 Sep 2021
That bug reports indicates the problem was fixed in R2020b. If you can reproduce your problem in R2020b (or later), then something else must be going wrong - please contact MathWorks support with your reproduction steps.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!