LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
Place.m
1classdef Place < Station
2 %
3 %
4 % Copyright (c) 2012-2026, Imperial College London
5 % All rights reserved.
6
7 properties
8 schedStrategies;
9 schedStrategy;
10 schedStrategyPar;
11 queueing; % true if this is a queueing place (has an embedded queue)
12 serviceProcess; % per-class service (queue) processes; empty for ordinary places
13 departureDiscipline; % per-class depository departure discipline
14 end
15
16 methods
17 function self = Place(model,name,schedStrategy)
18 % PLACE(MODEL, NAME)
19 % PLACE(MODEL, NAME, SCHEDSTRATEGY)
20 % SCHEDSTRATEGY (optional) turns the place into a queueing place with
21 % an embedded queue served under the given scheduling strategy once a
22 % service process is assigned via setService.
23
24 self@Station(name);
25 if model.isMatlabNative()
26 classes = model.getClasses();
27 self.input = Storage(classes);
28 self.output = Linkage(classes);
29 self.setModel(model);
30 self.model.addNode(self);
31 self.server = ServiceTunnel();
32
33 %numOfClasses = [];
34 % Places have infinite capacity (like delay nodes)
35 self.numberOfServers = Inf;
36 self.schedStrategy = SchedStrategy.INF;
37 self.schedStrategyPar = [];
38
39 self.classCap = [];
40 self.cap = [];
41 self.schedStrategies = [];
42 self.dropRule = [];
43 self.queueing = false;
44 self.serviceProcess = {};
45 self.departureDiscipline = [];
46 elseif model.isJavaNative()
47 self.setModel(model);
48 if nargin>=3 && ~isempty(schedStrategy)
49 self.obj = jline.lang.nodes.Place(model.obj, name, jline.lang.constant.SchedStrategy.fromText(SchedStrategy.toText(schedStrategy)));
50 else
51 self.obj = jline.lang.nodes.Place(model.obj, name);
52 end
53 self.index = model.obj.getNodeIndex(self.obj);
54 end
55 if nargin>=3 && ~isempty(schedStrategy)
56 self.schedStrategy = schedStrategy;
57 end
58 end
59
60 function init(self)
61 numOfClasses = length(self.model.getClasses());
62 % Preserve the embedded-queue scheduling strategy of a queueing
63 % place (set via the constructor); only ordinary places, whose
64 % strategy is nominal, default to FCFS here. Clobbering it would
65 % turn e.g. an infinite-server think place into a single-server
66 % FCFS station on the next refresh.
67 if ~self.queueing
68 self.schedStrategy = SchedStrategy.FCFS;
69 end
70 self.schedStrategyPar = zeros(1,numOfClasses);
71
72 % Preserve a user-configured finite place capacity (setClassCapacity
73 % is called before model.link, which invokes init): a bounded place is
74 % what makes an open Source->Place->Transition net a finite ergodic
75 % CTMC. Only (re)initialize entries the user has not set.
76 if isempty(self.classCap)
77 self.classCap = Inf(1,numOfClasses);
78 elseif length(self.classCap) < numOfClasses
79 tmp = Inf(1,numOfClasses);
80 tmp(1:length(self.classCap)) = self.classCap;
81 self.classCap = tmp;
82 end
83 self.cap = Inf;
84 self.schedStrategies = ones(1, numOfClasses);
85 for r=1:numOfClasses
86 classes = self.model.getClasses();
87 self.dropRule(classes{r}.index) = DropStrategy.WAITQ;
88 end
89 end
90
91 function self = setClassCapacity(self, class, capacity)
92 % SELF = SETCLASSCAPACITY(CLASS, CAPACITY)
93
94 % Resolve a JobClass object to its column index (mirrors Source.m);
95 % indexing classCap by the object itself silently fails to store the
96 % capacity, so the Place stays unbounded and setClassCapacity is a
97 % no-op for the CTMC marking bound.
98 if isa(class, 'JobClass')
99 r = class.index;
100 else
101 r = class;
102 end
103 self.classCap(r) = capacity;
104 end
105
106 function self = setSchedStrategies(self, class, strategy)
107 % SELF = SETSCHEDSTRATEGIES(CLASS, STRATEGY)
108
109 self.schedStrategies(class) = strategy;
110 end
111
112 function setService(self, class, distribution)
113 % SETSERVICE(CLASS, DISTRIBUTION)
114 % Assigns a service process to a token color, turning this ordinary
115 % place into a queueing place. The embedded queue serves tokens under
116 % the place's scheduling strategy; the first such call installs the
117 % concrete server section for that strategy.
118
119 if isa(distribution,'Workflow')
120 distribution = distribution.toPH();
121 end
122 if distribution.isImmediate()
123 distribution = Immediate.getInstance();
124 end
125 if isempty(self.obj)
126 if ~self.queueing
127 self.installQueueServer();
128 self.queueing = true;
129 end
130 c = class.index;
131 self.server.serviceProcess{1, c}{1} = class;
132 self.server.serviceProcess{1, c}{2} = ServiceStrategy.LI;
133 self.server.serviceProcess{1, c}{3} = distribution;
134 self.serviceProcess{c} = distribution;
135 if length(self.departureDiscipline) < c || self.departureDiscipline(c)==0
136 self.departureDiscipline(c) = DepartureDiscipline.NORMAL;
137 end
138 self.model.setInitialized(false);
139 else
140 self.obj.setService(class.obj, distribution.obj);
141 self.serviceProcess{class.index} = distribution;
142 self.queueing = true;
143 end
144 end
145
146 function installQueueServer(self)
147 % INSTALLQUEUESERVER()
148 % Installs the concrete server section matching the place's scheduling
149 % strategy, replacing the default ServiceTunnel used by ordinary places.
150
151 classes = self.model.getClasses();
152 switch SchedStrategy.toId(self.schedStrategy)
153 case SchedStrategy.INF
154 self.server = InfiniteServer(classes);
155 self.numberOfServers = Inf;
156 case {SchedStrategy.PS, SchedStrategy.DPS, SchedStrategy.GPS, SchedStrategy.LPS}
157 self.server = SharedServer(classes);
158 if isinf(self.numberOfServers); self.numberOfServers = 1; end
159 otherwise
160 self.server = Server(classes);
161 if isinf(self.numberOfServers); self.numberOfServers = 1; end
162 end
163 % A queueing place is a station with finite/infinite capacity like a Queue;
164 % initialize cap/classCap (left empty by the ordinary-place constructor).
165 nclasses = length(classes);
166 if isempty(self.cap); self.cap = Inf; end
167 if isempty(self.classCap); self.classCap = Inf(1,nclasses); end
168 if isempty(self.dropRule)
169 for r=1:nclasses
170 self.dropRule(classes{r}.index) = DropStrategy.WAITQ;
171 end
172 end
173 end
174
175 function bool = isQueueing(self)
176 % BOOL = ISQUEUEING()
177 bool = self.queueing;
178 end
179
180 function distribution = getService(self, class)
181 % DISTRIBUTION = GETSERVICE(CLASS)
182 distribution = self.serviceProcess{class.index};
183 end
184
185 function setDepartureDiscipline(self, class, discipline)
186 % SETDEPARTUREDISCIPLINE(CLASS, DISCIPLINE)
187 self.departureDiscipline(class.index) = discipline;
188 if ~isempty(self.obj)
189 self.obj.setDepartureDiscipline(class.obj, jline.lang.constant.DepartureDiscipline.fromID(discipline));
190 end
191 end
192
193 function self = setMarking(self, state)
194 % SELF = SETMARKING(STATE)
195 % Alias for setState using Petri-net terminology: sets the initial
196 % token marking (number of tokens per class) of this place.
197
198 self.setState(state);
199 end
200
201 end
202end
203
Definition fjtag.m:157
Definition Station.m:245