LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
MNetwork.m
1classdef MNetwork < Model
2 % An extended queueing network model.
3 %
4 % Copyright (c) 2012-2026, Imperial College London
5 % All rights reserved.
6
7 properties (Access=private)
8 enableChecks;
9 hasState;
10 logPath;
11 usedFeatures; % structure of booleans listing the used classes
12 % it must be accessed via getUsedLangFeatures that updates
13 % the Distribution classes dynamically
14 end
15
16 properties (Hidden)
17 obj; % empty
18 sn;
19 csMatrix;
20 hasStruct;
21 allowReplace;
22 end
23
24 properties (Hidden)
25 handles;
26 sourceidx; % cached value
27 sinkidx; % cached value
28 end
29
30 properties
31 classes;
32 items;
33 stations;
34 nodes;
35 connections;
36 regions;
37 end
38
39 methods % get methods
40 nodes = getNodes(self)
41 sa = getStruct(self, structType, wantState) % get abritrary representation
42 used = getUsedLangFeatures(self) % get used features
43 ft = getForkJoins(self, rt) % get fork-join pairs
44 [chainsObj,chainsMatrix] = getChains(self, rt) % get chain table
45 [rt,rtNodes,connections,chains,rtNodesByClass,rtNodesByStation] = getRoutingMatrix(self, arvRates) % get routing matrix
46 [Q,U,R,T,A,W] = getAvgHandles(self)
47 Q = getAvgQLenHandles(self);
48 U = getAvgUtilHandles(self);
49 R = getAvgRespTHandles(self);
50 T = getAvgTputHandles(self);
51 A = getAvgArvRHandles(self);
52 W = getAvgResidTHandles(self);
53 [Qt,Ut,Tt] = getTranHandles(self)
54 connections = getConnectionMatrix(self);
55 [absorbingStations, absorbingIdxs] = getAbsorbingStations(self) % get absorbing stations
56 info = getReducibilityInfo(self) % get reducibility analysis
57 end
58
59 methods % ergodicity analysis methods
60 [isErg, info] = isRoutingErgodic(self, P) % check if routing is ergodic
61 P = makeErgodic(self, targetNode) % generate ergodic routing matrix
62 end
63
64 methods % link, reset, refresh methods
65 self = link(self, P)
66 self = relink(self, P)
67 [loggerBefore,loggerAfter] = linkAndLog(self, nodes, classes, P, wantLogger, logPath)
68 sanitize(self);
69
70 reset(self, resetState)
71 resetHandles(self)
72 resetModel(self, resetState)
73 nodes = resetNetwork(self, deleteCSnodes)
74 resetStruct(self)
75
76 refreshStruct(self, hard);
77 [rates, scv, hasRateChanged, hasSCVChanged] = refreshRates(self, statSet, classSet);
78 [ph, mu, phi, phases] = refresProcessPhases(self, statSet, classSet);
79 proctypes = refreshProcessTypes(self);
80 [rt, rtfun, rtnodes] = refreshRoutingMatrix(self, rates);
81 [lt] = refreshLST(self, statSet, classSet);
82 sync = refreshSync(self);
83 classprio = refreshPriorities(self);
84 [sched, schedparam] = refreshScheduling(self);
85 [rates, scv, mu, phi, phases] = refreshProcesses(self, statSet, classSet);
86 [chains, visits, rt] = refreshChains(self, propagate)
87 [cap, classcap] = refreshCapacity(self);
88 nvars = refreshLocalVars(self);
89 end
90
91 % PUBLIC METHODS
92 methods (Access=public)
93
94 %Constructor
95 function self = MNetwork(modelName, varargin)
96 % SELF = NETWORK(MODELNAME)
97 self@Model(modelName);
98 self.nodes = {};
99 self.stations = {};
100 self.classes = {};
101 self.connections = [];
102 initUsedFeatures(self);
103 self.sn = [];
104 self.hasState = false;
105 self.logPath = '';
106 self.items = {};
107 self.regions = {};
108 self.sourceidx = [];
109 self.sinkidx = [];
110 self.setChecks(true);
111 self.hasStruct = false;
112 self.allowReplace = false;
113 end
114
115 setInitialized(self, bool);
116
117 function self = setChecks(self, bool)
118 self.enableChecks = bool;
119 end
120
121 P = getLinkedRoutingMatrix(self)
122
123 function logPath = getLogPath(self)
124 % LOGPATH = GETLOGPATH()
125
126 logPath = self.logPath;
127 end
128
129 function setLogPath(self, logPath)
130 % SETLOGPATH(LOGPATH)
131
132 self.logPath = logPath;
133 end
134
135 bool = hasInitState(self)
136
137 function [M,R] = getSize(self)
138 % [M,R] = GETSIZE()
139
140 M = self.getNumberOfNodes;
141 R = self.getNumberOfClasses;
142 end
143
144 function bool = hasOpenClasses(self)
145 % BOOL = HASOPENCLASSES()
146
147 bool = any(isinf(getNumberOfJobs(self)));
148 end
149
150 function bool = hasClassSwitching(self)
151 % BOOL = HASCLASSSWITCHING()
152
153 bool = any(cellfun(@(c) isa(c,'ClassSwitch'), self.nodes));
154 end
155
156 function bool = hasFork(self)
157 % BOOL = HASFORK()
158
159 bool = any(cellfun(@(c) isa(c,'Fork'), self.nodes));
160 end
161
162 function bool = hasJoin(self)
163 % BOOL = HASJOIN()
164
165 bool = any(cellfun(@(c) isa(c,'Join'), self.nodes));
166 end
167
168 function bool = hasClosedClasses(self)
169 % BOOL = HASCLOSEDCLASSES()
170
171 bool = any(isfinite(getNumberOfJobs(self)));
172 end
173
174 function bool = isMatlabNative(self)
175 % BOOL = ISMATLABNATIVE()
176 %
177 % Returns true for MATLAB native (MNetwork) implementation
178
179 bool = true;
180 end
181
182 function bool = isJavaNative(self)
183 % BOOL = ISJAVANATIVE()
184 %
185 % Returns false for MATLAB native (MNetwork) implementation
186
187 bool = false;
188 end
189
190 function index = getIndexOpenClasses(self)
191 % INDEX = GETINDEXOPENCLASSES()
192
193 index = find(isinf(getNumberOfJobs(self)))';
194 end
195
196 function index = getIndexClosedClasses(self)
197 % INDEX = GETINDEXCLOSEDCLASSES()
198
199 index = find(isfinite(getNumberOfJobs(self)))';
200 end
201
202 function classes = getClasses(self)
203 classes= self.classes;
204 end
205
206 chain = getClassChain(self, className)
207 c = getClassChainIndex(self, className)
208 classNames = getClassNames(self)
209
210 nodeNames = getNodeNames(self)
211 nodeTypes = getNodeTypes(self)
212
213 P = initRoutingMatrix(self)
214
215 ind = getNodeIndex(self, name)
216 lldScaling = getLimitedLoadDependence(self)
217 lcdScaling = getLimitedClassDependence(self)
218
219 function stationIndex = getStationIndex(self, name)
220 % STATIONINDEX = GETSTATIONINDEX(NAME)
221
222 if isa(name,'Node')
223 node = name;
224 name = node.getName();
225 end
226 stationIndex = find(cellfun(@(c) strcmp(c,name),self.getStationNames));
227 end
228
229 function statefulIndex = getStatefulNodeIndex(self, name)
230 % STATEFULINDEX = GETSTATEFULNODEINDEX(NAME)
231
232 if isa(name,'Node')
233 node = name;
234 name = node.getName();
235 end
236 statefulIndex = find(cellfun(@(c) strcmp(c,name),self.getStatefulNodeNames));
237 end
238
239 function classIndex = getClassIndex(self, name)
240 % CLASSINDEX = GETCLASSINDEX(NAME)
241 if isa(name,'JobClass')
242 jobclass = name;
243 name = jobclass.getName();
244 end
245 classIndex = find(cellfun(@(c) strcmp(c,name),self.getClassNames));
246 end
247
248 function stationnames = getStationNames(self)
249 % STATIONNAMES = GETSTATIONNAMES()
250
251 if self.hasStruct
252 nodenames = self.sn.nodenames;
253 isstation = self.sn.isstation;
254 stationnames = {nodenames{isstation}}';
255 else
256 stationnames = {};
257 for i=self.getStationIndexes
258 stationnames{end+1,1} = self.nodes{i}.name;
259 end
260 end
261 end
262
263 function nodes = getNodeByName(self, name)
264 % NODES = GETNODEBYNAME(SELF, NAME)
265 idx = findstring(self.getNodeNames,name);
266 if idx > 0
267 nodes = self.nodes{idx};
268 else
269 nodes = NaN;
270 end
271 end
272
273 function station = getStationByName(self, name)
274 % STATION = GETSTATIONBYNAME(SELF, NAME)
275 idx = findstring(self.getStationNames,name);
276 if idx > 0
277 station = self.stations{idx};
278 else
279 station = NaN;
280 end
281 end
282
283 function class = getClassByName(self, name)
284 % CLASS = GETCLASSBYNAME(SELF, NAME)
285 idx = findstring(self.getClassNames,name);
286 if idx > 0
287 class = self.classes{idx};
288 else
289 class = NaN;
290 end
291 end
292
293 function nodes = getNodeByIndex(self, idx)
294 % NODES = GETNODEBYINDEX(SELF, NAME)
295 if idx > 0
296 nodes = self.nodes{idx};
297 else
298 nodes = NaN;
299 end
300 end
301
302 function station = getStationByIndex(self, idx)
303 % STATION = GETSTATIONBYINDEX(SELF, NAME)
304 if idx > 0
305 station = self.stations{idx};
306 else
307 station = NaN;
308 end
309 end
310
311 function class = getClassByIndex(self, idx)
312 % CLASS = GETCLASSBYINDEX(SELF, NAME)
313 if idx > 0
314 class = self.classes{idx};
315 else
316 class = NaN;
317 end
318 end
319
320 function [infGen, eventFilt, ev] = getGenerator(self, varargin)
321 line_warning(mfilename,'Results will not be cached. Use SolverCTMC(model,...).getGenerator(...) instead.\n');
322 [infGen, eventFilt, ev] = SolverCTMC(self).getGenerator(varargin{:});
323 end
324
325 function [stateSpace,nodeStateSpace] = getStateSpace(self, varargin)
326 line_warning(mfilename,'Results will not be cached. Use SolverCTMC(model,...).getStateSpace(...) instead.\n');
327 [stateSpace,nodeStateSpace] = SolverCTMC(self).getStateSpace(varargin{:});
328 end
329
330 function summary(self)
331 % SUMMARY()
332 for i=1:self.getNumberOfClasses
333 self.classes{i}.summary();
334 if i<self.getNumberOfClasses
335 line_printf('\n');
336 end
337 end
338 for i=1:self.getNumberOfNodes
339 self.nodes{i}.summary();
340 end
341 line_printf('\n<strong>Routing matrix</strong>:');
342 self.printRoutingMatrix
343 line_printf('\n<strong>Product-form parameters</strong>:');
344 [arvRates,servDemands,nJobs,thinkTimes,ldScalings,nServers]= getProductFormParameters(self);
345 line_printf('\nArrival rates: %s',mat2str(arvRates,6));
346 line_printf('\nService demands: %s',mat2str(servDemands,6));
347 line_printf('\nNumber of jobs: %s',mat2str(nJobs));
348 line_printf('\nThink times: %s',mat2str(thinkTimes,6));
349 line_printf('\nLoad-dependent scalings: %s',mat2str(ldScalings,6));
350 line_printf('\nNumber of servers: %s\n',mat2str(nServers));
351 line_printf('\n<strong>Chains</strong>:');
352 end
353
354 function [D,Z] = getDemands(self)
355 % [D,Z]= GETDEMANDS()
356 %
357 % Outputs:
358 % D: service demands
359 % Z: think times
360
361 [~,D,~,Z,~,~] = sn_get_product_form_params(self.getStruct);
362 end
363
364 function [lambda,D,N,Z,mu,S]= getProductFormParameters(self)
365 % [LAMBDA,D,N,Z,MU,S]= GETPRODUCTFORMPARAMETERS()
366 %
367 % Outputs:
368 % LAMBDA: arrival rates for open classes
369 % D: service demands
370 % N: population vector for closed classes
371 % Z: think times
372 % mu: load-dependent rates
373 % S: number of servers
374
375 % mu also returns max(S) elements after population |N| as this is
376 % required by MVALDMX
377
378 [lambda,D,N,Z,mu,S] = sn_get_product_form_params(self.getStruct);
379 end
380
381 function [lambda,D,N,Z,mu,S]= getProductFormChainParameters(self)
382 % [LAMBDA,D,N,Z,MU,S]= GETPRODUCTFORMCHAINPARAMETERS()
383 %
384 % Outputs:
385 % LAMBDA: arrival rates for open classes
386 % D: service demands
387 % N: population vector for closed classes
388 % Z: think times
389 % mu: load-dependent rates
390 % S: number of servers
391
392 % mu also returns max(S) elements after population |N| as this is
393 % required by MVALDMX
394
395 [lambda,D,N,Z,mu,S]= sn_get_product_form_chain_params(self.getStruct);
396 end
397
398 function statefulnodes = getStatefulNodes(self)
399 statefulnodes = {};
400 for i=1:self.getNumberOfNodes
401 if self.nodes{i}.isStateful
402 statefulnodes{end+1,1} = self.nodes{i};
403 end
404 end
405 end
406
407 function statefulnames = getStatefulNodeNames(self)
408 % STATEFULNAMES = GETSTATEFULNODENAMES()
409
410 statefulnames = {};
411 for i=1:self.getNumberOfNodes
412 if self.nodes{i}.isStateful
413 statefulnames{end+1,1} = self.nodes{i}.name;
414 end
415 end
416 end
417
418 function M = getNumberOfNodes(self)
419 % M = GETNUMBEROFNODES()
420
421 M = length(self.nodes);
422 end
423
424 function S = getNumberOfStatefulNodes(self)
425 % S = GETNUMBEROFSTATEFULNODES()
426
427 S = sum(cellisa(self.nodes,'StatefulNode'));
428 end
429
430 function M = getNumberOfStations(self)
431 % M = GETNUMBEROFSTATIONS()
432
433 M = length(self.stations);
434 end
435
436 function R = getNumberOfClasses(self)
437 % R = GETNUMBEROFCLASSES()
438
439 R = length(self.classes);
440 end
441
442 function C = getNumberOfChains(self)
443 % C = GETNUMBEROFCHAINS()
444
445 sn = self.getStruct;
446 C = sn.nchains;
447 end
448
449 function Dchain = getDemandsChain(self)
450 % DCHAIN = GETDEMANDSCHAIN()
451 sn_get_demands_chain(self.getStruct);
452 end
453
454 function self = setUsedLangFeature(self,className)
455 % SELF = SETUSEDLANGFEATURE(SELF,CLASSNAME)
456
457 self.usedFeatures.setTrue(className);
458 end
459
460 %% Add the components to the model
461 addJobClass(self, customerClass);
462 bool = addNode(self, node);
463 fcr = addRegion(self, nodes);
464 addLink(self, nodeA, nodeB);
465 addLinks(self, nodeList);
466 addItemSet(self, itemSet);
467
468 node = getSource(self);
469 node = getSink(self);
470
471 function list = getStationIndexes(self)
472 % LIST = GETSTATIONINDEXES()
473
474 if self.hasStruct
475 list = find(self.sn.isstation)';
476 else
477 % returns the ids of nodes that are stations
478 list = find(cellisa(self.nodes, 'Station'))';
479 end
480 end
481
482 function list = getIndexStatefulNodes(self)
483 % LIST = GETINDEXSTATEFULNODES()
484
485 % returns the ids of nodes that are stations
486 list = find(cellisa(self.nodes, 'StatefulNode'))';
487 end
488
489 index = getIndexSourceStation(self);
490 index = getIndexSourceNode(self);
491 index = getIndexSinkNode(self);
492
493 N = getNumberOfJobs(self);
494 refstat = getReferenceStations(self);
495 refclass = getReferenceClasses(self);
496 sched = getStationScheduling(self);
497 S = getStationServers(self);
498 S = getStatefulServers(self);
499
500 jsimwView(self)
501 jsimgView(self)
502 function view(self)
503 % VIEW() Open the model in JSIMgraph
504 jsimgView(self);
505 end
506
507 function modelView(self)
508 % MODELVIEW() Open the model in ModelVisualizer
509 jnetwork = JLINE.line_to_jline(self);
510 jnetwork.plot();
511 end
512
513 function islld = isLimitedLoadDependent(self)
514 islld = isempty(self.getStruct().lldscaling);
515 end
516
517 function [isvalid] = isStateValid(self)
518 % [ISVALID] = ISSTATEVALID()
519
520 isvalid = sn_is_state_valid(self.getStruct);
521 end
522
523 [state, priorStateSpace, stateSpace] = getState(self) % get initial state
524
525 initFromAvgTableQLen(self, AvgTable)
526 initFromAvgQLen(self, AvgQLen)
527 initDefault(self, nodes)
528
529 initFromMarginal(self, n, options) % n(i,r) : number of jobs of class r in node or station i (autodetected)
530 initFromMarginalAndRunning(self, n, s, options) % n(i,r) : number of jobs of class r in node or station i (autodetected)
531 initFromMarginalAndStarted(self, n, s, options) % n(i,r) : number of jobs of class r in node or station i (autodetected)
532
533 [H,G] = getGraph(self)
534
535 function mask = getClassSwitchingMask(self)
536 % MASK = GETCLASSSWITCHINGMASK()
537
538 mask = self.getStruct.csmask;
539 end
540
541 function printRoutingMatrix(self, onlyclass)
542 % PRINTROUTINGMATRIX()
543 if nargin==1
544 sn_print_routing_matrix(self.getStruct);
545 else
546 sn_print_routing_matrix(self.getStruct, onlyclass);
547 end
548 end
549 end
550
551 % Private methods
552 methods (Access = protected)
553
554 function out = getModelNameExtension(self)
555 % OUT = GETMODELNAMEEXTENSION()
556
557 out = [getModelName(self), ['.', self.fileFormat]];
558 end
559
560 function self = initUsedFeatures(self)
561 % SELF = INITUSEDFEATURES()
562
563 % The list includes all classes but Model and Hidden or
564 % Constant or Abstract or Solvers
565 self.usedFeatures = SolverFeatureSet;
566 end
567 end
568
569 methods(Access = protected)
570 % Override copyElement method:
571 function clone = copyElement(self)
572 % CLONE = COPYELEMENT()
573
574 % Make a shallow copy of all properties
575 clone = copyElement@Copyable(self);
576 % Make a deep copy of each handle
577 for i=1:length(self.classes)
578 clone.classes{i} = self.classes{i}.copy;
579 end
580 % Make a deep copy of each handle
581 for i=1:length(self.nodes)
582 clone.nodes{i} = self.nodes{i}.copy;
583 if isa(clone.nodes{i},'Station')
584 clone.stations{i} = clone.nodes{i};
585 end
586 clone.connections = self.connections;
587 end
588 end
589 end
590
591 methods % wrappers
592 function bool = hasFCFS(self)
593 % BOOL = HASFCFS()
594
595 bool = sn_has_fcfs(self.getStruct);
596 end
597
598 function bool = hasHomogeneousScheduling(self, strategy)
599 % BOOL = HASHOMOGENEOUSSCHEDULING(STRATEGY)
600
601 bool = sn_has_homogeneous_scheduling(self.getStruct, strategy);
602 end
603
604 function bool = hasDPS(self)
605 % BOOL = HASDPS()
606
607 bool = sn_has_dps(self.getStruct);
608 end
609
610 function bool = hasGPS(self)
611 % BOOL = HASGPS()
612
613 bool = sn_has_gps(self.getStruct);
614 end
615
616 function bool = hasINF(self)
617 % BOOL = HASINF()
618
619 bool = sn_has_inf(self.getStruct);
620 end
621
622 function bool = hasPS(self)
623 % BOOL = HASPS()
624
625 bool = sn_has_ps(self.getStruct);
626 end
627
628 function bool = hasSIRO(self)
629 % BOOL = HASSIRO()
630
631 bool = sn_has_siro(self.getStruct);
632 end
633
634 function bool = hasHOL(self)
635 % BOOL = HASHOL()
636
637 bool = sn_has_hol(self.getStruct);
638 end
639
640 function bool = hasLCFS(self)
641 % BOOL = HASLCFS()
642
643 bool = sn_has_lcfs(self.getStruct);
644 end
645
646 function bool = hasLCFSPR(self)
647 % BOOL = HASLCFSPR()
648
649 bool = sn_has_lcfs_pr(self.getStruct);
650 end
651
652 function bool = hasSEPT(self)
653 % BOOL = HASSEPT()
654
655 bool = sn_has_sept(self.getStruct);
656 end
657
658 function bool = hasLEPT(self)
659 % BOOL = HASLEPT()
660
661 bool = sn_has_lept(self.getStruct);
662 end
663
664 function bool = hasSJF(self)
665 % BOOL = HASSJF()
666
667 bool = sn_has_sjf(self.getStruct);
668 end
669
670 function bool = hasLJF(self)
671 % BOOL = HASLJF()
672
673 bool = sn_has_ljf(self.getStruct);
674 end
675
676 function bool = hasMultiClassFCFS(self)
677 % BOOL = HASMULTICLASSFCFS()
678
679 bool = sn_has_multi_class_fcfs(self.getStruct);
680 end
681
682 function bool = hasMultiClassHeterFCFS(self)
683 % BOOL = HASMULTICLASSFCFS()
684
685 bool = sn_has_multi_class_heter_fcfs(self.getStruct);
686 end
687
688 function bool = hasMultiServer(self)
689 % BOOL = HASMULTISERVER()
690
691 bool = sn_has_multi_server(self.getStruct);
692 end
693
694 function bool = hasSingleChain(self)
695 % BOOL = HASSINGLECHAIN()
696
697 bool = sn_has_single_chain(self.getStruct);
698 end
699
700 function bool = hasMultiChain(self)
701 % BOOL = HASMULTICHAIN()
702
703 bool = sn_has_multi_chain(self.getStruct);
704 end
705
706 function bool = hasSingleClass(self)
707 % BOOL = HASSINGLECLASS()
708
709 bool = sn_has_single_class(self.getStruct);
710 end
711
712 function bool = hasMultiClass(self)
713 % BOOL = HASMULTICLASS()
714
715 bool = sn_has_multi_class(self.getStruct);
716 end
717 end
718
719 methods
720 function bool = hasProductFormSolution(self)
721 % BOOL = HASPRODUCTFORMSOLUTION()
722 bool = sn_has_product_form(self.getStruct);
723 end
724
725 function plot(self)
726 % PLOT()
727 [~,H] = self.getGraph;
728 H.Nodes.Name=strrep(H.Nodes.Name,'_','\_');
729 h=plot(H,'EdgeLabel',H.Edges.Weight,'Layout','Layered');
730 highlight(h,self.getNodeTypes==3,'NodeColor','r'); % class-switch nodes
731 end
732
733 function varargout = getMarkedCTMC( varargin )
734 [varargout{1:nargout}] = getCTMC( varargin{:} );
735 end
736
737 function mctmc = getCTMC(self, par1, par2)
738 if nargin<2
739 options = SolverCTMC.defaultOptions;
740 elseif ischar(par1)
741 options = SolverCTMC.defaultOptions;
742 options.(par1) = par2;
743 options.cache = false;
744 elseif isstruct(par1)
745 options = par1;
746 end
747 solver = SolverCTMC(self,options);
748 [infGen, eventFilt, ev] = solver.getInfGen();
749 mctmc = MarkedMarkovProcess(infGen, eventFilt, ev, true);
750 mctmc.setStateSpace(solver.getStateSpace);
751 end
752 end
753
754 methods (Static)
755
756 function model = tandemPs(lambda,D)
757 % MODEL = TANDEMPS(LAMBDA,D)
758
759 model = Network.tandemPsInf(lambda,D,[]);
760 end
761
762 function model = tandemPsInf(lambda,D,Z)
763 % MODEL = TANDEMPSINF(LAMBDA,D,Z)
764
765 if nargin<3%~exist('Z','var')
766 Z = [];
767 end
768 M = size(D,1);
769 Mz = size(Z,1);
770 strategy = {};
771 for i=1:Mz
772 strategy{i} = SchedStrategy.INF;
773 end
774 for i=1:M
775 strategy{Mz+i} = SchedStrategy.PS;
776 end
777 model = Network.tandem(lambda,[Z;D],strategy);
778 end
779
780 function model = tandemFcfs(lambda,D)
781 % MODEL = TANDEMFCFS(LAMBDA,D)
782
783 model = Network.tandemFcfsInf(lambda,D,[]);
784 end
785
786 function model = tandemFcfsInf(lambda,D,Z)
787 % MODEL = TANDEMFCFSINF(LAMBDA,D,Z)
788
789 if nargin<3%~exist('Z','var')
790 Z = [];
791 end
792 M = size(D,1);
793 Mz = size(Z,1);
794 strategy = {};
795 for i=1:Mz
796 strategy{i} = SchedStrategy.INF;
797 end
798 for i=1:M
799 strategy{Mz+i} = SchedStrategy.FCFS;
800 end
801 model = Network.tandem(lambda,[Z;D],strategy);
802 end
803
804 function model = tandem(lambda,D,strategy)
805 % MODEL = TANDEM(LAMBDA,S,STRATEGY)
806
807 % D(i,r) - mean service demand of class r at station i, equal
808 % to mean service time since the topology is linear
809 % lambda(r) - number of jobs of class r
810 % station(i) - scheduling strategy at station i
811 model = Network('Model');
812 [M,R] = size(D);
813 node{1} = Source(model, 'Source');
814 for i=1:M
815 switch SchedStrategy.toId(strategy{i})
816 case SchedStrategy.INF
817 node{end+1} = Delay(model, ['Station',num2str(i)]);
818 otherwise
819 node{end+1} = Queue(model, ['Station',num2str(i)], strategy{i});
820 end
821 end
822 node{end+1} = Sink(model, 'Sink');
823 P = cellzeros(R,R,M+2,M+2);
824 for r=1:R
825 jobclass{r} = OpenClass(model, ['Class',num2str(r)], 0);
826 P{r,r} = circul(length(node)); P{r}(end,:) = 0;
827 end
828 for r=1:R
829 node{1}.setArrival(jobclass{r}, Exp.fitMean(1/lambda(r)));
830 for i=1:M
831 node{1+i}.setService(jobclass{r}, Exp.fitMean(D(i,r)));
832 end
833 end
834 model.link(P);
835 end
836
837 function model = cyclicPs(N,D)
838 % MODEL = CYCLICPS(N,D)
839 M = size(D,1);
840 if nargin<4
841 S = ones(M,1);
842 end
843 model = Network.cyclicPsInf(N,D,[],S);
844 end
845
846 function model = cyclicPsInf(N,D,Z,S)
847 % MODEL = CYCLICPSINF(N,D,Z,S)
848 if nargin<3
849 Z = [];
850 end
851 M = size(D,1);
852 if nargin<4
853 S = ones(M,1);
854 end
855 Mz = size(Z,1);
856 strategy = cell(M+Mz,1);
857 for i=1:Mz
858 strategy{i} = SchedStrategy.INF;
859 end
860 for i=1:M
861 strategy{Mz+i} = SchedStrategy.PS;
862 end
863 model = Network.cyclic(N,[Z;D],strategy,[Inf*ones(size(Z,1),1);S]);
864 end
865
866 function model = cyclicFcfs(N,D,S)
867 % MODEL = CYCLICFCFS(N,D,S)
868 M = size(D,1);
869 if nargin<4
870 S = ones(M,1);
871 end
872 model = Network.cyclicFcfsInf(N,D,[],S);
873 end
874
875 function model = cyclicFcfsInf(N,D,Z,S)
876 % MODEL = CYCLICFCFSINF(N,D,Z,S)
877
878 if nargin<3%~exist('Z','var')
879 Z = [];
880 end
881 M = size(D,1);
882 if nargin<4
883 S = ones(M,1);
884 end
885
886 Mz = size(Z,1);
887 strategy = {};
888 for i=1:Mz
889 strategy{i} = SchedStrategy.INF;
890 end
891 for i=1:M
892 strategy{Mz+i} = SchedStrategy.FCFS;
893 end
894 model = Network.cyclic(N,[Z;D],strategy,[Inf*ones(size(Z,1),1);S]);
895 end
896
897 function model = cyclic(N,D,strategy,S)
898 % MODEL = CYCLIC(N,D,STRATEGY,S)
899
900 % L(i,r) - demand of class r at station i
901 % N(r) - number of jobs of class r
902 % strategy(i) - scheduling strategy at station i
903 % S(i) - number of servers at station i
904 model = Network('Model');
905 [M,R] = size(D);
906 node = cell(M,1);
907 nQ = 0; nD = 0;
908 for ist=1:M
909 switch SchedStrategy.toId(strategy{ist})
910 case SchedStrategy.INF
911 nD = nD + 1;
912 node{ist} = Delay(model, ['Delay',num2str(nD)]);
913 otherwise
914 nQ = nQ + 1;
915 node{ist} = Queue(model, ['Queue',num2str(nQ)], strategy{ist});
916 node{ist}.setNumberOfServers(S(ist));
917 end
918 end
919 P = cellzeros(R,M);
920 jobclass = cell(R,1);
921 for r=1:R
922 jobclass{r} = ClosedClass(model, ['Class',num2str(r)], N(r), node{1}, 0);
923 P{r,r} = circul(M);
924 end
925 for ist=1:M
926 for r=1:R
927 node{ist}.setService(jobclass{r}, Exp.fitMean(D(ist,r)));
928 end
929 end
930 model.link(P);
931 end
932
933 function P = serialRouting(varargin)
934 % P = SERIALROUTING(VARARGIN)
935
936 if length(varargin)==1
937 varargin = varargin{1};
938 end
939 model = varargin{1}.model;
940 P = zeros(model.getNumberOfNodes);
941 for i=1:length(varargin)-1
942 P(varargin{i},varargin{i+1})=1;
943 end
944 if ~isa(varargin{end},'Sink')
945 P(varargin{end},varargin{1})=1;
946 end
947 P = P ./ repmat(sum(P,2),1,length(P));
948 P(isnan(P)) = 0;
949 end
950
951 function printInfGen(Q,SS)
952 % PRINTINFGEN(Q,SS)
953 SolverCTMC.printInfGen(Q,SS);
954 end
955
956 function printEventFilt(sync,D,SS,myevents)
957 % PRINTEVENTFILT(SYNC,D,SS,MYEVENTS)
958 SolverCTMC.printEventFilt(sync,D,SS,myevents);
959 end
960
961 end
962end
Definition mmt.m:92