LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
refreshCapacity.m
1function [capacity, classcap, droprule] = refreshCapacity(self)
2% [CAPACITY, CLASSCAP, DROPRULE] = REFRESHCAPACITY()
3
4% Copyright (c) 2012-2026, Imperial College London
5% All rights reserved.
6%I = getNumberOfStatefulNodes(self);
7M = getNumberOfStations(self);
8K = getNumberOfClasses(self);
9C = self.sn.nchains;
10% set zero buffers for classes that are disabled
11classcap = Inf*ones(M,K);
12chaincap = Inf*ones(M,K);
13capacity = zeros(M,1);
14droprule = DropStrategy.WAITQ*ones(M,K);
15sn = self.sn;
16njobs = sn.njobs;
17rates = sn.rates;
18% A chain holding a spawn-target class is not population-conserving -- see _kb/04-networkstruct.md
19spawnFedChain = false(1, C);
20for r0 = 1:K
21 if isprop(self.classes{r0}, 'spawnClass') && ~isempty(self.classes{r0}.spawnClass)
22 tIdx = self.classes{r0}.spawnClass.index;
23 for c0 = 1:C
24 if any(sn.inchain{c0} == tIdx)
25 spawnFedChain(c0) = true;
26 end
27 end
28 end
29end
30for c = 1:C
31 inchain = sn.inchain{c};
32 for r = inchain
33 chainCap = sum(njobs(inchain));
34 if spawnFedChain(c)
35 chainCap = Inf;
36 end
37 for ist=1:M
38 station = self.getStationByIndex(ist);
39
40 if sn.nodetype(sn.stationToNode(ist)) ~= NodeType.Source
41 % Guard against dropRule array not having entry for class r; a 0 gap-fill is not a DropStrategy member (WAITQ is -1)
42 if length(station.dropRule) >= r && ~isempty(station.dropRule(r)) ...
43 && station.dropRule(r) ~= 0
44 stationDropRule = station.dropRule(r);
45 else
46 stationDropRule = [];
47 end
48 % Explicit setDropRule(WAITQ) at a finite buffer for an open class is rejected (no solver honours it) -- see _kb/04-networkstruct.md
49 isUserRuleNode = ~isa(station, 'Place') && ~isa(station, 'Join');
50 % classCap(r)==0 is "class absent from station", not a real finite buffer -- must not trip the WAITQ gate below
51 classCapIsFinite = length(station.classCap) >= r ...
52 && station.classCap(r) > 0 && ~isinf(station.classCap(r));
53 stationCapIsFinite = ~isempty(station.cap) && station.cap >= 0 ...
54 && ~isinf(station.cap) && station.cap < intmax;
55 if isUserRuleNode && ~isempty(stationDropRule) && stationDropRule == DropStrategy.WAITQ ...
56 && isinf(njobs(r)) && (stationCapIsFinite || classCapIsFinite)
57 line_error(mfilename, sprintf(['Station ''%s'' declares setDropRule(WAITQ) for the open class ''%s'' at a finite capacity. ' ...
58 'LINE does not implement waiting-room blocking for an open arrival at a plain finite buffer: no solver honours this combination ' ...
59 '(SolverCTMC drops the arrival, SolverJMT blocks at the Source and ignores the capacity). ' ...
60 'Use setDropRule(DropStrategy.DROP) for a loss station (M/M/1/K), or one of the blocking policies LINE implements ' ...
61 '(DropStrategy.BAS, DropStrategy.BBS, DropStrategy.RSRD) for blocking between stations.'], ...
62 station.getName(), self.classes{r}.getName()));
63 end
64 % Derived from the final station capacity so it doesn't depend on setCapacity/setService call order
65 if isempty(stationDropRule)
66 if isinf(station.cap) || station.cap >= intmax
67 % No buffer: the rule is never consulted.
68 stationDropRule = DropStrategy.WAITQ;
69 elseif station.cap >= 0 && ~isinf(njobs(r))
70 % Finite buffer + CLOSED class: WAITQ (the correct default is unsettled across LINE's solvers) -- see _kb/04-networkstruct.md
71 stationDropRule = DropStrategy.WAITQ;
72 else
73 % Finite buffer + OPEN class (or cap<0, JMT's unlimited sentinel): DROP, matching the CTMC reference -- see _kb/04-networkstruct.md
74 stationDropRule = DropStrategy.DROP;
75 end
76 end
77 droprule(ist,r) = stationDropRule;
78 end
79 if isnan(rates(ist,r)) && sn.nodetype(sn.stationToNode(ist)) ~= NodeType.Place
80 classcap(ist,r) = 0;
81 chaincap(ist,c) = 0;
82 else
83 chaincap(ist,c) = chainCap;
84 classcap(ist,r) = chainCap;
85 % Guard against classCap array not having entry for class r
86 if length(station.classCap) >= r && station.classCap(r) >= 0
87 classcap(ist,r) = min(classcap(ist,r), station.classCap(r));
88 end
89 if station.cap >= 0
90 classcap(ist,r) = min(classcap(ist,r), station.cap);
91 end
92 % Finite orbit bounds population at (servers + orbit capacity): a retrial station has no waiting room -- see _kb/04-networkstruct.md
93 if isprop(station,'orbitMaxJobs') && length(station.orbitMaxJobs) >= r ...
94 && station.orbitMaxJobs(r) >= 0
95 nsrv = sn.nservers(ist);
96 if ~isfinite(nsrv)
97 nsrv = 1;
98 end
99 classcap(ist,r) = min(classcap(ist,r), nsrv + station.orbitMaxJobs(r));
100 end
101 end
102 end
103 end
104end
105for ist=1:M
106 station = self.getStationByIndex(ist);
107 % If station has explicit finite cap set, use it directly (Kendall K notation)
108 % Otherwise use minimum of chain cap sum and class cap sum
109 if station.cap >= 0 && ~isinf(station.cap)
110 % Explicit capacity set - use directly as total capacity
111 capacity(ist,1) = station.cap;
112 else
113 capacity(ist,1) = min([sum(chaincap(ist,:)),sum(classcap(ist,:))]);
114 end
115end
116self.sn.cap = capacity;
117self.sn.classcap = classcap;
118self.sn.droprule = droprule;
119end