LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
gallery_lukumar_reentrant.m
1function model = gallery_lukumar_reentrant(schedStrategy)
2% GALLERY_LUKUMAR_REENTRANT Lu-Kumar (Rybko-Stolyar) unstable network example
3%
4% This example implements the classic Lu-Kumar/Rybko-Stolyar network,
5% which demonstrates that queueing networks can be unstable even when
6% the utilization at each station is strictly less than 1.
7%
8% Network structure (two chains sharing two stations):
9% - 2 stations (servers)
10% - 4 job classes in 2 chains
11% - Chain 1: Source -> Class1@Station1 -> Class2@Station2 -> Sink
12% - Chain 2: Source -> Class3@Station2 -> Class4@Station1 -> Sink
13%
14% Under FCFS scheduling: The network is stable when all station
15% utilizations are < 1.
16%
17% Under the "bad" priority policy (HOL with class 1 > class 4 at
18% station 1, and class 3 > class 2 at station 2): The network becomes
19% unstable due to the "virtual bottleneck" phenomenon, even with
20% utilization < 1 at each station.
21%
22% Reference:
23% Lu, S.H. and Kumar, P.R. (1991), "Distributed Scheduling Based on Due
24% Dates and Buffer Priorities", IEEE Transactions on Automatic Control,
25% Vol. 36, No. 12, pp. 1406-1416.
26%
27% Rybko, A.N. and Stolyar, A.L. (1992), "Ergodicity of stochastic
28% processes describing the operation of open queueing networks",
29% Problems of Information Transmission, Vol. 28, pp. 199-220.
30%
31% Usage:
32% model = gallery_lukumar_reentrant(); % FCFS scheduling (stable)
33% model = gallery_lukumar_reentrant('FCFS'); % FCFS scheduling (stable)
34% model = gallery_lukumar_reentrant('HOL'); % HOL priority (unstable)
35% model = gallery_lukumar_reentrant('PS'); % Processor sharing (stable)
36%
37% Copyright (c) 2012-2026, Imperial College London
38% All rights reserved.
39
40if nargin < 1
41 schedStrategy = 'FCFS';
42end
43
44% Convert string to scheduling strategy
45switch upper(schedStrategy)
46 case 'FCFS'
47 sched1 = SchedStrategy.FCFS;
48 sched2 = SchedStrategy.FCFS;
49 case 'HOL'
50 sched1 = SchedStrategy.HOL;
51 sched2 = SchedStrategy.HOL;
52 case 'PS'
53 sched1 = SchedStrategy.PS;
54 sched2 = SchedStrategy.PS;
55 otherwise
56 sched1 = SchedStrategy.FCFS;
57 sched2 = SchedStrategy.FCFS;
58end
59
60model = Network('Lu-Kumar-Reentrant');
61
62%% Block 1: Nodes
63source = Source(model, 'Source');
64station1 = Queue(model, 'Station1', sched1);
65station2 = Queue(model, 'Station2', sched2);
66sink = Sink(model, 'Sink');
67
68%% Block 2: Job Classes
69% For HOL scheduling, priority is specified as the third parameter
70% Higher value = higher priority
71%
72% "Bad" priority policy for instability demonstration (FBFS):
73% Station 1: Class 1 (priority 1) > Class 4 (priority 0)
74% Station 2: Class 3 (priority 1) > Class 2 (priority 0)
75%
76% This prioritizes first-visit jobs at each station, creating a
77% "virtual bottleneck" that leads to instability.
78
79class1 = OpenClass(model, 'Class1', 1); % Higher priority at Station 1 (Chain 1, first visit)
80class2 = OpenClass(model, 'Class2', 0); % Lower priority at Station 2 (Chain 1, second visit)
81class3 = OpenClass(model, 'Class3', 1); % Higher priority at Station 2 (Chain 2, first visit)
82class4 = OpenClass(model, 'Class4', 0); % Lower priority at Station 1 (Chain 2, second visit)
83
84%% Block 3: Arrival Process
85% External arrivals to Class 1 (Chain 1) and Class 3 (Chain 2)
86arrivalRate = 0.08; % arrival rate lambda for each chain
87source.setArrival(class1, Exp(arrivalRate)); % Chain 1 arrivals
88source.setArrival(class2, Disabled());
89source.setArrival(class3, Exp(arrivalRate)); % Chain 2 arrivals
90source.setArrival(class4, Disabled());
91
92%% Block 4: Service Times
93% ASYMMETRIC service times - classic Kumar-Seidman instability configuration
94% First-visit classes (Class1, Class3) have SLOW service (m=10)
95% Second-visit classes (Class2, Class4) have FAST service (m=1)
96%
97% This asymmetry creates the "virtual bottleneck" that causes instability
98% under FBFS priority policy, even with physical utilization < 100%.
99%
100% Mean service times:
101% m1 = 10.0 (Class 1 at Station 1) - slow first visit
102% m2 = 1.0 (Class 2 at Station 2) - fast second visit
103% m3 = 10.0 (Class 3 at Station 2) - slow first visit
104% m4 = 1.0 (Class 4 at Station 1) - fast second visit
105%
106% Station utilizations (with lambda=0.08 per chain):
107% rho1 = lambda * (m1 + m4) = 0.08 * (10 + 1) = 0.88 < 1
108% rho2 = lambda * (m2 + m3) = 0.08 * (1 + 10) = 0.88 < 1
109
110m1 = 10.0; % Mean service time for Class 1 at Station 1 (slow)
111m2 = 1.0; % Mean service time for Class 2 at Station 2 (fast)
112m3 = 10.0; % Mean service time for Class 3 at Station 2 (slow)
113m4 = 1.0; % Mean service time for Class 4 at Station 1 (fast)
114
115% Station 1 services (Class 1 and Class 4)
116station1.setService(class1, Exp(1/m1));
117station1.setService(class2, Disabled());
118station1.setService(class3, Disabled());
119station1.setService(class4, Exp(1/m4));
120
121% Station 2 services (Class 2 and Class 3)
122station2.setService(class1, Disabled());
123station2.setService(class2, Exp(1/m2));
124station2.setService(class3, Exp(1/m3));
125station2.setService(class4, Disabled());
126
127%% Block 5: Routing (Two-Chain Topology)
128% Chain 1: Source -> Class1@Station1 -> Class2@Station2 -> Sink
129% Chain 2: Source -> Class3@Station2 -> Class4@Station1 -> Sink
130%
131% This is the classic Lu-Kumar/Rybko-Stolyar network topology where
132% two chains share two stations, visiting them in opposite order.
133
134P = model.initRoutingMatrix();
135
136% Chain 1 routing
137P{class1, class1}(source, station1) = 1; % Source -> Class1@Station1
138P{class1, class2}(station1, station2) = 1; % Class1@Station1 -> Class2@Station2
139P{class2, class2}(station2, sink) = 1; % Class2@Station2 -> Sink
140
141% Chain 2 routing
142P{class3, class3}(source, station2) = 1; % Source -> Class3@Station2
143P{class3, class4}(station2, station1) = 1; % Class3@Station2 -> Class4@Station1
144P{class4, class4}(station1, sink) = 1; % Class4@Station1 -> Sink
145
146model.link(P);
147
148end