LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
Activity.m
1classdef Activity < LayeredNetworkElement
2 % A stage of service in a Task of a LayeredNetwork.
3 %
4 % Copyright (c) 2012-2026, Imperial College London
5 % All rights reserved.
6
7 properties
8 hostDemand;
9 hostDemandMean; %double
10 hostDemandSCV; %double
11 parent;
12 parentName; %string
13 boundToEntry; %string
14 callOrder; %string \in {'STOCHASTIC', 'DETERMINISTIC'}
15 syncCallDests = cell(0); %string array
16 syncCallMeans = []; %integer array
17 asyncCallDests = cell(0); %string array
18 asyncCallMeans = []; %integer array
19 scheduling = [];
20 thinkTime; %Distribution object
21 thinkTimeMean; %double
22 thinkTimeSCV; %double
23 end
24
25 methods
26 %public methods, including constructor
27
28 %constructor
29 function obj = Activity(model, name, hostDemand, boundToEntry, callOrder)
30 % OBJ = ACTIVITY(MODEL, NAME, HOSTDEMAND, BOUNDTOENTRY, CALLORDER)
31 name = char(name);
32 if nargin<2 %~exist('name','var')
33 line_error(mfilename,'Constructor requires to specify at least a name.');
34 end
35 obj@LayeredNetworkElement(name);
36
37 if nargin<3 %~exist('hostDemand','var')
38 hostDemand = GlobalConstants.FineTol;
39 elseif isnumeric(hostDemand) && hostDemand == 0
40 hostDemand = GlobalConstants.FineTol;
41 end
42 if nargin<4 %~exist('boundToEntry','var')
43 boundToEntry = '';
44 end
45 if nargin<5 %~exist('callOrder','var')
46 callOrder = 'STOCHASTIC';
47 end
48
49 obj.setHostDemand(hostDemand);
50 obj.boundToEntry = boundToEntry;
51 obj.setCallOrder(callOrder);
52
53 % Initialize default think time
54 obj.thinkTime = Immediate.getInstance();
55 obj.thinkTimeMean = GlobalConstants.FineTol;
56 obj.thinkTimeSCV = GlobalConstants.FineTol;
57
58 if isa(model,'LayeredNetwork')
59 model.activities{end+1} = obj;
60 obj.model = model;
61 elseif isa(model,'JLayeredNetwork')
62 % JLayeredNetwork support would go here if it exists
63 obj.obj = jline.lang.layered.Activity(model.obj, name, hostDemand, boundToEntry, callOrder);
64 model.addActivity(obj);
65 end
66 end
67
68 function obj = setParent(obj, parent)
69 % OBJ = SETPARENT(OBJ, PARENT)
70
71 if isa(parent,'Entry') || isa(parent,'Task')
72 obj.parentName = parent.name;
73 obj.parent = parent;
74 else
75 obj.parentName = parent;
76 obj.parent = [];
77 end
78 end
79
80 function self = on(self, parent)
81 % OBJ = ON(OBJ, PARENT)
82 if ~isa(parent,'Task')
83 line_error(mfilename,'Invalid .on() argument: expected a task.')
84 end
85 if isempty(self.parent)
86 parent.addActivity(self);
87 self.parent = parent;
88 else
89 line_error(mfilename,'Parent task already defined.')
90 end
91 end
92
93 function obj = setHostDemand(obj, hostDemand)
94 % OBJ = SETHOSTDEMAND(OBJ, HOSTDEMAND)
95
96 if isnumeric(hostDemand)
97 if hostDemand <= GlobalConstants.FineTol
98 obj.hostDemand = Immediate.getInstance();
99 obj.hostDemandMean = GlobalConstants.FineTol;
100 obj.hostDemandSCV = GlobalConstants.FineTol;
101 else
102 obj.hostDemand = Exp(1/hostDemand);
103 obj.hostDemandMean = hostDemand;
104 obj.hostDemandSCV = 1.0;
105 end
106 elseif isa(hostDemand,'Distribution')
107 obj.hostDemand = hostDemand;
108 obj.hostDemandMean = hostDemand.getMean();
109 obj.hostDemandSCV = hostDemand.getSCV();
110 end
111 end
112
113 function obj = repliesTo(obj, entry)
114 % OBJ = REPLIESTO(OBJ, ENTRY)
115
116 if ~isempty(obj.parent)
117 switch SchedStrategy.fromText(obj.parent.scheduling)
118 case SchedStrategy.REF
119 line_error(mfilename,'Activities in reference tasks cannot reply.');
120 otherwise
121 entry.replyActivity{end+1} = obj.name;
122 end
123 else
124 entry.replyActivity{end+1} = obj.name;
125 end
126 end
127
128 function obj = boundTo(obj, entry)
129 % OBJ = BOUNDTO(OBJ, ENTRY)
130
131 if isa(entry,'Entry')
132 obj.boundToEntry = entry.name;
133 elseif ischar(entry)
134 obj.boundToEntry = entry;
135 else
136 line_error(mfilename,'Wrong entry parameter for boundTo method.');
137 end
138 end
139
140 function obj = setCallOrder(obj, callOrder)
141 % OBJ = SETCALLORDER(OBJ, CALLORDER)
142
143 if strcmpi(callOrder,'STOCHASTIC') || strcmpi(callOrder,'DETERMINISTIC')
144 obj.callOrder = upper(callOrder);
145 else
146 obj.callOrder = 'STOCHASTIC';
147 end
148 end
149
150 function obj = setThinkTime(obj, thinkTime)
151 % OBJ = SETTHINKTIME(OBJ, THINKTIME)
152
153 if isnumeric(thinkTime)
154 if thinkTime <= GlobalConstants.FineTol
155 obj.thinkTime = Immediate.getInstance();
156 obj.thinkTimeMean = GlobalConstants.FineTol;
157 obj.thinkTimeSCV = GlobalConstants.FineTol;
158 else
159 obj.thinkTime = Exp(1/thinkTime);
160 obj.thinkTimeMean = thinkTime;
161 obj.thinkTimeSCV = 1.0;
162 end
163 elseif isa(thinkTime,'Distribution')
164 obj.thinkTime = thinkTime;
165 obj.thinkTimeMean = thinkTime.getMean();
166 obj.thinkTimeSCV = thinkTime.getSCV();
167 end
168 end
169
170 %synchCall
171
172 function obj = synchCall(obj, synchCallDest, synchCallMean)
173 % OBJ = SYNCHCALL(OBJ, SYNCHCALLDEST, SYNCHCALLMEAN)
174
175 if nargin<3 %~exist('synchCallMean','var')
176 synchCallMean = 1.0;
177 end
178
179 % Get the destination entry name
180 if ischar(synchCallDest)
181 destName = synchCallDest;
182 else % object
183 destName = synchCallDest.name;
184 end
185
186 % Check if this entry is already in the synchronous call destinations
187 if ~isempty(obj.syncCallDests)
188 for i = 1:length(obj.syncCallDests)
189 if strcmp(obj.syncCallDests{i}, destName)
190 error_msg = sprintf('Activity "%s" already has a synchronous call to entry "%s". ', ...
191 obj.name, destName);
192 error_msg = [error_msg, 'If you intend multiple calls, change the mean number of calls using synchCall(entry, mean_calls) or define an activity graph with explicit precedences.'];
193 line_error(mfilename, error_msg);
194 end
195 end
196 end
197
198 % Add the new call destination
199 obj.syncCallDests{length(obj.syncCallDests)+1} = destName;
200 obj.syncCallMeans = [obj.syncCallMeans; synchCallMean];
201 end
202
203 %asynchCall
204 function obj = asynchCall(obj, asynchCallDest, asynchCallMean)
205 % OBJ = ASYNCHCALL(OBJ, ASYNCHCALLDEST, ASYNCHCALLMEAN)
206
207 if nargin<3 %~exist('asynchCallMean','var')
208 asynchCallMean = 1.0;
209 end
210
211 % Get the destination entry name
212 if ischar(asynchCallDest)
213 destName = asynchCallDest;
214 else % object
215 destName = asynchCallDest.name;
216 end
217
218 % Check if this entry is already in the asynchronous call destinations
219 if ~isempty(obj.asyncCallDests)
220 for i = 1:length(obj.asyncCallDests)
221 if strcmp(obj.asyncCallDests{i}, destName)
222 error_msg = sprintf('Activity "%s" already has an asynchronous call to entry "%s". ', ...
223 obj.name, destName);
224 error_msg = [error_msg, 'If you intend multiple calls, change the mean number of calls using asynchCall(entry, mean_calls) or define an activity graph with explicit precedences.'];
225 line_error(mfilename, error_msg);
226 end
227 end
228 end
229
230 % Add the new call destination
231 obj.asyncCallDests{length(obj.asyncCallDests)+1} = destName;
232 obj.asyncCallMeans = [obj.asyncCallMeans; asynchCallMean];
233 end
234
235 end
236
237end