LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
getTranAvg.m
1function [QNclass_t, UNclass_t, TNclass_t] = getTranAvg(self,Qt,Ut,Tt)
2% [QNCLASS_T, UNCLASS_T, TNCLASS_T] = GETTRANAVG(SELF,QT,UT,TT)
3% Returns transient mean performance metrics over time
4%
5% @brief Computes transient queue length, utilization, and throughput time series
6%
7% This method returns transient performance metrics (time-dependent averages)
8% for each station and job class. The transient analysis tracks how metrics
9% evolve from the initial state toward steady state over the specified time span.
10%
11% The Fluid solver uses ODE-based mean-field approximations to compute transient
12% behavior efficiently. The method returns different data structures depending on
13% whether optional handles are provided.
14%
15% @param self SolverFluid instance (must have timespan configured, e.g.,
16% SolverFluid(model, 'timespan', [0, 50]))
17% @param Qt (optional) Queue length handle from previous computation. If provided,
18% returns cached results. Otherwise computes new QN(t).
19% @param Ut (optional) Utilization handle. If provided, uses cached results.
20% Otherwise computes new UN(t).
21% @param Tt (optional) Throughput handle. If provided, uses cached results.
22% Otherwise computes new TN(t).
23%
24% @return QNclass_t Nested cell array of queue length time series
25% - Structure: {station_1, station_2, ...} where each station contains
26% {class_1_timeseries, class_2_timeseries, ...}
27% - Each element is a vector of queue lengths at each time point
28% - Shape: [num_stations][num_classes] with each element a time-series array
29%
30% @return UNclass_t Nested cell array of utilization time series
31% - Same structure as QNclass_t but containing utilization values
32%
33% @return TNclass_t Nested cell array of throughput time series
34% - Same structure as QNclass_t but containing throughput values
35%
36% @note Transient analysis is only available for certain solvers (CTMC, Fluid, JMT).
37% Must configure timespan when creating solver instance:
38% solver = SolverFluid(model, 'timespan', [0, 100]);
39%
40% @warning The Fluid approximation is mean-field based and provides estimates
41% rather than exact transient probabilities. Use CTMC for small models
42% requiring exact transient analysis.
43%
44% @see getTranHandles - Get result handles for transient metrics
45% @see getAvg - Get steady-state average metrics
46%
47% Example:
48% @code
49% model = Network('example');
50% % ... model construction ...
51% solver = SolverFluid(model, 'timespan', [0, 50]);
52% [QN_t, UN_t, TN_t] = solver.getTranAvg();
53%
54% % Access queue length time series for station 0, class 1
55% qlen_time_series = QN_t{1}{2};
56% plot(qlen_time_series);
57% @endcode
58%
59% Copyright (c) 2012-2026, Imperial College London
60% All rights reserved.
61
62% temporarily switch to closing method
63if nargin == 1
64 [Qt,Ut,Tt] = self.getTranHandles;
65end
66
67options = self.options;
68% Force MATLAB path for transient analysis (Java path only produces steady-state)
69self.options.lang = 'matlab';
70
71% Cache models: the surrounding queueing metrics are still obtained from the
72% closing method, but the cache itself carries a genuine transient through
73% the refined mean-field (RMF) drift rather than the closing fallback (which
74% is cache-blind and would report an empty cache). The RMF cache trajectory
75% is integrated over the timespan and stashed on the solver result.
76sn = self.getStruct;
77hasCache = any(sn.nodetype == NodeType.Cache);
78
79% Detect NHPP (non-homogeneous Poisson) sources and pass their intensity
80% schedules to the closing ODE, so the transient tracks lambda(t) rather than
81% the baked-in time-average rate. Steady-state getAvg is unaffected (no
82% schedule injected there), consistent with defining the NHPP steady state as
83% its time average.
84self.options.config.nhpp_sched = local_detect_nhpp(self.model, sn);
85
86switch options.method
87 case {'default', 'matrix', 'closing', 'rmf', 'fluid.rmf'}
88 % These methods can switch to closing silently for the queueing
89 % transient (RMF caches keep their transient via cacheqn_tran below).
90 self.options.method = 'closing';
91 case {'tbi','fluid.tbi'}
92 % TBI integrates the closing ODEs by cell decomposition and
93 % produces a genuine transient; keep the method as is.
94 otherwise
95 line_warning(mfilename,'getTranAvg is not offered by the specified method. Setting the solution method to ''''closing''''.\n');
96 self.options.method = 'closing';
97 self.reset();
98end
99
100if hasCache
101 % The cache carries its own transient through the RMF drift.
102 tranopts = self.options;
103 tranopts.method = 'rmf';
104 tranopts.timespan = options.timespan;
105 [tcache, hitprob_t, missprob_t, caches, arate] = solver_fld_cacheqn_tran(sn, tranopts);
106 self.result.CacheTran = struct('t', tcache, 'hitprob', hitprob_t, ...
107 'missprob', missprob_t, 'nodes', caches, 'arate', arate);
108 % Station-level queueing transient via closing. A cache network with no
109 % genuine queueing station (e.g. Source->Cache->Sink) has an empty fluid
110 % ODE and cannot be integrated; its station metrics are then constant and
111 % equal to the steady-state values, which we build directly.
112 try
113 [QNclass_t, UNclass_t, TNclass_t] = getTranAvg@NetworkSolver(self,Qt,Ut,Tt);
114 catch
115 [QNclass_t, UNclass_t, TNclass_t] = local_const_tran(self, options.timespan);
116 end
117else
118 [QNclass_t, UNclass_t, TNclass_t] = getTranAvg@NetworkSolver(self,Qt,Ut,Tt);
119end
120
121self.options = options;
122end
123
124function sched = local_detect_nhpp(model, sn)
125% Build the nhpp_sched struct array (station index in sn station space, class,
126% process handle) for every EXT/source station carrying a non-homogeneous
127% arrival process (identified by the getRateSchedule method, as in
128% refreshProcessRepresentations). Empty when there is none.
129sched = [];
130for i = 1:sn.nstations
131 if sn.sched(i) ~= SchedStrategy.EXT
132 continue
133 end
134 node = model.nodes{sn.stationToNode(i)};
135 if ~isa(node, 'Source')
136 continue
137 end
138 for c = 1:sn.nclasses
139 if numel(node.input.sourceClasses) < c || isempty(node.input.sourceClasses{c})
140 continue
141 end
142 proc = node.input.sourceClasses{c}{end};
143 if ismethod(proc, 'getRateSchedule')
144 entry = struct('station', i, 'class', c, 'nhpp', proc);
145 if isempty(sched)
146 sched = entry;
147 else
148 sched(end+1) = entry; %#ok<AGROW>
149 end
150 end
151 end
152end
153end
154
155function [QNt, UNt, TNt] = local_const_tran(self, timespan)
156% Build constant transient handles from the steady-state solution, for cache
157% networks whose queueing part has no fluid dynamics to integrate.
158solver = FLD(self.model, 'method', 'rmf');
159[QN, UN, ~, TN] = solver.getAvg();
160M = size(QN, 1); K = size(QN, 2);
161t0 = timespan(1); if isinf(t0), t0 = 0; end
162tcol = [t0; timespan(2)];
163QNt = cell(M, K); UNt = cell(M, K); TNt = cell(M, K);
164for i = 1:M
165 for r = 1:K
166 QNt{i,r} = [QN(i,r); QN(i,r)]; QNt{i,r}(:,2) = tcol;
167 UNt{i,r} = [UN(i,r); UN(i,r)]; UNt{i,r}(:,2) = tcol;
168 TNt{i,r} = [TN(i,r); TN(i,r)]; TNt{i,r}(:,2) = tcol;
169 end
170end
171end
Definition Station.m:245