LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
example_fes_aggregation.m
1clear node jobclass
2
3% Flow-Equivalent Server (FES) Aggregation Example
4%
5% This example demonstrates how to use ModelAdapter.aggregateFES to replace
6% a subset of stations in a closed product-form queueing network with a
7% single Flow-Equivalent Server (FES).
8%
9% The FES has Limited Joint Dependence (LJD) service rates where the rate
10% for class-c in state (n1,...,nK) equals the throughput of class-c in an
11% isolated subnetwork consisting only of the subset stations.
12
13fprintf('=== Flow-Equivalent Server (FES) Aggregation Example ===\n\n');
14
15%% Create original 4-station tandem network with 2 classes
16fprintf('Creating original 4-station network...\n');
17
18N1 = 3; % number of class-1 jobs
19N2 = 2; % number of class-2 jobs
20
21model = Network('OriginalModel');
22
23% Create stations
24node{1} = Delay(model, 'ThinkTime');
25node{2} = Queue(model, 'Queue1', SchedStrategy.PS);
26node{3} = Queue(model, 'Queue2', SchedStrategy.PS);
27node{4} = Queue(model, 'Queue3', SchedStrategy.PS);
28
29% Create job classes
30jobclass{1} = ClosedClass(model, 'Class1', N1, node{1}, 0);
31jobclass{2} = ClosedClass(model, 'Class2', N2, node{1}, 0);
32
33% Set service times
34node{1}.setService(jobclass{1}, Exp.fitMean(5.0));
35node{1}.setService(jobclass{2}, Exp.fitMean(4.0));
36
37node{2}.setService(jobclass{1}, Exp.fitMean(1.5));
38node{2}.setService(jobclass{2}, Exp.fitMean(2.0));
39
40node{3}.setService(jobclass{1}, Exp.fitMean(1.0));
41node{3}.setService(jobclass{2}, Exp.fitMean(1.2));
42
43node{4}.setService(jobclass{1}, Exp.fitMean(0.8));
44node{4}.setService(jobclass{2}, Exp.fitMean(1.0));
45
46% Set up tandem routing (all jobs visit all stations in order)
47P = model.initRoutingMatrix();
48P{1,1} = [0, 1, 0, 0;
49 0, 0, 1, 0;
50 0, 0, 0, 1;
51 1, 0, 0, 0];
52P{2,2} = P{1,1};
53model.link(P);
54
55%% Solve original model with MVA
56fprintf('\n--- Solving Original Model ---\n');
57solverOriginal = SolverMVA(model);
58AvgTableOriginal = solverOriginal.getAvgTable;
59fprintf('Original model results:\n');
60disp(AvgTableOriginal);
61
62%% Aggregate stations 2 and 3 into a Flow-Equivalent Server
63fprintf('\n--- Creating FES Model ---\n');
64fprintf('Aggregating Queue1 and Queue2 into a single FES...\n');
65
66stationSubset = {node{2}, node{3}};
67options.verbose = true;
68options.solver = 'mva';
69
70try
71 [fesModel, fesStation, deaggInfo] = ModelAdapter.aggregateFES(model, stationSubset, options);
72
73 fprintf('\nFES model created successfully!\n');
74 fprintf('FES station name: %s\n', fesStation.getName());
75 fprintf('Number of stations in FES model: %d\n', fesModel.getNumberOfStations());
76
77 %% Solve FES model
78 fprintf('\n--- Solving FES Model ---\n');
79 solverFES = SolverMVA(fesModel);
80 AvgTableFES = solverFES.getAvgTable;
81 fprintf('FES model results:\n');
82 disp(AvgTableFES);
83
84 %% Compare throughputs
85 fprintf('\n--- Throughput Comparison ---\n');
86
87 % Extract original throughputs (at Delay station, which is common)
88 for k = 1:length(jobclass)
89 className = jobclass{k}.name;
90
91 % Find throughput in original
92 for row = 1:height(AvgTableOriginal)
93 if strcmp(string(AvgTableOriginal.JobClass(row)), className) && ...
94 strcmp(string(AvgTableOriginal.Station(row)), 'ThinkTime')
95 tputOrig = AvgTableOriginal.Tput(row);
96 break;
97 end
98 end
99
100 % Find throughput in FES model
101 for row = 1:height(AvgTableFES)
102 if strcmp(string(AvgTableFES.JobClass(row)), className) && ...
103 strcmp(string(AvgTableFES.Station(row)), 'ThinkTime')
104 tputFES = AvgTableFES.Tput(row);
105 break;
106 end
107 end
108
109 relError = abs(tputOrig - tputFES) / max(tputOrig, 1e-10) * 100;
110 fprintf('%s: Original=%.4f, FES=%.4f, RelError=%.2f%%\n', ...
111 className, tputOrig, tputFES, relError);
112 end
113
114 %% Examine deaggregation info
115 fprintf('\n--- Deaggregation Info ---\n');
116 fprintf('Subset station indices: %s\n', mat2str(deaggInfo.subsetIndices));
117 fprintf('Complement station indices: %s\n', mat2str(deaggInfo.complementIndices));
118 fprintf('Cutoffs used: %s\n', mat2str(deaggInfo.cutoffs));
119 fprintf('FES node index: %d\n', deaggInfo.fesNodeIdx);
120
121catch ME
122 fprintf('Error during FES aggregation: %s\n', ME.message);
123 fprintf('Stack trace:\n');
124 for i = 1:length(ME.stack)
125 fprintf(' %s (line %d)\n', ME.stack(i).name, ME.stack(i).line);
126 end
127end
128
129fprintf('\n=== Example Complete ===\n');