LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
lqn_paramident.m
1% LQN_PARAMIDENT Identify hidden LQN parameters from measured performance.
2%
3% Demonstrates infer_lqn, an Extended Kalman Filter that tracks hidden LQN
4% parameters (host demands, think times) from measurable performance data,
5% following Zheng, Yang, Woodside, Litoiu, Iszlai, "Tracking Time-Varying
6% Parameters in Software Systems with Extended Kalman Filters", CASCON 2005.
7%
8% Here two parameters are hidden: the reference-task think time (the paper's Z)
9% and the P2 host demand of activity AS3 (the paper's service demand S_d). The
10% measurable vector is [R(E1), U(P1), U(P2)] (a user response time and two
11% processor utilizations). We synthesise a measurement sequence with a step
12% change plus noise, then recover the parameter trajectory.
13
14clear; lineStart;
15rng(12345);
16
17% ---- base LQN (mirrors lqn_basic.m) ----------------------------------------
18model = LayeredNetwork('paramident_LQN');
19P1 = Processor(model, 'P1', 2, SchedStrategy.PS);
20P2 = Processor(model, 'P2', 3, SchedStrategy.PS);
21T1 = Task(model, 'T1', 50, SchedStrategy.REF).on(P1).setThinkTime(Exp(1/2));
22T2 = Task(model, 'T2', 50, SchedStrategy.FCFS).on(P1).setThinkTime(Exp(1/3));
23T3 = Task(model, 'T3', 25, SchedStrategy.FCFS).on(P2).setThinkTime(Exp(1/4));
24E1 = Entry(model, 'E1').on(T1);
25E2 = Entry(model, 'E2').on(T2);
26E3 = Entry(model, 'E3').on(T3);
27A1 = Activity(model, 'AS1', Exp(10)).on(T1).boundTo(E1).synchCall(E2, 1);
28A2 = Activity(model, 'AS2', Exp(20)).on(T2).boundTo(E2).synchCall(E3, 5).repliesTo(E2);
29A3 = Activity(model, 'AS3', Exp(50)).on(T3).boundTo(E3).repliesTo(E3);
30
31% ---- what to estimate (paramSpec) and what is observed (obsSpec) -----------
32paramSpec = struct('type', {'think', 'hostdem'}, 'name', {'T1', 'AS3'});
33obsSpec = struct('metric', {'RespT', 'Util', 'Util'}, 'name', {'E1', 'P1', 'P2'});
34
35% ---- ground-truth parameter trajectory with a step change ------------------
36nsteps = 24;
37aTrueSeq = zeros(2, nsteps);
38aTrueSeq(1, :) = 0.5; % think time Z
39aTrueSeq(2, :) = 1/50; % S_d = AS3 mean host demand
40aTrueSeq(1, 13:end) = 1.0; % step: think time doubles at step 13
41aTrueSeq(2, 7:18) = 1/25; % pulse: S_d doubles for steps 7..18
42
43% ---- synthesise the measurement matrix Z from the true model + noise -------
44solveropts = SolverLN.defaultOptions; solveropts.verbose = VerboseLevel.SILENT;
45no = numel(obsSpec);
46Z = zeros(no, nsteps);
47for k = 1:nsteps
48 infer_lqn_setparams(model, paramSpec, aTrueSeq(:, k));
49 [QN, UN, RN, TN] = SolverLN(model, solveropts).getEnsembleAvg();
50 lsn = model.getStruct();
51 ztrue = infer_lqn_getobs(lsn.names, ...
52 struct('QLen', QN, 'Util', UN, 'RespT', RN, 'Tput', TN), obsSpec);
53 Z(:, k) = ztrue .* (1 + 0.02 * randn(no, 1)); % ~2% measurement noise
54end
55
56% ---- run the EKF identification --------------------------------------------
57opt = struct();
58opt.a0 = [0.7; 1/40]; % deliberately wrong initial guess
59opt.QFac = 0.1; % eq 9a drift-noise factor
60opt.RFac = 0.2; % eq 9b measurement-noise factor
61opt.gammaT = 1; % T = T* (measurement interval == system constant)
62opt.aTrue = aTrueSeq(:, end);
63[estModel, info] = infer_lqn(model, paramSpec, obsSpec, Z, opt);
64
65% ---- report -----------------------------------------------------------------
66fprintf('\nStep | Z_true Z_hat | Sd_true Sd_hat | ||e||\n');
67for k = 1:nsteps
68 fprintf('%4d | %6.3f %6.3f | %7.4f %7.4f | %.3g\n', k, ...
69 aTrueSeq(1, k), info.ahat(1, k), aTrueSeq(2, k), info.ahat(2, k), ...
70 norm(info.e(:, k)));
71end
72fprintf('\nFinal estimate: Z = %.4f (true %.4f), Sd = %.5f (true %.5f)\n', ...
73 info.ahat(1, end), aTrueSeq(1, end), info.ahat(2, end), aTrueSeq(2, end));
74fprintf('RMS parameter tracking error Ea = %.4g, prediction error Er = %.4g\n', ...
75 info.Ea, info.Er);
Definition Station.m:245