1%% Example: Using Reward Templates
2% This example demonstrates the use of Reward
template factory methods
3%
for quickly defining common metrics like queue length, utilization, and blocking.
5% The
new Reward templates provide a convenient way to define metrics
6% without writing lambda expressions.
8% Copyright (c) 2012-2026, Imperial College London
14% Create an M/M/1 queue with finite buffer
16model = Network(
'RewardTemplatesExample');
19source = Source(model,
'Source');
20queue = Queue(model,
'Queue', SchedStrategy.FCFS);
21sink = Sink(model,
'Sink');
24queue.setNumberOfServers(1);
28oclass = OpenClass(model,
'Class1');
29source.setArrival(oclass, Exp(1.5)); % Arrival rate = 1.5
30queue.setService(oclass, Exp(2)); % Service rate = 2 (rho = 0.75)
33model.link(Network.serialRouting(source, queue, sink));
35%% Define Rewards Using Templates
36% Reward templates provide a clean syntax
for common metrics
38fprintf(
'Defining reward metrics using Reward templates:\n\n');
40% Template 1: Queue Length
41% Returns the total number of jobs in the queue (all
classes)
42model.setReward(
'QueueLength', Reward.queueLength(queue));
43fprintf(
' ✓ QueueLength = Reward.queueLength(queue)\n');
45% Template 2: Queue Length
for Specific Class
46% Returns the number of jobs of a specific
class in the queue
47model.setReward(
'QueueLength_Class1', Reward.queueLength(queue, oclass));
48fprintf(
' ✓ QueueLength_Class1 = Reward.queueLength(queue, oclass)\n');
50% Template 3: Server Utilization
51% Returns min(jobs, nservers) - the utilization of the server(s)
52model.setReward(
'Utilization', Reward.utilization(queue));
53fprintf(
' ✓ Utilization = Reward.utilization(queue)\n');
55% Template 4: Utilization by Class
56% Returns the utilization contributed by a specific
class
57model.setReward(
'Utilization_Class1', Reward.utilization(queue, oclass));
58fprintf(
' ✓ Utilization_Class1 = Reward.utilization(queue, oclass)\n');
60% Template 5: Blocking Probability
61% Returns 1
if queue
is at capacity, 0 otherwise
62model.setReward(
'BlockingProb', Reward.blocking(queue));
63fprintf(
' ✓ BlockingProb = Reward.blocking(queue)\n');
65%% Solve with CTMC Solver
66fprintf(
'\nSolving with CTMC solver...\n\n');
68options = Solver.defaultOptions;
71solver = CTMC(model, options);
73%% Get Steady-State Expected Rewards
74[R, names] = solver.getAvgReward();
76fprintf(
'=== Steady-State Expected Rewards (Templates) ===\n');
77fprintf(
'%-25s: %10.6f\n',
'QueueLength', R(1));
78fprintf(
'%-25s: %10.6f\n',
'QueueLength_Class1', R(2));
79fprintf(
'%-25s: %10.6f\n',
'Utilization', R(3));
80fprintf(
'%-25s: %10.6f\n',
'Utilization_Class1', R(4));
81fprintf(
'%-25s: %10.6f\n',
'BlockingProb', R(5));
83%% Analytical Comparison
84fprintf(
'\n=== Comparison with M/M/1 Analytical Results ===\n');
86lambda = 1.5; % Arrival rate
89K = 10; % Buffer capacity
91% Steady-state probabilities
94 pi(n+1) = (1 - rho) * rho^n / (1 - rho^(K+1));
98L_analytical = sum((0:K)
' .* pi); % Expected queue length
99U_analytical = 1 - pi(1); % Utilization
100B_analytical = pi(end); % Blocking probability
102fprintf('%-25s: LINE = %10.6f, Analytical = %10.6f, Error = %.2e\n
', ...
103 'QueueLength
', R(1), L_analytical, abs(R(1) - L_analytical));
104fprintf('%-25s: LINE = %10.6f, Analytical = %10.6f, Error = %.2e\n
', ...
105 'Utilization
', R(3), U_analytical, abs(R(3) - U_analytical));
106fprintf('%-25s: LINE = %10.6f, Analytical = %10.6f, Error = %.2e\n
', ...
107 'BlockingProb
', R(5), B_analytical, abs(R(5) - B_analytical));
109fprintf('\n✓ Example completed successfully.\n
');
110fprintf(' All template-based rewards match analytical results!\n
');