1classdef JNetwork < Model
2 % JLINE extended queueing network model.
4 % Copyright (c) 2012-2026, Imperial College London
7 properties (Access=
public)
12 methods (Access=public)
15 function self = JNetwork(name)
16 % SELF = NETWORK(MODELNAME)
17 self@Model(name); % model
is the model's name
18 self.obj = jline.lang.Network(name);
21 function sn = getStruct(self, wantInitialState) % get abritrary representation
23 wantInitialState = false;
25 sn = JLINE.from_jline_struct(self.obj, self.obj.getStruct(wantInitialState));
28 function R = getNumberOfClasses(self)
29 % R = GETNUMBEROFCLASSES()
31 R = self.obj.getNumberOfClasses();
34 function M = getNumberOfStations(self)
35 % M = GETNUMBEROFSTATIONS()
37 M = self.obj.getNumberOfStations();
41 function I = getNumberOfNodes(self)
42 % I = GETNUMBEROFNODES()
44 I = self.obj.getNumberOfNodes();
47 function
bool = hasFork(self)
52 function ind = getNodeIndex(self, name)
54 ind = self.obj.getNodeByName(name);
56 ind = self.obj.getNodeIndex(name.obj);
60 function node = getNodeByName(self, name)
61 % NODE = GETNODEBYNAME(NAME)
63 javaNode = self.obj.getNodeByName(name);
67 % Create a wrapper MATLAB
object for the Java node
68 % We need to determine the node type and create appropriate wrapper
69 nodeClassName =
char(javaNode.getClass().getSimpleName());
71 % Create the MATLAB wrapper
object, then override the Java
object
74 node = Queue(self,
char(javaNode.getName()), SchedStrategy.FCFS); % Default schedule strategy
76 node = Source(self,
char(javaNode.getName()));
78 node = Sink(self,
char(javaNode.getName()));
80 node = Router(self,
char(javaNode.getName()));
82 node = Fork(self,
char(javaNode.getName()));
84 node = Join(self,
char(javaNode.getName()));
86 % Cache requires additional parameters, using defaults
87 node = Cache(self,
char(javaNode.getName()), 1, [1], ReplacementStrategy.LRU);
89 node = Logger(self,
char(javaNode.getName()), 'default.log');
91 node = ClassSwitch(self,
char(javaNode.getName()));
93 node = Place(self,
char(javaNode.getName()));
95 node = Transition(self,
char(javaNode.getName()));
97 % Fallback - create generic Node wrapper
98 node = Node(
char(javaNode.getName()));
102 % Override the Java
object with the existing one from the network
104 node.index = self.obj.getNodeIndex(javaNode);
108 function self = link(self,
P)
109 if isa(
P,'jline.lang.RoutingMatrix')
112 nodes = self.obj.getNodes();
113 classes = self.obj.getClasses();
114 routing_matrix = jline.lang.RoutingMatrix(self.obj, classes,
nodes);
115 I = self.obj.getNumberOfNodes;
116 R = self.obj.getNumberOfClasses;
124 routing_matrix.addConnection(
nodes.get(i-1),
nodes.get(j-1), classes.get(r-1), classes.get(s-1),
P{r,s}(i,j));
130 else %
if a single matrix
134 routing_matrix.addConnection(
nodes.get(i-1),
nodes.get(j-1), classes.get(0),
P(i,j));
139 self.obj.link(routing_matrix);
143 function
P = initRoutingMatrix(self)
144 M = self.getNumberOfNodes();
145 R = self.getNumberOfClasses();
146 P = cellzeros(R,R,M,M);
147 P = RoutingMatrix(
P);
150 function self = setChecks(self,
bool)
151 self.obj.setChecks(
bool);
154 function
bool = getChecks(self)
156 % True
if model validation
is enabled on
this model.
157 bool = self.obj.getChecks();
160 function addLinks(self, nodesList)
161 % ADDLINKS(NODESLIST)
163 % Copyright (c) 2012-2026, Imperial College London
164 % All rights reserved.
165 for i=1:size(nodesList,1)
166 self.obj.addLink(self.obj.getNodeByIndex(nodesList(i,1)-1), self.obj.getNodeByIndex(nodesList(i,2)-1));
170 function addLink(self, node1, node2)
173 % Copyright (c) 2012-2026, Imperial College London
174 % All rights reserved.
175 self.obj.addLink(node1.obj, node2.obj);
182 function jsimgView(self)
183 self.obj.jsimgView();
186 % Additional methods for coherence with MNetwork
188 function
nodes = getNodes(self)
190 javaNodes = self.obj.getNodes();
192 for i = 0:javaNodes.size()-1
193 jNode = javaNodes.get(i);
194 nodes{end+1} = self.getNodeByName(
char(jNode.getName()));
198 function classes = getClasses(self)
199 % CLASSES = GETCLASSES()
200 javaClasses = self.obj.getClasses();
202 for i = 0:javaClasses.size()-1
203 jClass = javaClasses.get(i);
204 % Note: Java
object wrapping
for classes not implemented
205 classes{end+1} = jClass;
209 function classNames = getClassNames(self)
210 % CLASSNAMES = GETCLASSNAMES()
211 javaClasses = self.obj.getClasses();
213 for i = 0:javaClasses.size()-1
214 classNames{end+1} = char(javaClasses.get(i).getName());
218 function nodeNames = getNodeNames(self)
219 % NODENAMES = GETNODENAMES()
220 javaNodes = self.obj.getNodes();
222 for i = 0:javaNodes.size()-1
223 nodeNames{end+1} = char(javaNodes.get(i).getName());
227 function nodeTypes = getNodeTypes(self)
228 % NODETYPES = GETNODETYPES()
229 javaNodeTypes = self.obj.getNodeTypes();
231 for i = 0:javaNodeTypes.size()-1
232 nodeTypes{end+1} = char(javaNodeTypes.get(i).toString());
236 function stationNames = getStationNames(self)
237 % STATIONNAMES = GETSTATIONNAMES()
238 % Note: Java
object does not support getStationNames method directly
239 nodes = self.getNodes();
241 for i = 1:length(
nodes)
242 if isa(
nodes{i},
'Station')
243 stationNames{end+1} =
nodes{i}.getName();
248 function stationIndex = getStationIndex(self, name)
249 % STATIONINDEX = GETSTATIONINDEX(NAME)
252 name = node.getName();
254 stationIndex = find(cellfun(@(c) strcmp(c,name),self.getStationNames));
257 function classIndex = getClassIndex(self, name)
258 % CLASSINDEX = GETCLASSINDEX(NAME)
259 if isa(name,'JobClass')
263 classIndex = find(cellfun(@(c) strcmp(c,name),self.getClassNames));
266 function station = getStationByName(self, name)
267 % STATION = GETSTATIONBYNAME(NAME)
268 node = self.getNodeByName(name);
276 function class = getClassByName(self, name)
277 % CLASS = GETCLASSBYNAME(NAME)
278 javaClass = self.obj.getClassByName(name);
279 if isempty(javaClass)
282 % Note: Java
object wrapping for classes not implemented
287 function node = getNodeByIndex(self, idx)
288 % NODE = GETNODEBYINDEX(IDX)
289 javaNode = self.obj.getNodeByIndex(idx-1); % Java uses 0-based indexing
293 node = self.getNodeByName(
char(javaNode.getName()));
297 function station = getStationByIndex(self, idx)
298 % STATION = GETSTATIONBYINDEX(IDX)
299 stations = self.getStationNames();
300 if idx > 0 && idx <= length(stations)
301 station = self.getStationByName(stations{idx});
307 function
class = getClassByIndex(self, idx)
308 % CLASS = GETCLASSBYINDEX(IDX)
309 javaClass = self.obj.getClassByIndex(idx-1); % Java uses 0-based indexing
310 if isempty(javaClass)
313 % Note: Java
object wrapping
for classes not implemented
318 function C = getNumberOfChains(self)
319 % C = GETNUMBEROFCHAINS()
320 sn = self.getStruct();
324 function S = getNumberOfStatefulNodes(self)
325 % S = GETNUMBEROFSTATEFULNODES()
326 % Note: Java
object does not support this method directly
327 nodes = self.getNodes();
328 S = sum(cellfun(@(n) isa(n, 'StatefulNode'),
nodes));
331 function list = getStationIndexes(self)
332 % LIST = GETSTATIONINDEXES()
333 nodes = self.getNodes();
337 function list = getIndexStatefulNodes(self)
338 % LIST = GETINDEXSTATEFULNODES()
339 nodes = self.getNodes();
340 list = find(cellfun(@(n) isa(n, 'StatefulNode'),
nodes))';
343 function index = getIndexSourceStation(self)
344 % INDEX = GETINDEXSOURCESTATION()
345 % Note: Java
object does not support this method directly
346 nodes = self.getNodes();
347 for i = 1:length(
nodes)
348 if isa(
nodes{i},
'Source')
356 function index = getIndexSourceNode(self)
357 % INDEX = GETINDEXSOURCENODE()
358 % Note: Java
object does not support
this method directly
359 nodes = self.getNodes();
360 for i = 1:length(
nodes)
361 if isa(
nodes{i},
'Source')
369 function index = getIndexSinkNode(self)
370 % INDEX = GETINDEXSINKNODE()
371 % Note: Java
object does not support
this method directly
372 nodes = self.getNodes();
373 for i = 1:length(
nodes)
374 if isa(
nodes{i},
'Sink')
382 function node = getSource(self)
384 idx = self.getIndexSourceNode();
386 node = self.getNodeByIndex(idx);
392 function node = getSink(self)
394 idx = self.getIndexSinkNode();
396 node = self.getNodeByIndex(idx);
402 function N = getNumberOfJobs(self)
403 % N = GETNUMBEROFJOBS()
404 javaClasses = self.obj.getClasses();
405 N = zeros(1, javaClasses.size());
406 for i = 0:javaClasses.size()-1
407 jClass = javaClasses.get(i);
408 if strcmp(
char(jClass.getClass().getSimpleName()), 'ClosedClass')
409 N(i+1) = jClass.getPopulation();
416 function
bool = hasOpenClasses(self)
417 % BOOL = HASOPENCLASSES()
418 N = self.getNumberOfJobs();
419 bool = any(isinf(N));
422 function
bool = hasClosedClasses(self)
423 % BOOL = HASCLOSEDCLASSES()
424 N = self.getNumberOfJobs();
425 bool = any(isfinite(N));
428 function
bool = isMatlabNative(self)
429 % BOOL = ISMATLABNATIVE()
431 % Returns false for Java (JNetwork) implementation
436 function
bool = isJavaNative(self)
437 % BOOL = ISJAVANATIVE()
439 % Returns true for Java (JNetwork) implementation
444 function index = getIndexOpenClasses(self)
445 % INDEX = GETINDEXOPENCLASSES()
446 N = self.getNumberOfJobs();
447 index = find(isinf(N))';
450 function index = getIndexClosedClasses(self)
451 % INDEX = GETINDEXCLOSEDCLASSES()
452 N = self.getNumberOfJobs();
453 index = find(isfinite(N))';
456 function
bool = hasClassSwitching(self)
457 % BOOL = HASCLASSSWITCHING()
458 nodes = self.getNodes();
459 bool = any(cellfun(@(n) isa(n,'ClassSwitch'),
nodes));
462 function
bool = hasJoin(self)
464 nodes = self.getNodes();
465 bool = any(cellfun(@(n) isa(n,'Join'),
nodes));
468 function [M,R] = getSize(self)
470 M = self.getNumberOfNodes();
471 R = self.getNumberOfClasses();
474 function used = getUsedLangFeatures(self)
475 % USED = GETUSEDLANGFEATURES()
476 javaFeatureSet = self.obj.getUsedLangFeatures();
478 % Convert Java FeatureSet to MATLAB struct
479 % Note: This
is a simplified conversion - may need refinement
480 % based on the actual FeatureSet structure
483 % If the Java FeatureSet has accessible fields/methods,
484 % we would convert them here. For now, return the Java
object
485 % This may need custom conversion logic depending on FeatureSet implementation
487 % Attempt to get feature names if FeatureSet has such methods
488 % This
is a placeholder - actual implementation depends on FeatureSet API
489 used = javaFeatureSet;
491 % Fallback - create empty struct
496 function summary(self)
501 function [D,Z] = getDemands(self)
502 % [D,Z] = GETDEMANDS()
503 ret = self.obj.getDemands();
504 D = JLINE.from_jline_matrix(ret.D);
505 Z = JLINE.from_jline_matrix(ret.Z);
508 function [lambda,D,N,Z,mu,S] = getProductFormParameters(self)
509 % [LAMBDA,D,N,Z,MU,S] = GETPRODUCTFORMPARAMETERS()
510 ret = self.obj.getProductFormParameters();
511 lambda = JLINE.from_jline_matrix(ret.lambda);
512 D = JLINE.from_jline_matrix(ret.D);
513 N = JLINE.from_jline_matrix(ret.N);
514 Z = JLINE.from_jline_matrix(ret.Z);
515 mu = JLINE.from_jline_matrix(ret.mu);
516 S = JLINE.from_jline_matrix(ret.S);
519 function printRoutingMatrix(self, onlyclass)
520 % PRINTROUTINGMATRIX(ONLYCLASS)
521 self.obj.printRoutingMatrix();
524 function [rt,rtNodes,connections,chains,rtNodesByClass,rtNodesByStation] = getRoutingMatrix(self, arvRates)
525 % [
RT,RTNODES,CONNECTIONS,CHAINS,RTNODEBYCLASS,RTNODEBYSTATION] = GETROUTINGMATRIX(ARVRATES)
526 % Note: Java
object does not support this method directly
527 error('getRoutingMatrix method not supported by Java
object');
530 function
P = getLinkedRoutingMatrix(self)
531 %
P = GETLINKEDROUTINGMATRIX()
532 javaP = self.obj.getLinkedRoutingMatrix();
533 % Convert Java Map<JobClass, Map<JobClass, Matrix>> to MATLAB cell array
535 % Note: This
is a complex conversion - simplified implementation
536 % May need custom conversion logic based on how MATLAB expects
this data
537 P = javaP; % Direct
return for now - may need refinement
540 function connections = getConnectionMatrix(self)
541 % CONNECTIONS = GETCONNECTIONMATRIX()
542 javaConnections = self.obj.getConnectionMatrix();
543 connections = JLINE.from_jline_matrix(javaConnections);
546 function mask = getClassSwitchingMask(self)
547 % MASK = GETCLASSSWITCHINGMASK()
548 javaMask = self.obj.getClassSwitchingMask();
549 mask = JLINE.from_jline_matrix(javaMask);
552 function
bool = hasProductFormSolution(self)
553 % BOOL = HASPRODUCTFORMSOLUTION()
554 bool = self.obj.hasProductFormSolution();
558 % PLOT() - Display network as TikZ diagram in PDF viewer
559 % Requires pdflatex to be installed on the system
563 function jsimwView(self)
565 self.obj.jsimwView();
569 % VIEW() Open the model in JSIMgraph
573 function modelView(self)
574 % MODELVIEW() Open the model in ModelVisualizer
578 % Save methods (for consistency with MNetwork/SolverJMT)
579 function saveAsJSIM(self, filename)
580 % SAVEASJSIM(FILENAME)
581 % Note: Java
object does not support direct JSIM export
582 error('saveAsJSIM method not supported by Java
object. Use SolverJMT for JSIM export.');
585 function saveAsJMVA(self, filename)
586 % SAVEASJMVA(FILENAME)
587 % Note: Java
object does not support direct JMVA export
588 error('saveAsJMVA method not supported by Java
object. Use SolverJMT for JMVA export.');
596 function model = tandemPs(lambda, D, S)
597 lambda = JLINE.from_line_matrix(lambda);
598 D = JLINE.from_line_matrix(D);
599 S = JLINE.from_line_matrix(S);
600 model = jline.lang.Network.tandemPs(lambda, D, S);
601 model = JNetwork(model);
604 function model = tandemPsInf(varargin)
605 lambda = JLINE.from_line_matrix(varargin{1});
606 D = JLINE.from_line_matrix(varargin{2});
608 model = jline.lang.Network.tandemPsInf(lambda, D);
610 Z = JLINE.from_line_matrix(varargin{3});
611 model = jline.lang.Network.tandemPsInf(lambda, D, Z);
613 Z = JLINE.from_line_matrix(varargin{3});
614 S = JLINE.from_line_matrix(varargin{4});
615 model = jline.lang.Network.tandemPsInf(lambda, D, Z, S);
617 error(
'Invalid number of arguments for tandemPsInf.');
619 model = JNetwork(model);
622 function model = tandemFcfs(varargin)
623 lambda = JLINE.from_line_matrix(varargin{1});
624 D = JLINE.from_line_matrix(varargin{2});
625 S = JLINE.from_line_matrix(varargin{3});
626 model = jline.lang.Network.tandemFcfs(lambda, D, S);
627 model = JNetwork(model);
630 function model = tandemFcfsInf(varargin)
631 lambda = JLINE.from_line_matrix(varargin{1});
632 D = JLINE.from_line_matrix(varargin{2});
634 model = jline.lang.Network.tandemFcfsInf(lambda, D);
636 Z = JLINE.from_line_matrix(varargin{3});
637 model = jline.lang.Network.tandemFcfsInf(lambda, D, Z);
639 Z = JLINE.from_line_matrix(varargin{3});
640 S = JLINE.from_line_matrix(varargin{4});
641 model = jline.lang.Network.tandemFcfsInf(lambda, D, Z, S);
643 error(
'Invalid number of arguments for tandemFcfsInf.');
645 model = JNetwork(model);
648 function model = tandem(lambda, D, strategy, S)
649 lambda = JLINE.from_line_matrix(lambda);
650 D = JLINE.from_line_matrix(D);
651 S = JLINE.from_line_matrix(S);
652 model = jline.lang.Network.tandem(lambda, D, strategy, S);
653 model = JNetwork(model);
656 function model = cyclicPs(varargin)
657 N = JLINE.from_line_matrix(varargin{1});
658 D = JLINE.from_line_matrix(varargin{2});
660 model = jline.lang.Network.cyclicPs(N, D);
662 S = JLINE.from_line_matrix(varargin{3});
663 model = jline.lang.Network.cyclicPs(N, D, S);
665 error(
'Invalid number of arguments for cyclicPs.');
667 model = JNetwork(model);
670 function model = cyclicFcfs(varargin)
671 N = JLINE.from_line_matrix(varargin{1});
672 D = JLINE.from_line_matrix(varargin{2});
674 model = jline.lang.Network.cyclicFcfs(N, D);
676 S = JLINE.from_line_matrix(varargin{3});
677 model = jline.lang.Network.cyclicFcfs(N, D, S);
679 error(
'Invalid number of arguments for cyclicFcfs.');
681 model = JNetwork(model);
684 function model = cyclicPsInf(varargin)
685 N = JLINE.from_line_matrix(varargin{1});
686 D = JLINE.from_line_matrix(varargin{2});
687 Z = JLINE.from_line_matrix(varargin{3});
689 model = jline.lang.Network.cyclicPsInf(N, D, Z);
691 S = JLINE.from_line_matrix(varargin{4});
692 model = jline.lang.Network.cyclicPsInf(N, D, Z, S);
694 error(
'Invalid number of arguments for cyclicPsInf.');
696 model = JNetwork(model);
699 function model = cyclicFcfsInf(varargin)
700 N = JLINE.from_line_matrix(varargin{1});
701 D = JLINE.from_line_matrix(varargin{2});
702 Z = JLINE.from_line_matrix(varargin{3});
704 model = jline.lang.Network.cyclicFcfsInf(N, D, Z);
706 S = JLINE.from_line_matrix(varargin{4});
707 model = jline.lang.Network.cyclicFcfsInf(N, D, Z, S);
709 error(
'Invalid number of arguments for cyclicFcfsInf.');
711 model = JNetwork(model);
714 function model = cyclic(N, D, strategy, S)
715 N = JLINE.from_line_matrix(N);
716 D = JLINE.from_line_matrix(D);
717 S = JLINE.from_line_matrix(S);
718 model = jline.lang.Network.cyclic(N, D, strategy, S);
719 model = JNetwork(model);
722 function
P = serialRouting(varargin)
723 if nargin == 1 && iscell(varargin{1})
724 % Case: serialRouting(List<Node>)
726 P = jline.lang.Network.serialRouting(
nodes);
728 elseif nargin == 1 && isa(varargin{1},
'Node')
729 % Case: serialRouting(Node...)
730 nodeObjs = cellfun(@(n) n.obj, varargin,
'UniformOutput', false);
731 P = jline.lang.Network.serialRouting(nodeObjs);
736 if isa(a,
'JobClass') && iscell(b)
737 % Case: serialRouting(JobClass, List<Node>)
738 P = jline.lang.Network.serialRouting(a.obj, b);
740 elseif isa(a,
'JobClass') && all(cellfun(@(x) isa(x,
'Node'), b))
741 % Case: serialRouting(JobClass, Node...)
742 nodeObjs = cellfun(@(n) n.obj, b, 'UniformOutput', false);
743 P = jline.lang.Network.serialRouting(a.obj, nodeObjs);
745 elseif iscell(a) && iscell(b)
746 % Case: serialRouting(List<JobClass>, List<Node>)
747 P = jline.lang.Network.serialRouting(a, b);
750 error('Unsupported serialRouting input pattern.');
753 elseif nargin >= 2 && isa(varargin{1},
'JobClass')
754 jobClass = varargin{1};
755 nodes = varargin(2:end);
756 nodeObjs = cellfun(@(n) n.obj,
nodes,
'UniformOutput',
false);
757 P = jline.lang.Network.serialRouting(jobClass.obj, nodeObjs);
759 elseif nargin >= 2 && all(cellfun(@(x) isa(x,
'Node'), varargin))
760 % Generic
case: serialRouting(Node1, Node2, ..., NodeN)
761 nodeObjs = cellfun(@(n) n.obj, varargin,
'UniformOutput',
false);
762 P = jline.lang.Network.serialRouting([nodeObjs{:}]);
764 elseif nargin == 2 && iscell(varargin{1}) && iscell(varargin{2})
765 % Possibly a fallback
for serialRouting(jobClasses,
nodes)
766 P = jline.lang.Network.serialRouting(varargin{1}, varargin{2});
769 error(
'Invalid arguments to serialRouting.');