2%% Example: EKF sliding-window change-point detection (open network)
4% Service demand changes from D=0.3 to D=0.6 at t=100.
5% A sliding window of size W feeds the EKF, which
is warm-started
6% from the previous window
's estimate for stable tracking.
8% Copyright (c) 2012-2026, Imperial College London
12model = Network('model
');
14node{1} = Delay(model, 'Delay
');
15node{2} = Queue(model, 'Queue1
', SchedStrategy.FCFS);
16node{3} = Source(model, 'Source
');
17node{4} = Sink(model, 'Sink
');
19jobclass{1} = OpenClass(model, 'Class1
', 0);
21node{1}.setService(jobclass{1}, Exp.fitMean(1.0));
22node{2}.setService(jobclass{1}, Exp(NaN));
23node{3}.setArrival(jobclass{1}, Exp(1.0));
25P = model.initRoutingMatrix;
26P{1,1} = [0,1,0,0; 0,0,0,1; 1,0,0,0; 0,0,0,0];
29%% Generate data with change point
38arvr_samples = lambda*ones(n,1) + randn(n,1)*noise;
40util_samples = zeros(n,1);
41respt_samples = zeros(n,1);
48 U = lambda * D + randn(1)*noise;
49 U = max(0.01, min(0.95, U));
51 respt_samples(t) = D / (1 - U) + randn(1)*noise*0.1;
54%% Sliding-window estimation with warm-start
56estimates = zeros(n - W + 1, 1);
57prevEst = []; % warm-start: empty
for first window (random init)
62 node{2}.setService(
jobclass{1}, Exp(NaN));
65 estoptions = ParamEstimator.defaultOptions;
66 estoptions.method =
'ekf';
67 estoptions.x0 = prevEst; % warm-start from previous estimate
68 se = ParamEstimator(model, estoptions);
70 se.addSamples(SampledMetric(MetricType.ArvR, ts(idx), arvr_samples(idx), node{2},
jobclass{1}));
71 se.addSamples(SampledMetric(MetricType.RespT, ts(idx), respt_samples(idx), node{2},
jobclass{1}));
72 se.addSamples(SampledMetric(MetricType.Util, ts(idx), util_samples(idx), node{2}));
74 estVal = se.estimateAt(node{2});
75 estimates(t - W + 1) = estVal(1);
76 prevEst = estVal(:); % pass to next window
81fprintf(1, '\n=== EKF Change-Point Detection (warm-start) ===\n
');
82fprintf(1, 'True demand: D=%.1f (t<=100), D=%.1f (t>100)\n
', D1, D2);
83fprintf(1, 'Window size: %d\n\n
', W);
85checkpoints = [W, 50, 80, 100, 110, 120, 130, 150, 180, 200];
86fprintf(1, '%6s %10s %10s\n
', 't
', 'Estimated
', 'True
');
87fprintf(1, '%6s %10s %10s\n
', '------
', '----------
', '----------
');
88for i = 1:length(checkpoints)
91 est = estimates(t - W + 1);
97 fprintf(1, '%6d %10.4f %10.4f\n
', t, est, trueD);
103plot(tAxis, estimates, 'b-
', 'LineWidth
', 1.5); hold on;
104yline(D1, 'r--
', sprintf('D=%.1f
', D1), 'LineWidth
', 1);
105yline(D2, 'r--
', sprintf('D=%.1f
', D2), 'LineWidth
', 1);
106xline(changeT, 'k:
', 'Change point
', 'LineWidth
', 1);
108ylabel('Estimated Demand
');
109title('EKF Sliding-Window Change-Point Detection (warm-start)
');
110legend('EKF estimate
', 'Location
', 'southeast
');