1%% Tandem M/M/1 Queues (Series of Two M/M/1 Stations)
3% This example demonstrates:
4% - Product-form open queueing network (OQN)
5% - Series (tandem) configuration: Source → Queue1 → Queue2 → Sink
6% - CTMC solver
for exact analysis of multi-station networks
7% - Verification against theoretical results
8% - Comparison with traditional queueing theory
10% For a tandem M/M/1-M/M/1 system:
11% - Station 1: λ₁ = 0.6, μ₁ = 1.0
12% - Station 2: λ₂ = 0.6 (same as λ₁, since all jobs from Q1 go to Q2), μ₂ = 1.2
14% - System
is product-form: π(n₁,n₂) = π₁(n₁)π₂(n₂)
18fprintf(
'========================================================================\n');
19fprintf(
'Tandem M/M/1 Queues (Series of Two Stations)\n');
20fprintf(
'========================================================================\n');
24% =========================================================================
26% =========================================================================
27model = Network(
'tandem_mm1');
29% Source sends jobs to Queue1
30source = Source(model,
'source');
32% Queue 1: λ₁ = 0.6, μ₁ = 1.0 (ρ₁ = 0.6)
33queue1 = Queue(model,
'queue1', SchedStrategy.FCFS);
35% Queue 2: λ₂ = 0.6, μ₂ = 1.2 (ρ₂ = 0.5)
36queue2 = Queue(model,
'queue2', SchedStrategy.FCFS);
38% Sink receives departures
39sink = Sink(model,
'sink');
44% =========================================================================
45% Define arrival and service processes
46% =========================================================================
47% External arrivals: λ = 0.6 (mean = 1/0.6 ≈ 1.667)
48source.setArrival(
jobclass, Exp.fit_mean(1/0.6));
50% Queue 1 service: μ₁ = 1.0 (mean = 1.0)
51queue1.setService(
jobclass, Exp.fit_mean(1.0));
53% Queue 2 service: μ₂ = 1.2 (mean = 1/1.2 ≈ 0.833)
54queue2.setService(
jobclass, Exp.fit_mean(1/1.2));
56% =========================================================================
57% Define routing: Source → Queue1 → Queue2 → Sink
58% =========================================================================
59R = model.init_routing_matrix();
72% =========================================================================
74% =========================================================================
75fprintf(
'\nSolving tandem M/M/1 system with CTMC...\n');
76fprintf(
'Parameters:\n');
77fprintf(
' Station 1: λ=0.6, μ=1.0, ρ=0.6\n');
78fprintf(
' Station 2: λ=0.6, μ=1.2, ρ=0.5\n\n');
80solver = SolverCTMC(model);
81avg_table = solver.getAvgTable();
83fprintf(
'CTMC Results for Tandem M/M/1:\n');
86% =========================================================================
87% Extract metrics
for each station
88% =========================================================================
89q1_idx = find(strcmp(avg_table.Node,
'queue1'));
90q2_idx = find(strcmp(avg_table.Node,
'queue2'));
92q1_qlen = avg_table.QLen(q1_idx);
93q1_util = avg_table.Util(q1_idx);
94q1_respt = avg_table.RespT(q1_idx);
95q1_tput = avg_table.Tput(q1_idx);
97q2_qlen = avg_table.QLen(q2_idx);
98q2_util = avg_table.Util(q2_idx);
99q2_respt = avg_table.RespT(q2_idx);
100q2_tput = avg_table.Tput(q2_idx);
102fprintf(
'\n========================================================================\n');
103fprintf(
'CTMC Results Summary:\n');
104fprintf(
'========================================================================\n');
106fprintf(
'\nQueue 1:\n');
107fprintf(
' Queue Length: %.6f\n', q1_qlen);
108fprintf(
' Utilization: %.6f\n', q1_util);
109fprintf(
' Response Time: %.6f\n', q1_respt);
110fprintf(
' Throughput: %.6f\n', q1_tput);
112fprintf(
'\nQueue 2:\n');
113fprintf(
' Queue Length: %.6f\n', q2_qlen);
114fprintf(
' Utilization: %.6f\n', q2_util);
115fprintf(
' Response Time: %.6f\n', q2_respt);
116fprintf(
' Throughput: %.6f\n', q2_tput);
118% =========================================================================
119% Theoretical M/M/1 results (product-form)
120% =========================================================================
125rho1 = lambda_rate / mu1;
126rho2 = lambda_rate / mu2;
128% M/M/1 formulas: L = ρ/(1-ρ), W = 1/(μ(1-ρ))
129L1 = rho1 / (1 - rho1);
130L2 = rho2 / (1 - rho2);
132W1 = 1 / (mu1 * (1 - rho1));
133W2 = 1 / (mu2 * (1 - rho2));
139fprintf(
'\n========================================================================\n');
140fprintf(
'Theoretical Results (Product-Form M/M/1-M/M/1):\n');
141fprintf(
'========================================================================\n');
143fprintf(
'\nQueue 1 (λ=0.6, μ=1.0, ρ=0.6):\n');
144fprintf(
' Queue Length (L₁): %.6f\n', L1);
145fprintf(
' Response Time (W₁): %.6f\n', W1);
146fprintf(
' Utilization (ρ₁): %.6f\n', rho1);
148fprintf(
'\nQueue 2 (λ=0.6, μ=1.2, ρ=0.5):\n');
149fprintf(
' Queue Length (L₂): %.6f\n', L2);
150fprintf(
' Response Time (W₂): %.6f\n', W2);
151fprintf(
' Utilization (ρ₂): %.6f\n', rho2);
153fprintf(
'\nSystem Totals:\n');
154fprintf(
' Total Queue Length: %.6f\n', L_system);
155fprintf(
' Total Response Time: %.6f\n', W_system);
157% =========================================================================
158% Comparison and Validation
159% =========================================================================
160fprintf(
'\n========================================================================\n');
161fprintf(
'COMPARISON: CTMC vs Theory\n');
162fprintf(
'========================================================================\n');
166fprintf(
'\nQueue 1:\n');
167diff = abs(q1_qlen - L1) / L1 * 100;
169if diff > tolerance * 100
172fprintf(
'%s Queue Length: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q1_qlen, L1, diff);
174diff = abs(q1_respt - W1) / W1 * 100;
176if diff > tolerance * 100
179fprintf(
'%s Response Time: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q1_respt, W1, diff);
181diff = abs(q1_util - rho1) / rho1 * 100;
183if diff > tolerance * 100
186fprintf(
'%s Utilization: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q1_util, rho1, diff);
188fprintf(
'\nQueue 2:\n');
189diff = abs(q2_qlen - L2) / L2 * 100;
191if diff > tolerance * 100
194fprintf(
'%s Queue Length: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q2_qlen, L2, diff);
196diff = abs(q2_respt - W2) / W2 * 100;
198if diff > tolerance * 100
201fprintf(
'%s Response Time: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q2_respt, W2, diff);
203diff = abs(q2_util - rho2) / rho2 * 100;
205if diff > tolerance * 100
208fprintf(
'%s Utilization: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q2_util, rho2, diff);
210fprintf(
'\nSystem:\n');
211diff = abs(q1_qlen + q2_qlen - L_system) / L_system * 100;
213if diff > tolerance * 100
216fprintf(
'%s Total QLen: CTMC=%.6f, Theory=%.6f (diff=%.2f%%)\n', status, q1_qlen + q2_qlen, L_system, diff);
218% =========================================================================
220% =========================================================================
221fprintf(
'\n========================================================================\n');
223fprintf(
'========================================================================\n');
224fprintf(
'\n✓ CTMC successfully analyzes tandem M/M/1-M/M/1 system\n');
225fprintf(
'✓ Product-form property verified:\n');
226fprintf(
' - Each station behaves independently as M/M/1\n');
227fprintf(
' - System decomposition holds\n');
228fprintf(
'✓ Results match theoretical predictions\n');
229fprintf(
'✓ CTMC feature support is working correctly!\n');
230fprintf(
'========================================================================\n');