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 unstable re-entrant line example
3%
4% This example implements the classic Lu-Kumar re-entrant line 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:
9% - 2 stations (servers)
10% - 4 job classes forming a re-entrant line
11% - Station 1 serves classes 1 and 4
12% - Station 2 serves classes 2 and 3
13% - Job path: Source -> Class1 -> Class2 -> Class3 -> Class4 -> Sink
14%
15% Under FCFS scheduling: The network is stable when all station
16% utilizations are < 1.
17%
18% Under certain priority policies (e.g., HOL with class 4 > class 1 at
19% station 1, and class 2 > class 3 at station 2): The network can become
20% unstable due to the "virtual bottleneck" phenomenon, even with
21% utilization < 1 at each station.
22%
23% Reference:
24% Lu, S.H. and Kumar, P.R. (1991), "Distributed Scheduling Based on Due
25% Dates and Buffer Priorities", IEEE Transactions on Automatic Control,
26% Vol. 36, No. 12, pp. 1406-1416.
27%
28% Usage:
29% model = gallery_lukumar_reentrant(); % FCFS scheduling (stable)
30% model = gallery_lukumar_reentrant('FCFS'); % FCFS scheduling (stable)
31% model = gallery_lukumar_reentrant('HOL'); % HOL priority scheduling
32% model = gallery_lukumar_reentrant('PS'); % Processor sharing
33%
34% Copyright (c) 2012-2026, Imperial College London
35% All rights reserved.
36
37if nargin < 1
38 schedStrategy = 'FCFS';
39end
40
41% Convert string to scheduling strategy
42switch upper(schedStrategy)
43 case 'FCFS'
44 sched1 = SchedStrategy.FCFS;
45 sched2 = SchedStrategy.FCFS;
46 case 'HOL'
47 sched1 = SchedStrategy.HOL;
48 sched2 = SchedStrategy.HOL;
49 case 'PS'
50 sched1 = SchedStrategy.PS;
51 sched2 = SchedStrategy.PS;
52 otherwise
53 sched1 = SchedStrategy.FCFS;
54 sched2 = SchedStrategy.FCFS;
55end
56
57model = Network('Lu-Kumar-Reentrant');
58
59%% Block 1: Nodes
60source = Source(model, 'Source');
61station1 = Queue(model, 'Station1', sched1);
62station2 = Queue(model, 'Station2', sched2);
63sink = Sink(model, 'Sink');
64
65%% Block 2: Job Classes
66% For HOL scheduling, priority is specified as the third parameter
67% Higher value = higher priority
68%
69% "Bad" priority policy for instability demonstration:
70% Station 1: Class 4 (priority 1) > Class 1 (priority 0)
71% Station 2: Class 2 (priority 1) > Class 3 (priority 0)
72%
73% Under this policy, jobs in Class 4 are served before Class 1 at Station 1,
74% and jobs in Class 2 are served before Class 3 at Station 2.
75
76class1 = OpenClass(model, 'Class1', 0); % Lower priority at Station 1
77class2 = OpenClass(model, 'Class2', 1); % Higher priority at Station 2
78class3 = OpenClass(model, 'Class3', 0); % Lower priority at Station 2
79class4 = OpenClass(model, 'Class4', 1); % Higher priority at Station 1
80
81%% Block 3: Arrival Process
82% External arrivals only to Class 1
83arrivalRate = 0.45; % arrival rate lambda
84source.setArrival(class1, Exp(arrivalRate));
85source.setArrival(class2, Disabled());
86source.setArrival(class3, Disabled());
87source.setArrival(class4, Disabled());
88
89%% Block 4: Service Times
90% Service rates chosen so that utilization at each station < 1
91% Station 1 serves Class 1 and Class 4
92% Station 2 serves Class 2 and Class 3
93%
94% Mean service times:
95% m1 = 1.0 (Class 1 at Station 1)
96% m2 = 1.0 (Class 2 at Station 2)
97% m3 = 1.0 (Class 3 at Station 2)
98% m4 = 1.0 (Class 4 at Station 1)
99%
100% Station utilizations:
101% rho1 = lambda * (m1 + m4) = 0.45 * (1 + 1) = 0.90 < 1
102% rho2 = lambda * (m2 + m3) = 0.45 * (1 + 1) = 0.90 < 1
103
104m1 = 1.0; % Mean service time for Class 1 at Station 1
105m2 = 1.0; % Mean service time for Class 2 at Station 2
106m3 = 1.0; % Mean service time for Class 3 at Station 2
107m4 = 1.0; % Mean service time for Class 4 at Station 1
108
109% Station 1 services (Class 1 and Class 4)
110station1.setService(class1, Exp(1/m1));
111station1.setService(class2, Disabled());
112station1.setService(class3, Disabled());
113station1.setService(class4, Exp(1/m4));
114
115% Station 2 services (Class 2 and Class 3)
116station2.setService(class1, Disabled());
117station2.setService(class2, Exp(1/m2));
118station2.setService(class3, Exp(1/m3));
119station2.setService(class4, Disabled());
120
121%% Block 5: Routing (Re-entrant Line Topology)
122% Job path: Source -> Class1@Station1 -> Class2@Station2 ->
123% Class3@Station2 -> Class4@Station1 -> Sink
124%
125% The re-entrant structure means jobs visit Station 1 twice (as Class 1
126% first, then as Class 4) and Station 2 twice (as Class 2 first, then
127% as Class 3).
128
129P = model.initRoutingMatrix();
130
131% Source -> Class1 at Station1
132P{class1, class1}(source, station1) = 1;
133
134% Class1 at Station1 -> Class2 at Station2 (class switch)
135P{class1, class2}(station1, station2) = 1;
136
137% Class2 at Station2 -> Class3 at Station2 (class switch, same station)
138P{class2, class3}(station2, station2) = 1;
139
140% Class3 at Station2 -> Class4 at Station1 (class switch)
141P{class3, class4}(station2, station1) = 1;
142
143% Class4 at Station1 -> Sink
144P{class4, class4}(station1, sink) = 1;
145
146model.link(P);
147
148end