LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
Node.m
1classdef Node < NetworkElement
2 % An abstract for a node in a Network model
3 %
4 % Copyright (c) 2012-2026, Imperial College London
5 % All rights reserved.
6
7 properties
8 model;
9 input;
10 server;
11 output;
12 index;
13 end
14
15 methods(Hidden)
16 %Constructor
17 function self = Node(name)
18 % SELF = NODE(NAME)
19
20 self@NetworkElement(char(name));
21 self.index = NaN;
22 end
23
24 function self = setModel(self, model)
25 % SELF = SETMODEL(MODEL)
26 %
27 % Add a pointer to the model object
28
29 self.model = model;
30 end
31
32 function self = link(self, nodeTo)
33 % SELF = LINK(NODETO)
34 %
35 %
36
37 self.model.addLink(self,nodeTo);
38 end
39
40 function self = reset(self)
41 % SELF = RESET()
42 %
43 % Reset internal data structures when the network model is
44 % reset
45
46 end
47 end
48
49 methods
50
51 function sections = getSections(self)
52 % SECTIONS = GETSECTIONS()
53
54 sections = {self.input, self.server, self.output};
55 end
56
57 function setProbRouting(self, class, destination, probability)
58 % SETPROBROUTING(CLASS, DESTINATION, PROBABILITY)
59
60 setRouting(self, class, RoutingStrategy.PROB, destination, probability);
61 end
62
63 function setRouting(self, class, strategy, par1, par2)
64 % SETROUTING(CLASS, STRATEGY, PARAM)
65 % SETROUTING(CLASS, STRATEGY, DESTINATION, PROBABILITY)
66
67 %global GlobalConstants.CoarseTol
68
69 if self.model.isJavaNative()
70 jline_classes = self.model.obj.getClasses();
71 switch strategy
72 case RoutingStrategy.RAND
73 self.obj.setRouting(jline_classes.get(class.index-1),jline.lang.constant.RoutingStrategy.RAND);
74 case RoutingStrategy.RROBIN
75 self.obj.setRouting(jline_classes.get(class.index-1),jline.lang.constant.RoutingStrategy.RROBIN);
76 case RoutingStrategy.WRROBIN
77 node_target = self.model.obj.getNodeByName(par1.getName());
78 weight = par2;
79 self.obj.setRouting(jline_classes.get(class.index-1),jline.lang.constant.RoutingStrategy.WRROBIN, node_target, weight);
80 case RoutingStrategy.DISABLED
81 self.obj.setRouting(jline_classes.get(class.index-1),jline.lang.constant.RoutingStrategy.DISABLED);
82 case RoutingStrategy.PROB
83 line_error(mfilename, 'Use setProbRouting to assign routing probabilities for a JNetwork node.');
84 end
85 return
86 end
87
88 if isa(self,'Cache')
89 switch strategy
90 case {RoutingStrategy.KCHOICES, RoutingStrategy.WRROBIN, RoutingStrategy.RROBIN}
91 line_error(mfilename,'State-dependent routing not supported with caches. Add instead a Router node after the cache.');
92 end
93 end
94 switch strategy
95 case RoutingStrategy.KCHOICES
96 if nargin < 4
97 par1 = 2; % param_k
98 end
99 if nargin < 5
100 par2 = false; % param_memory
101 end
102 param_k = par1;
103 param_memory = par2;
104 self.output.outputStrategy{1, class.index}{2} = RoutingStrategy.toText(strategy);
105 self.output.outputStrategy{1, class.index}{3}{1} = param_k;
106 self.output.outputStrategy{1, class.index}{3}{2} = param_memory;
107 case RoutingStrategy.WRROBIN
108 destination = par1;
109 weight = par2;
110 if abs(weight-round(weight)) < GlobalConstants.CoarseTol
111 self.output.outputStrategy{1, class.index}{2} = RoutingStrategy.toText(strategy);
112 if length(self.output.outputStrategy{1, class.index})<3
113 self.output.outputStrategy{1, class.index}{3}{1} = {destination, weight};
114 else
115 self.output.outputStrategy{1, class.index}{3}{end+1} = {destination, weight};
116 end
117 else
118 line_error(mfilename,'Weighted round robin weights must be integers.')
119 end
120 case RoutingStrategy.RL
121 self.output.outputStrategy{1, class.index}{2} = RoutingStrategy.toText(strategy);
122 if nargin < 4
123 par1 = -1;
124 par2 = {-1, -1};
125 end
126 self.output.outputStrategy{1, class.index}{3} = par1; % part1 is value function (tabular or FA)
127 self.output.outputStrategy{1, class.index}{4} = par2{1}; % part2{2} is nodes that need action
128 self.output.outputStrategy{1, class.index}{5} = par2{2}; % part2{2} is state size (truncation_value + 1)
129 otherwise
130 switch nargin
131 case 3 % no destination specified
132 self.output.outputStrategy{1, class.index}{2} = RoutingStrategy.toText(strategy);
133 case 5
134 destination = par1;
135 probability = par2;
136 self.output.outputStrategy{1, class.index}{2} = RoutingStrategy.toText(strategy);
137 if length(self.output.outputStrategy{1, class.index})<3
138 self.output.outputStrategy{1, class.index}{3}{1} = {destination, probability};
139 else
140 self.output.outputStrategy{1, class.index}{3}{end+1} = {destination, probability};
141 end
142 end
143 end
144 end
145
146 function bool = hasClassSwitching(self)
147 % BOOL = HASCLASSSWITCHING()
148
149 bool = isa(self.server,'ClassSwitcher');
150 end
151
152 function bool = isStateful(self)
153 % BOOL = ISSTATEFUL()
154
155 bool = isa(self,'StatefulNode');
156 end
157
158 function bool = isStation(self)
159 % BOOL = ISSTATION()
160
161 bool = isa(self,'Station');
162 end
163 end
164
165 methods(Access = protected)
166 % Override copyElement method:
167 function clone = copyElement(self)
168 % CLONE = COPYELEMENT()
169
170 % Make a shallow copy of all properties
171 clone = copyElement@Copyable(self);
172 % Make a deep copy of each object
173 clone.input = self.input.copy;
174 clone.server = self.server.copy;
175 clone.output = self.output.copy;
176 end
177 end
178
179 methods (Access = public)
180 function ind = subsindex(self)
181 % IND = SUBSINDEX()
182 if isa(self.model,'Network')
183 % Handle the new delegation pattern
184 node_idx = self.model.getNodeIndex(self.name);
185 if isempty(node_idx) || isnan(node_idx) || node_idx <= 0
186 error('Node:subsindex', 'Invalid node index for %s: %g', self.name, node_idx);
187 end
188 ind = double(node_idx)-1; % 0 based for MATLAB indexing
189 elseif isa(self.model,'MNetwork')
190 node_idx = self.model.getNodeIndex(self.name);
191 if isempty(node_idx) || isnan(node_idx) || node_idx <= 0
192 error('Node:subsindex', 'Invalid node index for %s: %g', self.name, node_idx);
193 end
194 ind = double(node_idx)-1; % 0 based
195 elseif isa(self.model,'JNetwork')
196 ind = self.model.obj.getNodeIndex(self.obj);
197 else
198 error('Node:subsindex', 'Unsupported model type: %s', class(self.model));
199 end
200 end
201
202 function V = horzcat(self, varargin)
203 % V = HORZCAT(VARARGIN)
204
205 V = zeros(1, length(varargin) + 1);
206 try
207 self_idx = self.subsindex();
208 if numel(self_idx) ~= 1
209 error('Node:horzcat', 'subsindex returned non-scalar value for %s: %s', self.name, mat2str(self_idx));
210 end
211 V(1) = 1+ self_idx;
212
213 for v=1:length(varargin)
214 if isa(varargin{v}, 'Node')
215 node_idx = varargin{v}.subsindex();
216 if numel(node_idx) ~= 1
217 error('Node:horzcat', 'subsindex returned non-scalar value for %s: %s', varargin{v}.name, mat2str(node_idx));
218 end
219 V(1+v) = 1+ node_idx;
220 else
221 error('Node:horzcat', 'Element %d is not a Node object', v);
222 end
223 end
224 catch e
225 error('Node:horzcat', 'Error in horizontal concatenation: %s', e.message);
226 end
227 end
228
229 function V = vertcat(self, varargin)
230 % V = VERTCAT(VARARGIN)
231
232 V = zeros(length(varargin) + 1, 1);
233 try
234 V(1) = 1+ self.subsindex;
235 for v=1:length(varargin)
236 if isa(varargin{v}, 'Node')
237 V(1+v) = 1+varargin{v}.subsindex;
238 else
239 error('Node:vertcat', 'Element %d is not a Node object', v);
240 end
241 end
242 catch e
243 error('Node:vertcat', 'Error in vertical concatenation: %s', e.message);
244 end
245 end
246
247 function summary(self)
248 % SUMMARY()
249
250 line_printf('\nNode: <strong>%s</strong>',self.getName);
251 %self.input.summary;
252 % self.server.summary;
253 % self.output.summary;
254 end
255 end
256end
Definition mmt.m:92