1classdef Node < NetworkElement
2 % An abstract
for a node in a Network model
4 % Copyright (c) 2012-2026, Imperial College London
17 function self = Node(name)
20 self@NetworkElement(
char(name));
24 function self = setModel(self, model)
25 % SELF = SETMODEL(MODEL)
27 % Add a pointer to the model
object
32 function self = link(self, nodeTo)
37 self.model.addLink(self,nodeTo);
40 function self = reset(self)
43 % Reset internal data structures when the network model
is
51 function sections = getSections(self)
52 % SECTIONS = GETSECTIONS()
54 sections = {self.input, self.server, self.output};
57 function setProbRouting(self,
class, destination, probability)
58 % SETPROBROUTING(CLASS, DESTINATION, PROBABILITY)
60 setRouting(self,
class, RoutingStrategy.PROB, destination, probability);
63 function setRouting(self,
class, strategy, par1, par2)
64 % SETROUTING(CLASS, STRATEGY, PARAM)
65 % SETROUTING(CLASS, STRATEGY, DESTINATION, PROBABILITY)
67 %global GlobalConstants.CoarseTol
69 if self.model.isJavaNative()
70 jline_classes = self.model.obj.getClasses();
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());
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.');
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.');
95 case RoutingStrategy.KCHOICES
100 par2 =
false; % param_memory
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
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};
115 self.output.outputStrategy{1,
class.index}{3}{end+1} = {destination, weight};
118 line_error(mfilename,
'Weighted round robin weights must be integers.')
120 case RoutingStrategy.RL
121 self.output.outputStrategy{1,
class.index}{2} = RoutingStrategy.toText(strategy);
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)
131 case 3 % no destination specified
132 self.output.outputStrategy{1,
class.index}{2} = RoutingStrategy.toText(strategy);
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};
140 self.output.outputStrategy{1,
class.index}{3}{end+1} = {destination, probability};
146 function
bool = hasClassSwitching(self)
147 % BOOL = HASCLASSSWITCHING()
149 bool = isa(self.server,'ClassSwitcher');
152 function
bool = isStateful(self)
153 % BOOL = ISSTATEFUL()
155 bool = isa(self,'StatefulNode');
158 function
bool = isStation(self)
161 bool = isa(self,'Station');
165 methods(Access = protected)
166 % Override copyElement method:
167 function clone = copyElement(self)
168 % CLONE = COPYELEMENT()
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;
179 methods (Access = public)
180 function ind = subsindex(self)
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);
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);
194 ind =
double(node_idx)-1; % 0 based
195 elseif isa(self.model,'JNetwork')
196 ind = self.model.obj.getNodeIndex(self.obj);
198 error('Node:subsindex', 'Unsupported model type: %s', class(self.model));
202 function V = horzcat(self, varargin)
203 % V = HORZCAT(VARARGIN)
205 V = zeros(1, length(varargin) + 1);
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));
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));
219 V(1+v) = 1+ node_idx;
221 error(
'Node:horzcat',
'Element %d is not a Node object', v);
225 error(
'Node:horzcat',
'Error in horizontal concatenation: %s', e.message);
229 function V = vertcat(self, varargin)
230 % V = VERTCAT(VARARGIN)
232 V = zeros(length(varargin) + 1, 1);
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;
239 error(
'Node:vertcat',
'Element %d is not a Node object', v);
243 error(
'Node:vertcat',
'Error in vertical concatenation: %s', e.message);
247 function summary(self)
250 line_printf('\nNode: <strong>%s</strong>',self.getName);
252 % self.server.summary;
253 % self.output.summary;