LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
example_infer_ekf_changepoint.m
1clear node jobclass
2%% Example: EKF sliding-window change-point detection (open network)
3%
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.
7%
8% Copyright (c) 2012-2026, Imperial College London
9% All rights reserved.
10
11%% define model
12model = Network('model');
13
14node{1} = Delay(model, 'Delay');
15node{2} = Queue(model, 'Queue1', SchedStrategy.FCFS);
16node{3} = Source(model, 'Source');
17node{4} = Sink(model, 'Sink');
18
19jobclass{1} = OpenClass(model, 'Class1', 0);
20
21node{1}.setService(jobclass{1}, Exp.fitMean(1.0));
22node{2}.setService(jobclass{1}, Exp(NaN));
23node{3}.setArrival(jobclass{1}, Exp(1.0));
24
25P = model.initRoutingMatrix;
26P{1,1} = [0,1,0,0; 0,0,0,1; 1,0,0,0; 0,0,0,0];
27model.link(P);
28
29%% Generate data with change point
30n = 200;
31changeT = 100;
32D1 = 0.3;
33D2 = 0.6;
34lambda = 1.0;
35noise = 0.02;
36
37ts = (1:n)';
38arvr_samples = lambda*ones(n,1) + randn(n,1)*noise;
39
40util_samples = zeros(n,1);
41respt_samples = zeros(n,1);
42for t = 1:n
43 if t <= changeT
44 D = D1;
45 else
46 D = D2;
47 end
48 U = lambda * D + randn(1)*noise;
49 U = max(0.01, min(0.95, U));
50 util_samples(t) = U;
51 respt_samples(t) = D / (1 - U) + randn(1)*noise*0.1;
52end
53
54%% Sliding-window estimation with warm-start
55W = 30;
56estimates = zeros(n - W + 1, 1);
57prevEst = []; % warm-start: empty for first window (random init)
58
59for t = W:n
60 idx = (t-W+1):t;
61
62 node{2}.setService(jobclass{1}, Exp(NaN));
63 model.reset();
64
65 estoptions = ParamEstimator.defaultOptions;
66 estoptions.method = 'ekf';
67 estoptions.x0 = prevEst; % warm-start from previous estimate
68 se = ParamEstimator(model, estoptions);
69
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}));
73 se.interpolate();
74 estVal = se.estimateAt(node{2});
75 estimates(t - W + 1) = estVal(1);
76 prevEst = estVal(:); % pass to next window
77end
78
79%% Report results
80tAxis = (W:n)';
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);
84
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)
89 t = checkpoints(i);
90 if t >= W && t <= n
91 est = estimates(t - W + 1);
92 if t <= changeT
93 trueD = D1;
94 else
95 trueD = D2;
96 end
97 fprintf(1, '%6d %10.4f %10.4f\n', t, est, trueD);
98 end
99end
100
101%% Plot
102figure;
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);
107xlabel('Time');
108ylabel('Estimated Demand');
109title('EKF Sliding-Window Change-Point Detection (warm-start)');
110legend('EKF estimate', 'Location', 'southeast');
111grid on;