LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
refreshProcessRepresentations.m
1function [ph, phases] = refreshProcessRepresentations(self)
2% [PH, PHASES] = REFRESHPROCESSREPRESENTATIONS()
3
4% Copyright (c) 2012-2026, Imperial College London
5% All rights reserved.
6
7
8M = getNumberOfStations(self);
9K = getNumberOfClasses(self);
10ph = cell(M,1);
11for ist=1:M
12 ph{ist,1} = cell(1,K);
13end
14phases = zeros(M,K);
15stations = self.stations;
16for ist=1:M
17 if ist == self.getIndexSourceStation
18 ph_i = stations{ist}.getSourceRates();
19 else
20 switch class(stations{ist})
21 case 'Fork'
22 mu_i = cell(1,K);
23 phi_i = cell(1,K);
24 for r=1:K
25 mu_i{r} = NaN;
26 phi_i{r} = NaN;
27 end
28 ph_i = Coxian(mu_i,phi_i).getProcess;
29 case 'Join'
30 mu_i = cell(1,K);
31 phi_i = cell(1,K);
32 for r=1:K
33 mu_i{r} = NaN;
34 phi_i{r} = NaN;
35 ph_i{r} = Coxian(mu_i{r},phi_i{r}).getProcess;
36 end
37 otherwise
38 ph_i = stations{ist}.getServiceRates();
39 end
40 end
41 for r=1:K
42 ph{ist}{r} = ph_i{r};
43 if isempty(ph{ist}{r}) % fluid fails otherwise
44 phases(ist,r) = 1;
45 elseif ~isMAP(ph{ist}{r})
46 % Non-Markovian distribution: convert to MAP representation
47 ph{ist}{r} = convertToMAP(stations{ist}, r, ph{ist}{r});
48 phases(ist,r) = length(ph{ist}{r}{1});
49 elseif any(isnan(ph{ist}{r}{1}(:))) || any(isnan(ph{ist}{r}{2}(:))) % disabled
50 phases(ist,r) = 0;
51 else
52 phases(ist,r) = length(ph{ist}{r}{1});
53 end
54 end
55end
56if ~isempty(self.sn) %&& isprop(self.sn,'mu')
57 proc = ph;
58 pie = cell(size(ph));
59 for ist=1:M
60 for r=1:K
61 map_ir = ph{ist}{r};
62 if ~isempty(map_ir)
63 %.proc{i}{r} = map_normalize(map_ir);
64 proc{ist}{r} = map_ir;
65 pie{ist}{r} = map_pie(map_ir);
66 else
67 pie{ist}{r} = NaN;
68 end
69 end
70 end
71 self.sn.proc = proc;
72 self.sn.pie = pie;
73 self.sn.phases = phases;
74 self.sn.phasessz = max(self.sn.phases,ones(size(self.sn.phases)));
75 self.sn.phasessz(self.sn.nodeToStation(self.sn.nodetype == NodeType.Join),:)=phases(self.sn.nodeToStation(self.sn.nodetype == NodeType.Join),:);
76 self.sn.phaseshift = [zeros(size(phases,1),1),cumsum(self.sn.phasessz,2)];
77end
78end
79
80function result = isMAP(proc)
81% ISMAP Check if a process representation is a valid MAP {D0, D1}
82%
83% A valid MAP has exactly 2 cell elements, both of which are square matrices
84% of the same size.
85result = false;
86if ~iscell(proc) || length(proc) ~= 2
87 return;
88end
89D0 = proc{1};
90D1 = proc{2};
91if ~isnumeric(D0) || ~isnumeric(D1)
92 return;
93end
94if ~ismatrix(D0) || ~ismatrix(D1)
95 return;
96end
97[m0, n0] = size(D0);
98[m1, n1] = size(D1);
99if m0 ~= n0 || m1 ~= n1 || m0 ~= m1
100 return;
101end
102result = true;
103end
104
105function MAP = convertToMAP(station, classIdx, proc)
106% CONVERTTOMAP Convert non-Markovian distribution parameters to MAP
107%
108% For non-Markovian distributions, the process representation contains
109% distribution parameters rather than {D0, D1} matrices. This function
110% converts them to an Erlang approximation.
111
112% Get the distribution object from the station
113if isa(station, 'Source')
114 dist = station.input.sourceClasses{classIdx}{end};
115else
116 dist = station.server.serviceProcess{classIdx}{end};
117end
118
119% Get mean for Erlang approximation
120targetMean = dist.getMean();
121
122% Determine number of phases based on SCV
123% For Det (SCV=0), use high number of phases; for others, match SCV
124scv = dist.getSCV();
125if scv < GlobalConstants.CoarseTol
126 % Deterministic or near-deterministic: use 20 phases
127 nPhases = 20;
128else
129 % Match SCV: for Erlang, SCV = 1/n, so n = 1/SCV
130 nPhases = max(1, ceil(1/scv));
131 nPhases = min(nPhases, 100); % Cap at 100 phases
132end
133
134% Create Erlang MAP approximation
135MAP = map_erlang(targetMean, nPhases);
136end