LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
rewardModel_mm1k.m
1%% Example: Using setReward for reward-based CTMC analysis
2% This example demonstrates the setReward feature for defining custom
3% reward functions on a queueing network model and computing steady-state
4% expected rewards using the CTMC solver.
5%
6% Copyright (c) 2012-2026, Imperial College London
7% All rights reserved.
8
9clear; clc;
10
11%% Model Definition
12% Create a simple M/M/1/K queue with finite buffer
13
14model = Network('RewardExample');
15
16% Block 1: nodes
17source = Source(model, 'Source');
18queue = Queue(model, 'Queue', SchedStrategy.FCFS);
19sink = Sink(model, 'Sink');
20
21% Set finite buffer capacity
22queue.setNumberOfServers(1);
23queue.setCapacity(3); % Maximum jobs in the system
24
25% Block 2: job classes
26oclass = OpenClass(model, 'Class1');
27source.setArrival(oclass, Exp(2)); % Arrival rate = 2
28queue.setService(oclass, Exp(3)); % Service rate = 3 (utilization ~ 0.67)
29
30% Block 3: topology
31model.link(Network.serialRouting(source,queue,sink));
32
33%% Define Reward Functions
34% setReward(name, rewardFn) where rewardFn uses RewardState for clear state access
35% The new API provides intuitive methods: state.at(node, class), state.at(node).total(), etc.
36
37% Reward 1: Queue length (number of jobs in the queue)
38% Old way: state(2) - unclear what state(2) means
39% New way: state.at(queue, oclass) - clear reference to queue and class
40model.setReward('QueueLength', @(state) state.at(queue, oclass));
41
42% Reward 2: Utilization (1 if server busy, 0 if idle)
43% Using Reward template for clarity
44model.setReward('Utilization', Reward.utilization(queue, oclass));
45
46% Reward 3: Blocking indicator (1 if buffer full, 0 otherwise)
47% Using Reward template for common metric
48model.setReward('BlockingProb', Reward.blocking(queue));
49
50% Reward 4: Weighted queue cost (quadratic penalty for long queues)
51% Custom reward using state accessor
52model.setReward('QueueCost', @(state) state.at(queue, oclass)^2);
53
54%% Solve with CTMC Solver
55fprintf('Solving with CTMC solver...\n\n');
56
57options = Solver.defaultOptions;
58options.verbose = 1;
59
60solver = CTMC(model, options);
61
62%% Get Steady-State Expected Rewards
63[R, names] = solver.getAvgReward();
64
65fprintf('\n=== Steady-State Expected Rewards ===\n');
66for i = 1:length(names)
67 fprintf('%15s: %.6f\n', names{i}, R(i));
68end
69
70%% Get Transient Reward Analysis
71% Track the expected reward E[r(X(t))] over time using getTranReward.
72% Transient analysis requires a finite timespan [0, Tmax].
73Tmax = 5;
74tranSolver = CTMC(model, 'timespan', [0, Tmax], 'verbose', 0);
75[Rt, t, names] = tranSolver.getTranReward();
76
77fprintf('\n=== Transient Reward Analysis ===\n');
78fprintf('Time horizon: [0, %g]\n', Tmax);
79fprintf('Number of time points: %d\n', numel(t));
80
81%% Plot Transient Rewards Converging to Steady-State
82figure('Name', 'Transient Rewards', 'Position', [100 100 800 600]);
83
84nRewards = numel(names);
85for r = 1:nRewards
86 subplot(2, 2, r);
87
88 % Transient expected reward E[r(X(t))] starting from the empty state
89 plot(Rt{r}.t, Rt{r}.metric, 'LineWidth', 1.5);
90 hold on;
91 yline(R(r), 'r--', 'LineWidth', 1.5);
92 hold off;
93
94 xlabel('Time t');
95 ylabel('E[r(X(t))]');
96 title(sprintf('%s (Steady-state: %.4f)', names{r}, R(r)));
97 legend('Transient E[r(X(t))]', 'Steady-state', 'Location', 'best');
98 grid on;
99end
100
101sgtitle('Convergence of Transient Rewards to Steady-State');
102
103%% Compare with Analytical Results for M/M/1/K
104fprintf('\n=== Comparison with M/M/1/K Analytical Results ===\n');
105
106lambda = 2; % Arrival rate
107mu = 3; % Service rate
108rho = lambda / mu;
109K = 10; % Buffer capacity
110
111% For M/M/1/K queue, steady-state probabilities:
112% pi(n) = (1-rho) * rho^n / (1 - rho^(K+1))
113if rho ~= 1
114 pi = zeros(K+1, 1);
115 for n = 0:K
116 pi(n+1) = (1 - rho) * rho^n / (1 - rho^(K+1));
117 end
118else
119 pi = ones(K+1, 1) / (K+1);
120end
121
122% Analytical expected queue length
123L_analytical = sum((0:K)' .* pi);
124
125% Analytical utilization (P(server busy) = 1 - pi(0))
126U_analytical = 1 - pi(1);
127
128% Analytical blocking probability = pi(K)
129B_analytical = pi(end);
130
131% Analytical queue cost (E[N^2])
132Cost_analytical = sum(((0:K).^2)' .* pi);
133
134fprintf('%15s: LINE = %.6f, Analytical = %.6f, Error = %.2e\n', ...
135 'QueueLength', R(1), L_analytical, abs(R(1) - L_analytical));
136fprintf('%15s: LINE = %.6f, Analytical = %.6f, Error = %.2e\n', ...
137 'Utilization', R(2), U_analytical, abs(R(2) - U_analytical));
138fprintf('%15s: LINE = %.6f, Analytical = %.6f, Error = %.2e\n', ...
139 'BlockingProb', R(3), B_analytical, abs(R(3) - B_analytical));
140fprintf('%15s: LINE = %.6f, Analytical = %.6f, Error = %.2e\n', ...
141 'QueueCost', R(4), Cost_analytical, abs(R(4) - Cost_analytical));
142
143fprintf('\nExample completed successfully.\n');
Definition fjtag.m:157
Definition Station.m:245