LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
spaceGenerator.m
1function [SS,SSh,sn,Adj,ST] = spaceGenerator(sn, cutoff, options)
2% SPACEGENERATOR Generate complete state space for queueing network analysis
3%
4% @brief Creates the complete state space including all possible network states
5% @param sn Network structure representing the queueing network
6% @param cutoff Population cutoff limits for open classes (scalar or matrix)
7% @param options Optional configuration structure for state generation
8% @return SS Complete state space matrix
9% @return SSh Hashed state space for efficient lookups
10% @return sn Updated network structure with state space information
11% @return Adj Adjacency matrix for state transitions (SPN support)
12% @return ST State transition information (SPN support)
13%
14% The state space generator creates all possible states for the queueing
15% network, including those not reachable from the initial state. This is
16% essential for steady-state analysis and performance metric computation.
17% For open classes, a cutoff parameter limits the maximum population.
18%
19% Copyright (c) 2012-2026, Imperial College London
20% All rights reserved.
21N = sn.njobs';
22Np = N;
23
24% Draft SPN support
25Adj = [];
26ST = [];
27
28%%
29if ~exist('cutoff','var') && any(isinf(Np)) % if the model has open classes
30 line_error(mfilename,'Unspecified cutoff for open classes in state space generator.');
31end
32
33if isscalar(cutoff)
34 cutoff = cutoff * ones(sn.nstations, sn.nclasses);
35end
36
37[~, sn, capacityc] = State.spaceGeneratorNodes(sn, cutoff, options);
38
39%%
40isOpenClass = isinf(Np);
41isClosedClass = ~isOpenClass;
42for r=1:sn.nclasses %cut-off open classes to finite capacity
43 if isOpenClass(r)
44 Np(r) = max(capacityc(:,r)); % if replaced by sum stateMarg_i can exceed capacity
45 end
46end
47
48nstatefulp = sn.nstateful - sum(sn.nodetype == NodeType.Source); % M without sources
49n = pprod(Np);
50chainStationPos=[];
51while n>=0
52 % this is rather inefficient since n ignores chains and thus it can
53 % generate state spaces such as
54 % J =
55 %
56 % 0 0 0 0
57 % 0 0 0 1
58 % 0 0 1 0
59 % 0 1 0 0
60 % 1 0 0 0
61 % 0 0 0 1
62 % 0 0 1 0
63 % 0 1 0 0
64 % 1 0 0 0
65 % 0 0 0 2
66 % 0 0 1 1
67 % 0 0 2 0
68 % 0 1 0 1
69 % 1 0 0 1
70 % 0 1 1 0
71 % 1 0 1 0
72 % 0 2 0 0
73 % 1 1 0 0
74 % 2 0 0 0
75 % that are then in the need for a call to unique
76 if all(isOpenClass) | (Np(isClosedClass) == n(isClosedClass)) %#ok<OR2>
77 chainStationPos = [chainStationPos; State.spaceClosedMultiCS(nstatefulp,n,sn.chains)];
78 end
79 n = pprod(n,Np);
80end
81
82chainStationPos = unique(chainStationPos,'rows');
83
84netstates = cell(size(chainStationPos,1), sn.nstateful);
85for j=1:size(chainStationPos,1)
86 for ind=1:sn.nnodes
87 if sn.nodetype(ind) == NodeType.Source
88 isf = sn.nodeToStateful(ind);
89 state_i = State.fromMarginal(sn,ind,[]);
90 netstates{j,isf} = State.getHash(sn,ind,state_i);
91 elseif sn.isstation(ind)
92 isf = sn.nodeToStateful(ind);
93 stateMarg_i = chainStationPos(j,(isf-sum(sn.nodetype(1:ind-1) == NodeType.Source)):nstatefulp:end);
94 if any(stateMarg_i > capacityc(ind,:))
95 netstates{j,isf} = State.getHash(sn,ind,[]);
96 else
97 state_i = State.fromMarginal(sn,ind,stateMarg_i);
98 netstates{j,isf} = State.getHash(sn,ind,state_i);
99 end
100 elseif sn.isstateful(ind)
101 isf = sn.nodeToStateful(ind);
102 stateMarg_i = chainStationPos(j,(isf-sum(sn.nodetype(1:ind-1) == NodeType.Source)):nstatefulp:end);
103 state_i = sn.space{isf};
104 if any(stateMarg_i > capacityc(ind,:))
105 netstates{j,isf} = State.getHash(sn,ind,[]);
106 elseif sn.nodetype(ind) == NodeType.Cache
107 % For cache nodes, we need to handle states with jobs in multiple classes
108 % (InitClass, HitClass, MissClass) since cache nodes support class switching
109 state_i = state_i(findrows(state_i(:,1:length(stateMarg_i)),stateMarg_i),:);
110 netstates{j,isf} = State.getHash(sn,ind,state_i);
111 else
112 state_i = state_i(findrows(state_i(:,1:length(stateMarg_i)),stateMarg_i),:);
113 netstates{j,isf} = State.getHash(sn,ind,state_i);
114 end
115 end
116 end
117end
118
119ctr = 0;
120%SS = sparse([]);
121SS = [];
122SSh = [];
123for j=1:size(chainStationPos,1)
124 % for each network state
125 v = {netstates{j,:}};
126 % cycle over lattice
127 vN = cellfun(@length,v)-1;
128 n = pprod(vN);
129 while n >=0
130 u={}; h={};
131 skip = false;
132 for isf=1:length(n)
133 h{isf} = v{isf}(1+n(isf));
134 if h{isf} < 0
135 skip = true;
136 break
137 end
138 u{isf} = sn.space{isf}(v{isf}(1+n(isf)),:);
139 end
140 if skip == false
141 ctr = ctr + 1; % do not move
142 SS(ctr,:)=cell2mat(u);
143 SSh(ctr,:)=cell2mat(h);
144 end
145 n = pprod(n,vN);
146 end
147end
148[SS,IA] = unique(SS,'rows');
149SSh = SSh(IA,:);
150end